Fork of my original MQTTGateway

Dependencies:   mbed-http

Files at this revision

API Documentation at this revision

Comitter:
vpcola
Date:
Sat Apr 08 14:43:14 2017 +0000
Commit message:
Initial commit

Changed in this revision

DownloadFile.cpp Show annotated file Show diff for this revision Revisions of this file
DownloadFile.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/FP/FP.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTConnect.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTConnectClient.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTConnectServer.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTDeserializePublish.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTPacket.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTPacket.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTPublish.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTSerializePublish.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTSubscribe.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTSubscribeClient.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTSubscribeServer.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTUnsubscribe.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTUnsubscribeClient.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/MQTTUnsubscribeServer.c Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/StackTrace.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/samples/publish-subscribe.txt Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/samples/simple-publish.txt Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTPacket/test/test1.txt Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTSManager.cpp Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTSManager.h Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTThreadedClient.cpp Show annotated file Show diff for this revision Revisions of this file
MQTTSManager/MQTTThreadedClient.h Show annotated file Show diff for this revision Revisions of this file
NTPClient/NTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
NTPClient/NTPClient.h Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
Sensor.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/802_Frames.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/802_Frames.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/ApiFrame.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/ApiFrame.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/AtCmdFrame.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/AtCmdFrame.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IO.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSample802.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSample802.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSampleDM.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSampleDM.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSampleZB.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/IO/IOSampleZB.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Utils/Debug.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Utils/Utils.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/Utils/Utils.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/Addresses.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/AtCommands.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/RadioConfig.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/XBee.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee/XBee.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee802/XBee802.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBee802/XBee802.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeDM/XBeeDM.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeDM/XBeeDM.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeLib.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeZB/XBeeZB.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XBeeLib/XBeeZB/XBeeZB.h Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XbeeMonitor.cpp Show annotated file Show diff for this revision Revisions of this file
XbeeMonitor/XbeeMonitor.h Show annotated file Show diff for this revision Revisions of this file
config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/COMMIT_EDITMSG Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/08/9aa4faf066ddefa6bc0d01299ed49bd71084d1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/0c/5ae545f0b266388e47de8bd706c786d485c072 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/0c/77697463c204aa53467a8b7c6286c31b973792 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/0d/c426db510ec4f4c73bc14a75a9de181dae6868 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/0e/924fc9504c5fc4425adf30f7ad85a9fe0bf4fd Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/10/0eb67f6eeb7460798f95f873ddcae32a8351fb Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/15/3045d3887fcebc76e82914138658e28909cc27 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/15/a293e5d2fffb7c16297ca58e726ad492b7bf34 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/19/f6f960eb5519fcdb734d9a2e80410f647d04b5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/1b/01547f94c5552694a1930da954b2b7e8da1b0e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/1b/44cc5b9087fa700d29a7f1db48931b6300c35e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/1d/8ffaa66c2d016d8c178199016ebe139856747e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/22/0970a75eb458de640e38c7e828b2ba8df91609 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/24/d353af5e8cdcaccc11029ab3e8434a197429fa Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/25/b70564bc258cd7587f910879cb94645229170e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/2f/55ecfeb118a73bf8bb60ab39e41056ea7c6d0f Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/30/1381a684281af9da36a455d57477d9a390a445 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/32/57c0301a578f652c3b0657cbdcf0250cdc5e9c Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/34/54ed73977760f2225f2b0b270ef1dbaf4803d7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/37/93db5dfd5198501ebc68ecc7f0504a349f94a5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/39/5e3cd97d052c82c51bd63616ea0c4085f45b8b Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/3a/1c91cf64d117ae96314093920547c11ed4d383 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/3a/5abc3fe130697448aca19177aa3f16f7004c62 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/3b/a9f999525e8f002c7cf5287ecae64a0aeec4e1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/3e/fe7f33ae0768cec61cd9d6548100ffb4410a72 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/42/4ae3367662881a6b866594e66388dfbe52d0bb Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/43/f40bcc5c52a70f4103a1bacd35f7174fdac8f7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/45/cfc786f2e75ef5309c2854805d6d2ce80099a8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/49/1a3bac7f0f38ea74c31da2aa2526caee85b279 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/4a/b5b17c065d256e2debf9d2e3b637e87d70026e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/4f/9a5e30a4f3874754a919746b617c053e8b4d92 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/4f/c50217275c7fba4d8fd73bce2c8b3ea0b361a3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/53/8e08c93dcc43b769d6a726f9072ace0aeb8bd4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/53/8fa834d808c87aafad8d80127152d3239a31dc Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/57/4b1793787ca4916a0c612b5ddef4e15489288a Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/57/cea69ad98a66e7ef1417aea9335b2f00d71116 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/59/3b4d82760aae5f2917c5ffbcb402dff05271e5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/5a/733bd2750342660d9021bfc9b3583ca8c62668 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/5b/9cb8cea4a11b0ab974c991b527c9b79fceae75 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/5d/3d0e811967c9c6f33a710aa076e8b8b77defcf Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/5e/4887274fd6836189c01b70e285f277611f5f3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/61/9c1c17362546bdf3353a800c11f233a7b72667 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/63/bda56ba519dff1fbe82947624c4c4bada62a9d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/67/2acbfe9df9289ca9fb342ab410b8d5493c5b3a Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/67/d50bbba064b284ec7710e217f0f689c4ed1d78 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/67/db7cbdf804b235c8d3dc51ad5663de67de16ac Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/68/ee82789079b8a48165e7e6e5066b5d1005eed3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/6e/09ffca24c3167f6f723c486d8f1081812cc556 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/6f/b5842becaefd360f57916a587b5a0ffdc45ff0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/70/e399a0adb32a4e02d3f2056fe7d9ae31d57642 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/72/3542653307ea78efb2d8b91fc1f69e6d567574 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/73/2661d17a0fae8c97f0be83b806fee80a3747ea Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/7a/3ee2bd184ca8dc4d8c49a4522b41a7b89f8d66 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/81/9375ab99e86e6efad0037fb9cff4e6af7223a8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/83/d2cd6dc0dd26e72cda79e89b289b29a66c7988 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/84/1ff5b5ec24ff027d27a6310cedfb6155556544 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/86/e02b59351d6a9a0d7e24bf4f70d3ab0f4c5b20 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/89/60c27a28435820cca76958a2d83008022b0a3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/89/a75a6da3be993d2e5aa3c7d0319cd6fab45824 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/91/1f2ef98edaac9b09407b5c318591a923d1a784 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/91/dc650f5ab8eaf00b5aca3385e5c9ede505cfd4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/93/1a0a5600917e7417b35ac2e4f25943fb930b98 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/93/8f7f2f726027ab3fda9c83e6934898816a0579 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/9d/233c35352ff61aa11ad4c818e901e0306934e0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/9f/567936d77b8c2bbd7ea5098c468d8f3358d310 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/a0/45def3617364e04e5654c512d863108ee699f0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/a2/483c9ba7dcaefc56b311488e530f376dfcc521 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/a8/31423401dcec34451fc60dd3cb52d4b6bc210e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/a9/13964341394430cd3997c6f2950f93ba1d75c8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ab/96de702ba89e0ca322756726404ea6f96558e4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ae/123517e7c3743ef983ad88f9da3d7808930da2 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ae/9cc8adaa8fbb00061c04cd3c24055043c0489b Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/b8/9589db944f6c58d39808147f6749c0a96a0cc2 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/b9/34a4600d3166ffc8b7359c3d5478b07040701a Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/bb/44bf51b776018d2ae3ea4e2e3aa380eed15e31 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/c2/b63f8793187dfd8e4264149540e21fccb12b9a Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/c8/e294486870313e4d4daa7d7a0b76e4a79af386 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/c9/352112681d09e7af0fc996552c7e7d1656edca Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/cb/933fb19cda0a733a64d6b71d271fb6bdaf9e6d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ce/6cb88c4d7c1a85d8b00c0ccf9fba76ccf5d7d6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ce/95fc4ab9f28413df4d1fa2e30c13d62c468d54 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ce/a47621759ff67ffa4b191809c364943f9db1f3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d1/85bc59084cd7da4ea47470add793b304569c3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d2/6ab233dacac50f47ece4493b16311d45e1bb58 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d3/503403331d10000e1d061fe189c17f215d4e89 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d3/ab1936ef685518aeb35cf67e31465cffb25021 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d5/964336e2d7f627d0706902ad22acbf00bdcc50 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/d5/ab2018616c4823c472bd3b71698eb00437383d Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/dd/245e4b056ea2e4001e97e3bb329307e2da7adc Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e2/c6d1de117c2917df101208c066337e50fde2e5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e3/8c0cbab2fadf0f00c34eef2b4e593cdfa0f9f6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e5/119192cfc8c687fec99ab9c9c9fe8dca954524 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e6/1ba698f31f71693451e91f68bb2035706695b7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e7/925a2477ce8f61e73235ff25725b55046840c9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/e8/b993a80e25977e8b2184415f6e8da1718c7a5e Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/ef/6c33a08523753da6a63b2818aba5b7d7d46ca1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/f5/6d654e0cc15325c291c707e0e13edbc1fb947f Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/f7/7df055e7907a3d9d3c4d77a578c0980d6b1466 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/fb/cc0ac33e944eb71feb80a1c40bf1baf5b2b61f Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/fb/eec5274508773d0f37c6893e794accf39e32f1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/objects/fc/c6be1d2b7c64f0c2232d7559cd5e49bcb45171 Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/.gitignore Show annotated file Show diff for this revision Revisions of this file
easy-connect/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/.msub Show annotated file Show diff for this revision Revisions of this file
easy-connect/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/objects/pack/pack-cb9e3e95d81b3cf553d3174ae4ccbca538c03c13.idx Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/objects/pack/pack-cb9e3e95d81b3cf553d3174ae4ccbca538c03c13.pack Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.gitignore Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/LICENSE Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/module.json Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/source/AT86RFReg.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/source/at24mac.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/atmel-rf-driver/source/at24mac.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/easy-connect.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/07/bcb9b245abc132562d04eda40e8a19f1597603 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/09/3cbfaa677ad0f1a8b2e9e71e5eb3c9b59e5c6c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/16/80c8292e1addcea4defbe1d2469c4106964e89 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/18/7bb094d5f1910589e4bd343db0ce1fa0868c5f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/19/6587025cf513267b3951ed7ae861f6b5887854 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/19/99dae3ef80f9c4cb363ee01d9696dca1e4ad61 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/1c/f9de7a21e429683d2eb0b66fe432ed62076940 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/1d/a853686baeb82ad49a3096a35a6039e3784d0f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/1f/ebc6b296641ca1db45adc9dbeb6cd07a0c826f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/1f/fb7d341d8e640475216fbe547a27a414b6da8c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/22/3dd241b1fc8f44dd138118cf6fec74cd1a9bc0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/28/42cffee5a2e5ced2dd2be10ebef3706f615b42 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/29/cc547a20c724f7bc42b054348b67bbeaed6b19 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/29/d63ae2ee0a233e2fbd9577cdddc7661bb783d1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2b/043ceb297fac4e61b9692b067dc0aa687e908e Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2b/ac3dde128ea49dfedcf71a634d278a4d183721 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2c/b42275ecb72337156ccc82bd4b294c76478cc8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2d/4c36ef2e6528e1c8327babe5bedd834d6e558d Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/2e/9e58d448e915e171348d6fcc3881e007359e87 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/35/4b47b19c9e48a6d2cc99bfb84838355ff8e59b Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/36/dcaec219088ae255ccd1b63a6bd213ea08b43a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/37/084b5e2bef8a8997323b0afb3d664c5143a7ed Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/3b/6d076031a93285f075bf9342b24b64db0e6082 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/40/050a429b64dacc27067d0c6f5ec1aa9858cedd Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/45/0cc128865ffb90b5cbfe5af193621644024fa7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/4a/3f18ae22a0402db6001e0b2145f79693c66a7f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/4e/d87bf7fe37d5ba0de6c4e78868f604a82f8ecb Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/58/8eb441e386da562bc0b29358186a0414b2eb21 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/58/e9a0ed3ecc7e05ddf9578c6153c2a4882e8484 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/60/7744089602deb46784e2f5d7bd815837f65a1f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/63/6af254ddfee68e83cd550e5184e253efa469a0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/63/da515ed94f2f08c3adf90b51458c4891e61347 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/69/aa3c94dc3fbc0fa13e539c0e958d787d17c8a6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/6f/c14e3cc6a40c322c8e5c4d8a2e9da552537027 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/71/cc5953f21d106855490b4ff1b08472472c3a3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/72/02907f786dec6fedf5618a1df556ebf15679c1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/74/b05f50b0d7e5e40753dceb5b55f44776572277 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/76/27ac0bc2f5d7e79d81861e328d7a44757e81d0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/77/d37a0a4d1dcf2348571c8407560f6786e4daf3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/83/1e027303af67fcf6df5adb872b801f6449ee3b Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/83/76fae074f632e3ca81ce6dfc91944c3cb11847 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/85/42c211a5de5eeccef8a9a9997f9321ba6d880c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/85/92c80138ba308aa332f6a427cfd97ac6eb3329 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/85/fbaf1da3ed19b09195fcb4138178b5f0f4c2c4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/86/45716bafafd88b0d67b2c3d12b8b8e4bf46a0a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/86/ed47c8bf40c86fdc569c7e678a8944f5e01c2a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8a/21294bb1073d2d6804235b6bc6af2fb2d08ce6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8a/ae3bd490162291eef8d92f0b169b9b8fd706a6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8b/3302ea06c0f2d012f20563700f48c7d75d4b3c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8d/1823c75c461e49fa7dc8f7cd0bc3a4eb980ef6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8e/0c9a889667fd3a837894a1cace2d8196a691a6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8f/231b0645ab4e7081eccc0b3a1bf366c70634e7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/8f/2bc9cd442ea21d44a52c8bab55333c6941fb17 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/90/10cd39078cc91486da1d08547eb05660362c2c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/94/d0e46f45972aac11ae428b5cc64fe8a4ee6d27 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/95/3bb50291cd5a3100d0e45b128a5d266235e24a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/95/9c04625282673ad11f65ffd55ed8f97a1a0cea Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/98/2da6743ef487d0d0947cb5fc1f0b305ff310d3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/9d/54161261715aa62843752a37a092b48db56c27 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/a0/9061bb1823bd9c729a46cf3b2cd121063a5af1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/a3/b83979ec8272d283fb1a2ad25c9b9e74d9e0cf Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/a8/b5125912fe6450dcca33fa357ad7b5870cbeab Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/a8/d252d67bcbf06bbeb53aff60cb01f96136ef92 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/aa/bf2bfd8ad215d2080613cfe16a1ade42b65525 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/ad/baed3a1a00735f51ba1e24c38d552a80acd3b8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/b8/8add7ec5d94cae6d187ada1bcb5ab545eb846e Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/bb/8182f41bb5512e916d29be1c734aa9f1f19d2f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/c2/09d637a05d23a7390c41c594867e66cd7a2b61 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/c3/0ea2129fa524f9352ef4ec7388986fe0a3513f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/cc/460d8d2e1456b3734b3792da65ced4a132800f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/cc/760c5cfd58ef1044951e299f3ade8b9693ca1c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/cd/1bf66c5d69ec983c6dee28fc1e321f9f6467ec Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/d6/fc3baf28fbcb8e58792079af68bcc9c23e1dce Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/d9/141ca34383010414da53f1ca1b9e63f02d1c9c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/d9/566bd8f78b611da45730ac75e7a07eca493a03 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/da/dd0c5ed6c6246b0a1d800e832cf49b5ac008ea Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/db/de089f2f8ca06714f1f9c94212a5cb6d2aad02 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/dc/37b65ca877d969aa492f348626df6e1b0b1df0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/dd/16c394cb04f4bbad0e8d2103e5a33ff0e24bf5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/de/b0b90a3ec974c3b1634155711cdd74ed498d2e Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/e2/1cfb7dc779c8f4eb259d1d2beeb13fd1d18a68 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/e2/f0dc5443e5a1d9c7ad96f98202c93749158758 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/e4/2e2eeb911f57571bf2708fa7a9136f5bb677bb Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/e4/c54243acb2e7a28d0913dee7ebbe369311e8b3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/ed/2c98d0a9878f01b5a9996497223be7e1361fac Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/ee/fdaba7a9dee8e0b7db8b369517b7fe43258fbd Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/f0/bec599b1539dd61af8ccca0e7a640176f6709f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/f1/c3f75ad0a80184aa30155e298f07f373a75263 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/f3/e3d6d5476b159f82b07d3dec0220e1047bd9b0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/f9/7b41d3f75717a383be2c0410acb3137a725563 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/fc/0f1633de1d2b92aacc30e8cbee920f8e495b7f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/objects/fd/612d3304a70f928496e13f3a54aba553b0dd9f Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/.msub Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/08/2f11ce298302a41ff877eed55ec226b944c24d Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/26/9f14532b98442669c50383782cbce1c67aced5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/27/80390d5b3a7ed7a95478fc61b1a8632b843d1b Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/4d/677496a85bcdfd5a2d8bd5260f36d92bec09a5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/52/f9e7d0c92be3026ed8e2d929f5a2f3af5c7216 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/7d/0e42380917cbd4e2b474ba5771a7e15215e74c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/80/0d8517da4d091eb52094a1cac0a66903aed59a Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/93/e4cb7ebd99ce690370a168ac831cacea4034a9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/98/76baf6df887b76b6cb5da0a2e9bec41146001b Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/ac/0e4a88ca41a9de0f9d03f1d6b75ac2ba0b4ccc Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/e2/3cc82f00dee6d8a91d5fd2bbdf6f4b548a0ffe Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/f3/e3d6d5476b159f82b07d3dec0220e1047bd9b0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/ATParser.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/ATParser.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/Buffer/MyBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/Buffer/MyBuffer.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedPrint.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedSerial.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedSerial.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ATParser/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ESP8266.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266/ESP8266.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266Interface.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/ESP8266Interface.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/esp8266-driver/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/02/865db7ef99ebab8b7ed5e1b5c19180d7001e2f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/0a/8554f3274c0bd641370e7847051bacfdeb8a66 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/0c/1a2859120b36fac35ce950bd266d04e3ed8507 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/0e/4cf3ee99953ca19984fe31ffe0644f6ab37f04 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/0f/a954a6c35d007da7c03f62ecc17f21f75652de Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/18/40de743f199fc7f402ff7bd3c56ccc58954c16 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/19/a06dee5ede2f7c27cce52cfb328e6006576c98 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/20/8d0295c1411f67259867fd86272a9dfe43cc3d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/22/04c03fb0924bc71c988a1ce9a52d5db7e803c9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/2d/75557d97f1cae0d34baf502dcfcbd07ce45343 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/2e/9215af72d17010b1fd609eadb351a035386cf9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/31/b76e128c01acb9372970af3c0d4da92ba0ff3f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/3d/16f39f0b355ed14d158a5ad2ef66c345fd2669 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/40/97116916be1b04358ba3e84569012380657836 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/42/6961ba19e931271a202d1a43173b19976a45c4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/43/cb369dc7aa155af93995bb358bd259f891dda5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/4b/0221132ba0f8fb5cadb2609a9d7f8c2abc1e51 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/4e/1413bd42d39b48bd0547d8814d9d70529dabad Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/51/0214274c3a49819284e615389d631ca912ce15 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/55/8982806e80b6ece3193ff27e41a449277f853c Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/55/8ecca761792e7c80d03a5c0e99e47d49aadde3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/55/ed7949e6509ddcfe671046dc8e6bc6453fb767 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/59/48bc25260f0f636066c51c7a270d468f0583ce Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/5d/6da427b48ef68de41fac9f2478d7a05675c3b0 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/62/0e5785b8fddff70d89319c3927eb08a1a9fad9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/63/037691d31e5413017548618fabfc13ea00962e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/65/e678ec229fe585dede1e6d6ceb2d29fcfc62f1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/67/83dfd110a5b808c5e1a5c09af0ba4b4818a75d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/70/ce9021485641775f9581928f71ef06450f418e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/71/f0db96a14bcfad5c51286ba67aec53a3674224 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/72/e873f0923bc4e89240029f43e9cb23ab674010 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/74/71c50c837b4b85d8f283182a23459d31793416 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/75/db2c976f25deba71e83141e88207472f633cfd Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/76/f34a69bbb943fe6f7fa00a011d7030e3383bf3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/79/a446a98e48485c9f91edf7bdb1d12167e3b7fc Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/7b/9a0ec7821de45f92ec0383eec2f02ea74932ff Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/7b/caf35e20fdcb92e43d2aa23903f041411e958c Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/84/fa8c082c87a2c4e4362605979e4e89c0e931c7 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/85/8335a2b2b1b7b003319143c879b6783c18e4cb Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/8e/cf5b680ac9e4c2e8720a48324efbf1b1bd86f3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/90/b3c4025c969b2faa63f286c4571356b159a1a5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/95/0e428af5013a721584e45d71b45421d40158bc Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/95/26bfc5c480d5eab26293f158095da3dcde9a0e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/97/2c8c3de8a2a362d1dcb91e345dd7c5522e9305 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/97/421f5031567f4fc597d9a56e029c23f00caa13 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/97/df0e645d35bdd2071ab3c147eff48d500dde44 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a2/42e35bcea673ac39310b463fa06311bdca17de Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a2/8948345dfbd89719c60b765a9837ffbd434a2e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a4/ac803efe4c6b4adecb1c9b56c16be1f7802c66 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a5/6963aed6bef9d940e8d5708e06be2d71d929c8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/a8/6dff3733344fb6369a5aaba25773f56042ff18 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/aa/5667ef467392729cf49612b8da3e8ecbab9120 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/aa/927dde7777cbb59654ea4f643e2eafd9d24db3 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/ac/c25aa610ae854f7243fcce0205ab7b15be972d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/af/b0b546ecdd51f44169a66d906c5b65c2039da1 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b1/ddea7d63ddbdc6e2ca59af6316f71ee8f9e70d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b3/a7d6982e43c7ba5a1db261e467571b36215683 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b5/90d12182647706581b143c94012c1462d619b8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b9/7c819a0e740b7f717b2981f75fe380827a1692 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/b9/b1382eb53ac73320f1c20b2986a440c49722a6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/bc/5fe10fd97e239e5a26019580bf7c84e08cd97d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/c3/0d737b6eb86ea642f9ff66603945d3ee045ebf Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/c3/f2caeea01d744dee5e4e7640bfcfcd8b47075e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/c6/d6bc4cdb6628a5a9989fab8bc8e8cd9fd28168 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/c9/bad045a769d69d9709505db2db43c5c59da62d Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/ca/29a807256ea38445915c68d57eadff7c2f4331 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/ca/56cae6cae0f6ddd60baaa8a92e87599d32831f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/cc/4b9cb12a800bdcf4b9f125230c28bbff6d32dd Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/cc/964c3d20a90fac64f7e640fbdcecc105fd5970 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/cc/f8ef134d4bd64a643af9f5d52802484df0caa9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/cd/38b72090af7baac8c9ccfb76709ea8eacad749 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d3/e76502e4bc7bcc0a7d1c77182353b54018b6f6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d5/04c2085fdd21e130930f01f2d9b393d88a8398 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d5/806d6ebede85680f75302f3fdad97a0050fb73 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d6/583d3fcffde81ccd638d1a801d564f90d59b89 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d7/8395e8087d68381c9476391fae880c1c76300f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/d8/810e105d7d35315aa708ec51d821156cad45e9 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/dc/169501b60ceb8f89ae8ddc1c6c261820f40c44 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/dc/321419e543344fd18d7facb378c2f3b82f63e8 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/dc/9eef5f8e370a525df1c7ed24d0125e3c2d75ab Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/de/d8678fad855d8ca6b669dd448e03404ca6fc9f Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/e1/e674c8b81f384254d415dcf6e42805a8eaad3a Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/eb/6f2c8e201c9f8228bcecd525415fb534129e1b Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/eb/99aed8db609de6df1874113d7ca16be82782d5 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/ee/8495c80d204ddf972bf5f61d4f6e8ecac88261 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f3/2a5c3737a70dc828a90f140cf398ee9fbf176e Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f4/32c6962076588227064fa4761bea534a62fbdf Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f5/710629b84db1290f7d4f8417fa638e896e3ae4 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f5/f8b5f7d280ff8b10fd0ef96b3f739e5aca02ab Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/f6/fbfc172fc798d2f1c15a49fadae84ed3f6b3c6 Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/fb/aec7f29a4a5fbc785378a235a9a866cc0d50ef Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/objects/fc/1e7ca40846577040c56df52889ba212e0c24ae Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.gitignore Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/LICENSE Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/module.json Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/MCR20Drv.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/MCR20Drv.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/MCR20Overwrites.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/MCR20Reg.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/mcr20a-rf-driver/source/XcvrSpi.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver.lib Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-54cd72b06384ef3c69fe7a53d28e1b53ffe0b4ce.idx Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-54cd72b06384ef3c69fe7a53d28e1b53ffe0b4ce.pack Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.gitignore Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/.meta Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/NanostackRfPhySpirit1.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/SimpleSpirit1.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/README.md Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/contiki-conf.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/hw-config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/ip64-conf.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/platform-conf.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/radio.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1-config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1-const.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/stm32l-spirit1-config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/Release_Notes.html Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/MCU_Interface.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Aes.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Calibration.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Commands.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Csma.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_DirectRF.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_General.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Gpio.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Irq.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_LinearFifo.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Management.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktBasic.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktCommon.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktMbus.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktStack.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Qi.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Radio.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Regs.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Timer.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Types.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Aes.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Calibration.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Commands.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Csma.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_DirectRF.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_General.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Gpio.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Irq.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_LinearFifo.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Management.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktBasic.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktCommon.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktMbus.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktStack.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Qi.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Radio.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Timer.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Types.c Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/X-NUCLEO-IDS01Ax/radio_gpio.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/X-NUCLEO-IDS01Ax/radio_shield_config.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/source/radio_spi.cpp Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/NanostackRfPhySpirit1.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/SimpleSpirit1.h Show annotated file Show diff for this revision Revisions of this file
easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/radio_spi.h Show annotated file Show diff for this revision Revisions of this file
jsmn/LICENSE Show annotated file Show diff for this revision Revisions of this file
jsmn/README.md Show annotated file Show diff for this revision Revisions of this file
jsmn/RadioCfg.cpp Show annotated file Show diff for this revision Revisions of this file
jsmn/RadioCfg.h Show annotated file Show diff for this revision Revisions of this file
jsmn/WeatherInfo.cpp Show annotated file Show diff for this revision Revisions of this file
jsmn/WeatherInfo.h Show annotated file Show diff for this revision Revisions of this file
jsmn/jsmn.c Show annotated file Show diff for this revision Revisions of this file
jsmn/jsmn.h Show annotated file Show diff for this revision Revisions of this file
jsmn/library.json Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-http.lib Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
mbed_settings.py Show annotated file Show diff for this revision Revisions of this file
mbedtls_entropy_config.h Show annotated file Show diff for this revision Revisions of this file
sd-driver.lib Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/config Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/description Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/index Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/objects/pack/pack-3818907d42dc76a69d2f1576b67ec166057798d1.idx Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/objects/pack/pack-3818907d42dc76a69d2f1576b67ec166057798d1.pack Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
sd-driver/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
sd-driver/.meta Show annotated file Show diff for this revision Revisions of this file
sd-driver/README.md Show annotated file Show diff for this revision Revisions of this file
sd-driver/config/mbed_app.json Show annotated file Show diff for this revision Revisions of this file
sd-driver/docs/pics/sd_driver_k64_with_ci_test_shield.jpg Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/TESTS/examples/example1/example1.cpp Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/TESTS/filesystem/basic/basic.cpp Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/TESTS/filesystem/fopen/fopen.cpp Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/sd/SDBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/sd/SDBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/test/fsfat_debug.h Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/test/fsfat_test.c Show annotated file Show diff for this revision Revisions of this file
sd-driver/features/filesystem/test/fsfat_test.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r a1734fe1ec4b DownloadFile.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DownloadFile.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,149 @@
+#include "DownloadFile.h"
+#include "https_request.h"
+
+void dump_response(HttpResponse* res) 
+{
+    mbedtls_printf("\r\nStatus: %d - %s\r\n", res->get_status_code(), res->get_status_message().c_str());
+
+    mbedtls_printf("Headers:\r\n");
+    for (size_t ix = 0; ix < res->get_headers_length(); ix++) {
+        mbedtls_printf("\t%s: %s\r\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str());
+    }
+    mbedtls_printf("\nBody (%d bytes):\r\n\r\n%s\r\n", res->get_body_length(), res->get_body_as_string().c_str());
+}
+
+static unsigned int base64enc_len(const char *str) 
+{
+   return (((strlen(str)-1)/3)+1)<<2;
+}
+
+static void base64enc(const char *input, unsigned int length, char *output) 
+{
+   static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+   unsigned int c, c1, c2, c3;
+   for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
+     c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
+     c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
+     c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
+
+     c = ((c1 & 0xFC) >> 2);
+     output[j+0] = base64[c];
+     c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
+     output[j+1] = base64[c];
+     c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
+     output[j+2] = (length>i+1)?base64[c]:'=';
+     c = (c3 & 0x3F);
+     output[j+3] = (length>i+2)?base64[c]:'=';
+   }
+   output[(((length-1)/3)+1)<<2] = '\0';
+}
+
+static string encode(const string& str)
+{
+    char* out = new char[ base64enc_len(str.c_str()) ];
+    base64enc(str.c_str(), str.length(), out);
+    string res(out);
+    delete[] out;
+    return res;
+}
+
+void DownloadFile::basic_auth(const char * user, const char * password)
+{
+    authstr = user;
+    authstr += ":";
+    authstr += password;
+    printf("Auth Str : %s\r\n", authstr.c_str());
+
+    std::string base64str = encode(authstr);
+    printf("Base64 conversion : %s\r\n", base64str.c_str());
+    
+    authstr = "Basic " + base64str;
+    printf("Authorization: %s\r\n", authstr.c_str()); 
+}
+        
+HttpResponse* DownloadFile::get_file(const char * url)
+{
+    if (url == NULL) 
+        return NULL;
+
+    if(get_req != NULL) 
+        delete get_req;
+        
+    HttpResponse* get_res;
+    Callback<void(const char *at, size_t length)> aBodyCallback = NULL;
+    
+    if (fp != NULL)
+        aBodyCallback = mbed::callback(this, &DownloadFile::body_callback);
+    
+    if (useSSL)
+    {                
+        get_req_ssl = new HttpsRequest(network, 
+                pem, HTTP_GET, 
+                url,
+                aBodyCallback);
+                
+        if (!authstr.empty())
+            get_req_ssl->set_header("Authorization", authstr.c_str());
+            
+        get_req_ssl->set_debug(true);
+        
+        get_res = get_req_ssl->send();
+        
+    }
+    else
+    {
+        get_req = new HttpRequest(network, 
+                HTTP_GET, 
+                url,
+                aBodyCallback);
+    
+        if (!authstr.empty())
+            get_req->set_header("Authorization", authstr.c_str());
+            
+        get_res = get_req->send();        
+    }
+    
+    if (!get_res) {
+            printf("HttpRequest failed (error code %d)\r\n", get_req->get_error());
+            return NULL;
+    }
+    
+    //dump_response(get_res);
+
+    return get_res;    
+}
+
+std::string DownloadFile::get_file_content()
+{
+    size_t numread;
+    
+    if (fp == NULL) 
+        return "";
+        
+    // plain old c ..
+    // Determine file size
+    fseek(fp, 0, SEEK_END);
+    size_t size = ftell(fp);
+
+    char* dummy = new char[(sizeof(char) * size) + 1];
+
+    rewind(fp);
+    numread = fread(dummy, sizeof(char), size, fp);
+    // Make sure its NULL terminanted
+    dummy[numread] = 0;
+
+    // create a return string
+    std::string retstr = std::string((const char *) dummy);
+
+    delete[] dummy;
+
+    return retstr;
+}
+
+void DownloadFile::body_callback(const char* data, size_t data_len)
+{
+    // do something with the data
+    if (fp != NULL) {
+        size_written += fwrite((const void *) data, sizeof(char), data_len, fp);
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b DownloadFile.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DownloadFile.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,80 @@
+#ifndef _DOWNLOAD_FILE_H_
+#define _DOWNLOAD_FILE_H_
+
+#include <stdio.h>
+#include <string>
+#include "mbed.h"
+#include "rtos.h"
+#include "NetworkInterface.h"
+#include "https_request.h"
+#include "http_request.h"
+
+class DownloadFile
+{
+    public:
+        DownloadFile(NetworkInterface* nw, const char * file = NULL, const char * capem = NULL)
+            :network(nw), 
+            filename(file), 
+            pem(capem), 
+            useSSL(capem != NULL), 
+            fp(NULL), 
+            size_written(0), 
+            get_req_ssl(NULL),
+            get_req(NULL)
+        {
+            if (filename)
+            {
+                fp = fopen(file, "w+");
+                if (fp != NULL)
+                    printf("File open successfull!\r\n");
+            }
+        }
+        
+        virtual ~DownloadFile()
+        {
+            if (fp != NULL) 
+                fclose(fp);
+            
+            // HttpsRequest destructor also free's up
+            // the HttpsResult ... so it must be consumed
+            // before this class goes out of scope
+            if(get_req)
+                delete get_req;
+            if(get_req_ssl)
+                delete get_req_ssl;
+        }
+ 
+        HttpResponse* get_file(const char * url);
+        
+        std::string get_file_content();
+        
+        const char * get_filename()
+        {
+            return filename;
+        }
+            
+        size_t get_written_size() {
+            return size_written;
+        }
+        
+        void basic_auth(const char * user, const char * password);
+
+        
+    protected:
+        void body_callback(const char* data, size_t data_len);
+        
+    private:
+        NetworkInterface* network;
+        const char * filename;
+        const char * pem; 
+        bool useSSL;
+        FILE * fp;
+        size_t size_written;
+        std::string authstr;
+        
+        HttpsRequest* get_req_ssl;
+        HttpRequest* get_req;
+};
+
+#endif
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/FP/FP.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/FP/FP.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,212 @@
+/**
+ * @file    FP.h
+ * @brief   Core Utility - Templated Function Pointer Class
+ * @author  sam grove
+ * @version 1.1
+ * @see     http://mbed.org/users/sam_grove/code/FP/
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FP_H
+#define FP_H
+
+/** Example using the FP Class with global functions
+ * @code
+ *  #include "mbed.h"
+ *  #include "FP.h"
+ *
+ *  FP<void,bool>fp;
+ *  DigitalOut myled(LED1);
+ *
+ *  void handler(bool value)
+ *  {
+ *      myled = value;
+ *      return;
+ *  }
+ *
+ *  int main()
+ *  {
+ *      fp.attach(&handler);
+ *
+ *      while(1)
+ *      {
+ *          fp(1);
+ *          wait(0.2);
+ *          fp(0);
+ *          wait(0.2);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/** Example using the FP Class with different class member functions
+ * @code
+ *  #include "mbed.h"
+ *  #include "FP.h"
+ *
+ *  FP<void,bool>fp;
+ *  DigitalOut myled(LED4);
+ *
+ *  class Wrapper
+ *  {
+ *  public:
+ *      Wrapper(){}
+ *
+ *      void handler(bool value)
+ *      {
+ *          myled = value;
+ *          return;
+ *      }
+ *  };
+ *
+ *  int main()
+ *  {
+ *      Wrapper wrapped;
+ *      fp.attach(&wrapped, &Wrapper::handler);
+ *
+ *      while(1)
+ *      {
+ *          fp(1);
+ *          wait(0.2);
+ *          fp(0);
+ *          wait(0.2);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/** Example using the FP Class with member FP and member function
+* @code
+*  #include "mbed.h"
+*  #include "FP.h"
+*
+*  DigitalOut myled(LED2);
+*
+*  class Wrapper
+*  {
+*  public:
+*      Wrapper()
+*      {
+*          fp.attach(this, &Wrapper::handler);
+*      }
+*
+*      void handler(bool value)
+*      {
+*          myled = value;
+*          return;
+*      }
+*
+*      FP<void,bool>fp;
+*  };
+*
+*  int main()
+*  {
+*      Wrapper wrapped;
+*
+*      while(1)
+*      {
+*          wrapped.fp(1);
+*          wait(0.2);
+*          wrapped.fp(0);
+*          wait(0.2);
+*      }
+*  }
+* @endcode
+*/
+
+/**
+ *  @class FP
+ *  @brief API for managing Function Pointers
+ */
+template<class retT, class argT>
+class FP
+{
+public:
+    /** Create the FP object - only one callback can be attached to the object, that is
+     *  a member function or a global function, not both at the same time
+     */
+    FP()
+    {
+        obj_callback = 0;
+        c_callback = 0;
+    }
+
+    /** Add a callback function to the object
+     *  @param item - Address of the initialized object
+     *  @param member - Address of the member function (dont forget the scope that the function is defined in)
+     */
+    template<class T>
+    void attach(T *item, retT (T::*method)(argT))
+    {
+        obj_callback = (FPtrDummy *)(item);
+        method_callback = (retT (FPtrDummy::*)(argT))(method);
+        return;
+    }
+
+    /** Add a callback function to the object
+     *  @param function - The address of a globally defined function
+     */
+    void attach(retT (*function)(argT))
+    {
+        c_callback = function;
+    }
+
+    /** Invoke the function attached to the class
+     *  @param arg - An argument that is passed into the function handler that is called
+     *  @return The return from the function hanlder called by this class
+     */
+    retT operator()(argT arg) const
+    {
+        if( 0 != c_callback ) {
+            return obj_callback ? (obj_callback->*method_callback)(arg) : (*c_callback)(arg);
+        }
+        return (retT)0;
+    }
+
+    /** Determine if an callback is currently hooked
+     *  @return 1 if a method is hooked, 0 otherwise
+     */
+    bool attached()
+    {
+        return obj_callback || c_callback;
+    }
+
+    /** Release a function from the callback hook
+     */
+    void detach()
+    {
+        obj_callback = 0;
+        c_callback = 0;
+    }
+
+private:
+
+    // empty type used for casting
+    class FPtrDummy;
+
+    FPtrDummy *obj_callback;
+
+    /**
+     *  @union Funciton
+     *  @brief Member or global callback function
+     */
+    union {
+        retT (*c_callback)(argT);                   /*!< Footprint for a global function */
+        retT (FPtrDummy::*method_callback)(argT);   /*!< Footprint for a member function */
+    };
+};
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTConnect.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTConnect.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - add connack return code definitions 
+ *******************************************************************************/
+
+#ifndef MQTTCONNECT_H_
+#define MQTTCONNECT_H_
+
+enum connack_return_codes
+{
+	MQTT_CONNECTION_ACCEPTED = 0,
+	MQTT_UNNACCEPTABLE_PROTOCOL = 1,
+	MQTT_CLIENTID_REJECTED = 2,
+	MQTT_SERVER_UNAVAILABLE = 3,
+	MQTT_BAD_USERNAME_OR_PASSWORD = 4,
+	MQTT_NOT_AUTHORIZED = 5,
+};
+	
+
+typedef union
+{
+	unsigned char all;	/**< all connect flags */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int username : 1;			/**< 3.1 user name */
+		unsigned int password : 1; 			/**< 3.1 password */
+		unsigned int willRetain : 1;		/**< will retain setting */
+		unsigned int willQoS : 2;				/**< will QoS value */
+		unsigned int will : 1;			    /**< will flag */
+		unsigned int cleansession : 1;	  /**< clean session flag */
+		unsigned int : 1;	  	          /**< unused */
+	} bits;
+#else
+	struct
+	{
+		unsigned int : 1;	     					/**< unused */
+		unsigned int cleansession : 1;	  /**< cleansession flag */
+		unsigned int will : 1;			    /**< will flag */
+		unsigned int willQoS : 2;				/**< will QoS value */
+		unsigned int willRetain : 1;		/**< will retain setting */
+		unsigned int password : 1; 			/**< 3.1 password */
+		unsigned int username : 1;			/**< 3.1 user name */
+	} bits;
+#endif
+} MQTTConnectFlags;	/**< connect flags byte */
+
+
+
+/**
+ * Defines the MQTT "Last Will and Testament" (LWT) settings for
+ * the connect packet.
+ */
+typedef struct
+{
+	/** The eyecatcher for this structure.  must be MQTW. */
+	char struct_id[4];
+	/** The version number of this structure.  Must be 0 */
+	int struct_version;
+	/** The LWT topic to which the LWT message will be published. */
+	MQTTString topicName;
+	/** The LWT payload. */
+	MQTTString message;
+	/**
+      * The retained flag for the LWT message (see MQTTAsync_message.retained).
+      */
+	unsigned char retained;
+	/**
+      * The quality of service setting for the LWT message (see
+      * MQTTAsync_message.qos and @ref qos).
+      */
+	char qos;
+} MQTTPacket_willOptions;
+
+
+#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
+
+
+typedef struct
+{
+	/** The eyecatcher for this structure.  must be MQTC. */
+	char struct_id[4];
+	/** The version number of this structure.  Must be 0 */
+	int struct_version;
+	/** Version of MQTT to be used.  3 = 3.1 4 = 3.1.1
+	  */
+	unsigned char MQTTVersion;
+	MQTTString clientID;
+	unsigned short keepAliveInterval;
+	unsigned char cleansession;
+	unsigned char willFlag;
+	MQTTPacket_willOptions will;
+	MQTTString username;
+	MQTTString password;
+} MQTTPacket_connectData;
+
+typedef union
+{
+	unsigned char all;	/**< all connack flags */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int sessionpresent : 1;    /**< session present flag */
+		unsigned int : y;	  	          /**< unused */
+	} bits;
+#else
+	struct
+	{
+		unsigned int : 7;	     			/**< unused */
+		unsigned int sessionpresent : 1;    /**< session present flag */
+	} bits;
+#endif
+} MQTTConnackFlags;	/**< connack flags byte */
+
+#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
+		MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
+
+int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options);
+int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len);
+
+int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent);
+int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen);
+
+int MQTTSerialize_disconnect(unsigned char* buf, int buflen);
+int MQTTSerialize_pingreq(unsigned char* buf, int buflen);
+
+#endif /* MQTTCONNECT_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTConnectClient.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTConnectClient.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
+  * @param options the options to be used to build the connect packet
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_connectLength(MQTTPacket_connectData* options)
+{
+	int len = 0;
+
+	FUNC_ENTRY;
+
+	if (options->MQTTVersion == 3)
+		len = 12; /* variable depending on MQTT or MQIsdp */
+	else if (options->MQTTVersion == 4)
+		len = 10;
+
+	len += MQTTstrlen(options->clientID)+2;
+	if (options->willFlag)
+		len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2;
+	if (options->username.cstring || options->username.lenstring.data)
+		len += MQTTstrlen(options->username)+2;
+	if (options->password.cstring || options->password.lenstring.data)
+		len += MQTTstrlen(options->password)+2;
+
+	FUNC_EXIT_RC(len);
+	return len;
+}
+
+
+/**
+  * Serializes the connect options into the buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param len the length in bytes of the supplied buffer
+  * @param options the options to be used to build the connect packet
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options)
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	MQTTConnectFlags flags = {0};
+	int len = 0;
+	int rc = -1;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = CONNECT;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
+
+	if (options->MQTTVersion == 4)
+	{
+		writeCString(&ptr, "MQTT");
+		writeChar(&ptr, (char) 4);
+	}
+	else
+	{
+		writeCString(&ptr, "MQIsdp");
+		writeChar(&ptr, (char) 3);
+	}
+
+	flags.all = 0;
+	flags.bits.cleansession = options->cleansession;
+	flags.bits.will = (options->willFlag) ? 1 : 0;
+	if (flags.bits.will)
+	{
+		flags.bits.willQoS = options->will.qos;
+		flags.bits.willRetain = options->will.retained;
+	}
+
+	if (options->username.cstring || options->username.lenstring.data)
+		flags.bits.username = 1;
+	if (options->password.cstring || options->password.lenstring.data)
+		flags.bits.password = 1;
+
+	writeChar(&ptr, flags.all);
+	writeInt(&ptr, options->keepAliveInterval);
+	writeMQTTString(&ptr, options->clientID);
+	if (options->willFlag)
+	{
+		writeMQTTString(&ptr, options->will.topicName);
+		writeMQTTString(&ptr, options->will.message);
+	}
+	if (flags.bits.username)
+		writeMQTTString(&ptr, options->username);
+	if (flags.bits.password)
+		writeMQTTString(&ptr, options->password);
+
+	rc = ptr - buf;
+
+	exit: FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into connack data - return code
+  * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
+  * @param connack_rc returned integer value of the connack return code
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param len the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+	MQTTConnackFlags flags = {0};
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != CONNACK)
+		goto exit;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+	if (enddata - curdata < 2)
+		goto exit;
+
+	flags.all = readChar(&curdata);
+	*sessionPresent = flags.bits.sessionpresent;
+	*connack_rc = readChar(&curdata);
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @param packettype the message type
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype)
+{
+	MQTTHeader header = {0};
+	int rc = -1;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = packettype;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_disconnect(unsigned char* buf, int buflen)
+{
+	return MQTTSerialize_zero(buf, buflen, DISCONNECT);
+}
+
+
+/**
+  * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pingreq(unsigned char* buf, int buflen)
+{
+	return MQTTSerialize_zero(buf, buflen, PINGREQ);
+}
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTConnectServer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTConnectServer.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+#include <string.h>
+
+#define min(a, b) ((a < b) ? a : b)
+
+
+/**
+  * Validates MQTT protocol name and version combinations
+  * @param protocol the MQTT protocol name as an MQTTString
+  * @param version the MQTT protocol version number, as in the connect packet
+  * @return correct MQTT combination?  1 is true, 0 is false
+  */
+int MQTTPacket_checkVersion(MQTTString* protocol, int version)
+{
+	int rc = 0;
+
+	if (version == 3 && memcmp(protocol->lenstring.data, "MQIdsp",
+			min(6, protocol->lenstring.len)) == 0)
+		rc = 1;
+	else if (version == 4 && memcmp(protocol->lenstring.data, "MQTT",
+			min(4, protocol->lenstring.len)) == 0)
+		rc = 1;
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into connect data structure
+  * @param data the connect data structure to be filled out
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param len the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len)
+{
+	MQTTHeader header = {0};
+	MQTTConnectFlags flags = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = &buf[len];
+	int rc = 0;
+	MQTTString Protocol;
+	int version;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != CONNECT)
+		goto exit;
+
+	curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */
+
+	if (!readMQTTLenString(&Protocol, &curdata, enddata) ||
+		enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */
+		goto exit;
+
+	version = (int)readChar(&curdata); /* Protocol version */
+	/* If we don't recognize the protocol version, we don't parse the connect packet on the
+	 * basis that we don't know what the format will be.
+	 */
+	if (MQTTPacket_checkVersion(&Protocol, version))
+	{
+		flags.all = readChar(&curdata);
+		data->cleansession = flags.bits.cleansession;
+		data->keepAliveInterval = readInt(&curdata);
+		if (!readMQTTLenString(&data->clientID, &curdata, enddata))
+			goto exit;
+		if (flags.bits.will)
+		{
+			data->willFlag = 1;
+			data->will.qos = flags.bits.willQoS;
+			data->will.retained = flags.bits.willRetain;
+			if (!readMQTTLenString(&data->will.topicName, &curdata, enddata) ||
+				  !readMQTTLenString(&data->will.message, &curdata, enddata))
+				goto exit;
+		}
+		if (flags.bits.username)
+		{
+			if (enddata - curdata < 3 || !readMQTTLenString(&data->username, &curdata, enddata))
+				goto exit; /* username flag set, but no username supplied - invalid */
+			if (flags.bits.password &&
+				(enddata - curdata < 3 || !readMQTTLenString(&data->password, &curdata, enddata)))
+				goto exit; /* password flag set, but no password supplied - invalid */
+		}
+		else if (flags.bits.password)
+			goto exit; /* password flag set without username - invalid */
+		rc = 1;
+	}
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the connack packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param connack_rc the integer connack return code to be used 
+  * @param sessionPresent the MQTT 3.1.1 sessionPresent flag
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+	MQTTConnackFlags flags = {0};
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = CONNACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+
+	flags.all = 0;
+	flags.bits.sessionpresent = sessionPresent;
+	writeChar(&ptr, flags.all); 
+	writeChar(&ptr, connack_rc);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTDeserializePublish.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTDeserializePublish.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+#include <string.h>
+
+#define min(a, b) ((a < b) ? 1 : 0)
+
+/**
+  * Deserializes the supplied (wire) buffer into publish data
+  * @param dup returned integer - the MQTT dup flag
+  * @param qos returned integer - the MQTT QoS value
+  * @param retained returned integer - the MQTT retained flag
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param topicName returned MQTTString - the MQTT topic in the publish
+  * @param payload returned byte buffer - the MQTT publish payload
+  * @param payloadlen returned integer - the length of the MQTT payload
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success
+  */
+int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+		unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != PUBLISH)
+		goto exit;
+	*dup = header.bits.dup;
+	*qos = header.bits.qos;
+	*retained = header.bits.retain;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	if (!readMQTTLenString(topicName, &curdata, enddata) ||
+		enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */
+		goto exit;
+
+	if (*qos > 0)
+		*packetid = readInt(&curdata);
+
+	*payloadlen = enddata - curdata;
+	*payload = curdata;
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Deserializes the supplied (wire) buffer into an ack
+  * @param packettype returned integer - the MQTT packet type
+  * @param dup returned integer - the MQTT dup flag
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	*dup = header.bits.dup;
+	*packettype = header.bits.type;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	if (enddata - curdata < 2)
+		goto exit;
+	*packetid = readInt(&curdata);
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTPacket.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTPacket.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,453 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+
+#include <string.h>
+
+/**
+ * Encodes the message length according to the MQTT algorithm
+ * @param buf the buffer into which the encoded data is written
+ * @param length the length to be encoded
+ * @return the number of bytes written to buffer
+ */
+int MQTTPacket_encode(unsigned char* buf, int length)
+{
+	int rc = 0;
+
+	FUNC_ENTRY;
+	do
+	{
+		char d = length % 128;
+		length /= 128;
+		/* if there are more digits to encode, set the top bit of this digit */
+		if (length > 0)
+			d |= 0x80;
+		buf[rc++] = d;
+	} while (length > 0);
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+ * Decodes the message length according to the MQTT algorithm
+ * @param getcharfn pointer to function to read the next character from the data source
+ * @param value the decoded length returned
+ * @return the number of bytes read from the socket
+ */
+int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value)
+{
+	unsigned char c;
+	int multiplier = 1;
+	int len = 0;
+#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
+
+	FUNC_ENTRY;
+	*value = 0;
+	do
+	{
+		int rc = MQTTPACKET_READ_ERROR;
+
+		if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+		{
+			rc = MQTTPACKET_READ_ERROR;	/* bad data */
+			goto exit;
+		}
+		rc = (*getcharfn)(&c, 1);
+		if (rc != 1)
+			goto exit;
+		*value += (c & 127) * multiplier;
+		multiplier *= 128;
+	} while ((c & 128) != 0);
+exit:
+	FUNC_EXIT_RC(len);
+	return len;
+}
+
+
+int MQTTPacket_len(int rem_len)
+{
+	rem_len += 1; /* header byte */
+
+	/* now remaining_length field */
+	if (rem_len < 128)
+		rem_len += 1;
+	else if (rem_len < 16384)
+		rem_len += 2;
+	else if (rem_len < 2097151)
+		rem_len += 3;
+	else
+		rem_len += 4;
+	return rem_len;
+}
+
+
+static unsigned char* bufptr;
+
+int bufchar(unsigned char* c, int count)
+{
+	int i;
+
+	for (i = 0; i < count; ++i)
+		*c = *bufptr++;
+	return count;
+}
+
+
+int MQTTPacket_decodeBuf(unsigned char* buf, int* value)
+{
+	bufptr = buf;
+	return MQTTPacket_decode(bufchar, value);
+}
+
+
+/**
+ * Calculates an integer from two bytes read from the input buffer
+ * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
+ * @return the integer value calculated
+ */
+int readInt(unsigned char** pptr)
+{
+	unsigned char* ptr = *pptr;
+	int len = 256*(*ptr) + (*(ptr+1));
+	*pptr += 2;
+	return len;
+}
+
+
+/**
+ * Reads one character from the input buffer.
+ * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
+ * @return the character read
+ */
+char readChar(unsigned char** pptr)
+{
+	char c = **pptr;
+	(*pptr)++;
+	return c;
+}
+
+
+/**
+ * Writes one character to an output buffer.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param c the character to write
+ */
+void writeChar(unsigned char** pptr, char c)
+{
+	**pptr = c;
+	(*pptr)++;
+}
+
+
+/**
+ * Writes an integer as 2 bytes to an output buffer.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param anInt the integer to write
+ */
+void writeInt(unsigned char** pptr, int anInt)
+{
+	**pptr = (unsigned char)(anInt / 256);
+	(*pptr)++;
+	**pptr = (unsigned char)(anInt % 256);
+	(*pptr)++;
+}
+
+
+/**
+ * Writes a "UTF" string to an output buffer.  Converts C string to length-delimited.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param string the C string to write
+ */
+void writeCString(unsigned char** pptr, const char* string)
+{
+	int len = strlen(string);
+	writeInt(pptr, len);
+	memcpy(*pptr, string, len);
+	*pptr += len;
+}
+
+
+int getLenStringLen(char* ptr)
+{
+	int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
+	return len;
+}
+
+
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring)
+{
+	if (mqttstring.lenstring.len > 0)
+	{
+		writeInt(pptr, mqttstring.lenstring.len);
+		memcpy(*pptr, mqttstring.lenstring.data, mqttstring.lenstring.len);
+		*pptr += mqttstring.lenstring.len;
+	}
+	else if (mqttstring.cstring)
+		writeCString(pptr, mqttstring.cstring);
+	else
+		writeInt(pptr, 0);
+}
+
+
+/**
+ * @param mqttstring the MQTTString structure into which the data is to be read
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param enddata pointer to the end of the data: do not read beyond
+ * @return 1 if successful, 0 if not
+ */
+int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata)
+{
+	int rc = 0;
+
+	FUNC_ENTRY;
+	/* the first two bytes are the length of the string */
+	if (enddata - (*pptr) > 1) /* enough length to read the integer? */
+	{
+		mqttstring->lenstring.len = readInt(pptr); /* increments pptr to point past length */
+		if (&(*pptr)[mqttstring->lenstring.len] <= enddata)
+		{
+			mqttstring->lenstring.data = (char*)*pptr;
+			*pptr += mqttstring->lenstring.len;
+			rc = 1;
+		}
+	}
+	mqttstring->cstring = NULL;
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+ * Return the length of the MQTTstring - C string if there is one, otherwise the length delimited string
+ * @param mqttstring the string to return the length of
+ * @return the length of the string
+ */
+int MQTTstrlen(MQTTString mqttstring)
+{
+	int rc = 0;
+
+	if (mqttstring.cstring)
+		rc = strlen(mqttstring.cstring);
+	else
+		rc = mqttstring.lenstring.len;
+	return rc;
+}
+
+
+/**
+ * Compares an MQTTString to a C string
+ * @param a the MQTTString to compare
+ * @param bptr the C string to compare
+ * @return boolean - equal or not
+ */
+int MQTTPacket_equals(MQTTString* a, char* bptr)
+{
+	int alen = 0,
+		blen = 0;
+	char *aptr;
+	
+	if (a->cstring)
+	{
+		aptr = a->cstring;
+		alen = strlen(a->cstring);
+	}
+	else
+	{
+		aptr = a->lenstring.data;
+		alen = a->lenstring.len;
+	}
+	blen = strlen(bptr);
+	
+	return (alen == blen) && (strncmp(aptr, bptr, alen) == 0);
+}
+
+
+/**
+ * Helper function to read packet data from some source into a buffer
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param getfn pointer to a function which will read any number of bytes from the needed source
+ * @return integer MQTT packet type, or -1 on error
+ */
+int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int))
+{
+	int rc = -1;
+	MQTTHeader header = {0};
+	int len = 0;
+	int rem_len = 0;
+
+	/* 1. read the header byte.  This has the packet type in it */
+	if ((*getfn)(buf, 1) != 1)
+		goto exit;
+
+	len = 1;
+	/* 2. read the remaining length.  This is variable in itself */
+	MQTTPacket_decode(getfn, &rem_len);
+	len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */
+
+	/* 3. read the rest of the buffer using a callback to supply the rest of the data */
+	if ((*getfn)(buf + len, rem_len) != rem_len)
+		goto exit;
+
+	header.byte = buf[0];
+	rc = header.bits.type;
+exit:
+	return rc;
+}
+
+
+const char* MQTTPacket_names[] =
+{
+	"RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL",
+	"PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK",
+	"PINGREQ", "PINGRESP", "DISCONNECT"
+};
+
+
+char* MQTTPacket_toString(char* strbuf, int strbuflen, unsigned char* buf, int buflen)
+{
+	int index = 0;
+	int rem_length = 0;
+	MQTTHeader header = {0};
+	int strindex = 0;
+
+	header.byte = buf[index++];
+	index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
+
+	switch (header.bits.type)
+	{
+	case CONNECT:
+	{
+		MQTTPacket_connectData data;
+		if (MQTTDeserialize_connect(&data, buf, buflen) == 1)
+		{
+			strindex = snprintf(strbuf, strbuflen,
+				"CONNECT MQTT version %d, client id %.*s, clean session %d, keep alive %hd",
+				(int)data.MQTTVersion, data.clientID.lenstring.len, data.clientID.lenstring.data,
+				(int)data.cleansession, data.keepAliveInterval);
+			if (data.willFlag)
+				strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", will QoS %d, will retain %d, will topic %.*s, will message %.*s",
+				data.will.qos, data.will.retained,
+				data.will.topicName.lenstring.len, data.will.topicName.lenstring.data,
+				data.will.message.lenstring.len, data.will.message.lenstring.data);
+			if (data.username.lenstring.data && data.username.lenstring.len > 0)
+			{
+				printf("user name\n");
+				strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", user name %.*s", data.username.lenstring.len, data.username.lenstring.data);
+			}
+			if (data.password.lenstring.data && data.password.lenstring.len > 0)
+				strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", password %.*s", data.password.lenstring.len, data.password.lenstring.data);
+		}
+	}
+	break;
+	case CONNACK:
+	{
+		unsigned char sessionPresent, connack_rc;
+		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+			"CONNACK session present %d, rc %d", sessionPresent, connack_rc);
+	}
+	break;
+	case PUBLISH:
+	{
+		unsigned char dup, retained, *payload;
+		unsigned short packetid;
+		int qos, payloadlen;
+		MQTTString topicName = MQTTString_initializer;
+		if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
+				&payload, &payloadlen, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"PUBLISH dup %d, QoS %d, retained %d, packet id %d, topic %.*s, payload length %d, payload %.*s",
+				dup, qos, retained, packetid,
+				(topicName.lenstring.len < 20) ? topicName.lenstring.len : 20, topicName.lenstring.data,
+				payloadlen, (payloadlen < 20) ? payloadlen : 20, payload);
+	}
+	break;
+	case PUBACK:
+	case PUBREC:
+	case PUBREL:
+	case PUBCOMP:
+	{
+		unsigned char packettype, dup;
+		unsigned short packetid;
+		if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"%s dup %d, packet id %d",
+				MQTTPacket_names[packettype], dup, packetid);
+	}
+	break;
+	case SUBSCRIBE:
+	{
+		unsigned char dup;
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		MQTTString topicFilters[1];
+		int requestedQoSs[1];
+		if (MQTTDeserialize_subscribe(&dup, &packetid, maxcount, &count,
+				topicFilters, requestedQoSs, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"SUBSCRIBE dup %d, packet id %d count %d topic %.*s qos %d",
+				dup, packetid, count,
+				topicFilters[0].lenstring.len, topicFilters[0].lenstring.data,
+				requestedQoSs[0]);
+	}
+	break;
+	case SUBACK:
+	{
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		int grantedQoSs[1];
+		if (MQTTDeserialize_suback(&packetid, maxcount, &count, grantedQoSs, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"SUBACK packet id %d count %d granted qos %d",
+				packetid, count, grantedQoSs[0]);
+	}
+	break;
+	case UNSUBSCRIBE:
+	{
+		unsigned char dup;
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		MQTTString topicFilters[1];
+		if (MQTTDeserialize_unsubscribe(&dup, &packetid, maxcount, &count, topicFilters, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"UNSUBSCRIBE dup %d, packet id %d count %d topic %.*s",
+				dup, packetid, count,
+				topicFilters[0].lenstring.len, topicFilters[0].lenstring.data);
+	}
+	break;
+	case UNSUBACK:
+	{
+		unsigned short packetid;
+		if (MQTTDeserialize_unsuback(&packetid, buf, buflen) == 1)
+			strindex = snprintf(strbuf, strbuflen,
+				"UNSUBACK packet id %d", packetid);
+	}
+	break;
+	case PINGREQ:
+	case PINGRESP:
+	case DISCONNECT:
+		strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
+		break;
+	}
+	return strbuf;
+}
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTPacket.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTPacket.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef MQTTPACKET_H_
+#define MQTTPACKET_H_
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+enum errors
+{
+	MQTTPACKET_BUFFER_TOO_SHORT = -2,
+	MQTTPACKET_READ_ERROR = -1,
+	MQTTPACKET_READ_COMPLETE,
+};
+
+enum msgTypes
+{
+	CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
+	PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
+	PINGREQ, PINGRESP, DISCONNECT
+};
+
+/**
+ * Bitfields for the MQTT header byte.
+ */
+typedef union
+{
+	unsigned char byte;	                /**< the whole byte */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int type : 4;			/**< message type nibble */
+		unsigned int dup : 1;				/**< DUP flag bit */
+		unsigned int qos : 2;				/**< QoS value, 0, 1 or 2 */
+		unsigned int retain : 1;		/**< retained flag bit */
+	} bits;
+#else
+	struct
+	{
+		unsigned int retain : 1;		/**< retained flag bit */
+		unsigned int qos : 2;				/**< QoS value, 0, 1 or 2 */
+		unsigned int dup : 1;				/**< DUP flag bit */
+		unsigned int type : 4;			/**< message type nibble */
+	} bits;
+#endif
+} MQTTHeader;
+
+typedef struct
+{
+	int len;
+	char* data;
+} MQTTLenString;
+
+typedef struct
+{
+	char* cstring;
+	MQTTLenString lenstring;
+} MQTTString;
+
+#define MQTTString_initializer {NULL, {0, NULL}}
+
+int MQTTstrlen(MQTTString mqttstring);
+
+#include "MQTTConnect.h"
+#include "MQTTPublish.h"
+#include "MQTTSubscribe.h"
+#include "MQTTUnsubscribe.h"
+
+int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid);
+int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen);
+
+int MQTTPacket_len(int rem_len);
+int MQTTPacket_equals(MQTTString* a, char* b);
+
+int MQTTPacket_encode(unsigned char* buf, int length);
+int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value);
+int MQTTPacket_decodeBuf(unsigned char* buf, int* value);
+
+int readInt(unsigned char** pptr);
+char readChar(unsigned char** pptr);
+void writeChar(unsigned char** pptr, char c);
+void writeInt(unsigned char** pptr, int anInt);
+int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata);
+void writeCString(unsigned char** pptr, const char* string);
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring);
+
+int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int));
+
+char* MQTTPacket_toString(char* strbuf, int strbuflen, unsigned char* buf, int buflen);
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+
+#endif /* MQTTPACKET_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTPublish.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTPublish.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef MQTTPUBLISH_H_
+#define MQTTPUBLISH_H_
+
+int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
+		MQTTString topicName, unsigned char* payload, int payloadlen);
+
+int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+		unsigned char** payload, int* payloadlen, unsigned char* buf, int len);
+
+int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid);
+int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid);
+int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid);
+
+#endif /* MQTTPUBLISH_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTSerializePublish.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTSerializePublish.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Determines the length of the MQTT publish packet that would be produced using the supplied parameters
+  * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
+  * @param topicName the topic name to be used in the publish  
+  * @param payloadlen the length of the payload to be sent
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_publishLength(int qos, MQTTString topicName, int payloadlen)
+{
+	int len = 0;
+
+	len += 2 + MQTTstrlen(topicName) + payloadlen;
+	if (qos > 0)
+		len += 2; /* packetid */
+	return len;
+}
+
+
+/**
+  * Serializes the supplied publish data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param qos integer - the MQTT QoS value
+  * @param retained integer - the MQTT retained flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param topicName MQTTString - the MQTT topic in the publish
+  * @param payload byte buffer - the MQTT publish payload
+  * @param payloadlen integer - the length of the MQTT payload
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
+		MQTTString topicName, unsigned char* payload, int payloadlen)
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.bits.type = PUBLISH;
+	header.bits.dup = dup;
+	header.bits.qos = qos;
+	header.bits.retain = retained;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeMQTTString(&ptr, topicName);
+
+	if (qos > 0)
+		writeInt(&ptr, packetid);
+
+	memcpy(ptr, payload, payloadlen);
+	ptr += payloadlen;
+
+	rc = ptr - buf;
+
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Serializes the ack packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param type the MQTT packet type
+  * @param dup the MQTT dup flag
+  * @param packetid the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char packettype, unsigned char dup, unsigned short packetid)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 4)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.bits.type = packettype;
+	header.bits.dup = dup;
+	header.bits.qos = 0;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+	writeInt(&ptr, packetid);
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes a puback packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBACK, packetid, 0);
+}
+
+
+/**
+  * Serializes a pubrel packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBREL, packetid, dup);
+}
+
+
+/**
+  * Serializes a pubrel packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBCOMP, packetid, 0);
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTSubscribe.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTSubscribe.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef MQTTSUBSCRIBE_H_
+#define MQTTSUBSCRIBE_H_
+
+int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[], int requestedQoSs[]);
+
+int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid,
+		int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int len);
+
+int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs);
+
+int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int len);
+
+
+#endif /* MQTTSUBSCRIBE_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTSubscribeClient.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTSubscribeClient.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters
+  * @param count the number of topic filter strings in topicFilters
+  * @param topicFilters the array of topic filter strings to be used in the publish
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_subscribeLength(int count, MQTTString topicFilters[])
+{
+	int i;
+	int len = 2; /* packetid */
+
+	for (i = 0; i < count; ++i)
+		len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */
+	return len;
+}
+
+
+/**
+  * Serializes the supplied subscribe data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied bufferr
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the topicFilters and reqQos arrays
+  * @param topicFilters - array of topic filter names
+  * @param requestedQoSs - array of requested QoS
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, int count,
+		MQTTString topicFilters[], int requestedQoSs[])
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = 0;
+	int i = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = SUBSCRIBE;
+	header.bits.dup = dup;
+	header.bits.qos = 1;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+	{
+		writeMQTTString(&ptr, topicFilters[i]);
+		writeChar(&ptr, requestedQoSs[i]);
+	}
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Deserializes the supplied (wire) buffer into suback data
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the grantedQoSs array
+  * @param count returned integer - number of members in the grantedQoSs array
+  * @param grantedQoSs returned array of integers - the granted qualities of service
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != SUBACK)
+		goto exit;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+	if (enddata - curdata < 2)
+		goto exit;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (*count > maxcount)
+		{
+			rc = -1;
+			goto exit;
+		}
+		grantedQoSs[(*count)++] = readChar(&curdata);
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTSubscribeServer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTSubscribeServer.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Deserializes the supplied (wire) buffer into subscribe data
+  * @param dup integer returned - the MQTT dup flag
+  * @param packetid integer returned - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
+  * @param count - number of members in the topicFilters and requestedQoSs arrays
+  * @param topicFilters - array of topic filter names
+  * @param requestedQoSs - array of requested QoS
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
+	int requestedQoSs[], unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = -1;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != SUBSCRIBE)
+		goto exit;
+	*dup = header.bits.dup;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
+			goto exit;
+		if (curdata >= enddata) /* do we have enough data to read the req_qos version byte? */
+			goto exit;
+		requestedQoSs[*count] = readChar(&curdata);
+		(*count)++;
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the supplied suback data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the grantedQoSs array
+  * @param grantedQoSs - array of granted QoS
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs)
+{
+	MQTTHeader header = {0};
+	int rc = -1;
+	unsigned char *ptr = buf;
+	int i;
+
+	FUNC_ENTRY;
+	if (buflen < 2 + count)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = SUBACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2 + count); /* write remaining length */
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+		writeChar(&ptr, grantedQoSs[i]);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTUnsubscribe.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTUnsubscribe.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#ifndef MQTTUNSUBSCRIBE_H_
+#define MQTTUNSUBSCRIBE_H_
+
+int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[]);
+
+int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[],
+		unsigned char* buf, int len);
+
+int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid);
+
+int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int len);
+
+#endif /* MQTTUNSUBSCRIBE_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTUnsubscribeClient.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTUnsubscribeClient.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters
+  * @param count the number of topic filter strings in topicFilters
+  * @param topicFilters the array of topic filter strings to be used in the publish
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_unsubscribeLength(int count, MQTTString topicFilters[])
+{
+	int i;
+	int len = 2; /* packetid */
+
+	for (i = 0; i < count; ++i)
+		len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/
+	return len;
+}
+
+
+/**
+  * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the topicFilters array
+  * @param topicFilters - array of topic filter names
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[])
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = -1;
+	int i = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = UNSUBSCRIBE;
+	header.bits.dup = dup;
+	header.bits.qos = 1;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+		writeMQTTString(&ptr, topicFilters[i]);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into unsuback data
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen)
+{
+	unsigned char type = 0;
+	unsigned char dup = 0;
+	int rc = 0;
+
+	FUNC_ENTRY;
+	rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen);
+	if (type == UNSUBACK)
+		rc = 1;
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/MQTTUnsubscribeServer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/MQTTUnsubscribeServer.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Deserializes the supplied (wire) buffer into unsubscribe data
+  * @param dup integer returned - the MQTT dup flag
+  * @param packetid integer returned - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
+  * @param count - number of members in the topicFilters and requestedQoSs arrays
+  * @param topicFilters - array of topic filter names
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
+		unsigned char* buf, int len)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != UNSUBSCRIBE)
+		goto exit;
+	*dup = header.bits.dup;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
+			goto exit;
+		(*count)++;
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the supplied unsuback data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = UNSUBACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+
+	writeInt(&ptr, packetid);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/StackTrace.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/StackTrace.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - fix for bug #434081
+ *******************************************************************************/
+
+#ifndef STACKTRACE_H_
+#define STACKTRACE_H_
+
+#include <stdio.h>
+#define NOSTACKTRACE 1
+
+#if defined(NOSTACKTRACE)
+#define FUNC_ENTRY
+#define FUNC_ENTRY_NOLOG
+#define FUNC_ENTRY_MED
+#define FUNC_ENTRY_MAX
+#define FUNC_EXIT
+#define FUNC_EXIT_NOLOG
+#define FUNC_EXIT_MED
+#define FUNC_EXIT_MAX
+#define FUNC_EXIT_RC(x)
+#define FUNC_EXIT_MED_RC(x)
+#define FUNC_EXIT_MAX_RC(x)
+
+#else
+
+#if defined(WIN32)
+#define inline __inline
+#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
+#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
+#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
+#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
+#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
+#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
+#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
+#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
+#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
+#else
+#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
+#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
+#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
+#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
+#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
+#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
+#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
+#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
+#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
+
+void StackTrace_entry(const char* name, int line, int trace);
+void StackTrace_exit(const char* name, int line, void* return_value, int trace);
+
+void StackTrace_printStack(FILE* dest);
+char* StackTrace_get(unsigned long);
+
+#endif
+
+#endif
+
+
+
+
+#endif /* STACKTRACE_H_ */
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/samples/publish-subscribe.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/samples/publish-subscribe.txt	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,115 @@
+#include "MQTTPacket.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "EthernetInterface.h"
+
+
+TCPSocketConnection mysock; 
+
+int getdata(char* buf, int count)
+{
+    return mysock.receive(buf, (size_t)count);
+}
+
+int toStop = 0;
+
+
+int main()
+{
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+    int rc = 0;
+    char buf[200];
+    int buflen = sizeof(buf);
+    int msgid = 1;
+    MQTTString topicString = MQTTString_initializer;
+    int req_qos = 0;
+    char* payload = "mypayload";
+    int payloadlen = strlen(payload);
+    int len = 0;
+    EthernetInterface eth;
+    
+    eth.init(); //Use DHCP
+    eth.connect();
+
+    rc = mysock.connect("m2m.eclipse.org", 1883);
+
+    data.clientID.cstring = "SendReceive mbed MQTT ";
+    data.keepAliveInterval = 20;
+    data.cleansession = 1;
+
+    mysock.set_blocking(true, 1000);  /* 1 second Timeout */
+
+    len = MQTTSerialize_connect(buf, buflen, &data);
+    rc = mysock.send(buf, len);
+
+    /* wait for connack */
+    if (MQTTPacket_read(buf, buflen, getdata) == CONNACK)
+    {
+        int connack_rc;
+
+        if (MQTTDeserialize_connack(&connack_rc, buf, buflen) != 1 || connack_rc != 0)
+        {
+            printf("Unable to connect, return code %d\n", connack_rc);
+            goto exit;
+        }
+    }
+    else
+        goto exit;
+
+    /* subscribe */
+    topicString.cstring = "substopic";
+    len = MQTTSerialize_subscribe(buf, buflen, 0, msgid, 1, &topicString, &req_qos);
+
+    rc = mysock.send(buf, len);
+    if (MQTTPacket_read(buf, buflen, getdata) == SUBACK)    /* wait for suback */
+    {
+        int submsgid;
+        int subcount;
+        int granted_qos;
+
+        rc = MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, buf, buflen);
+        if (granted_qos != 0)
+        {
+            printf("granted qos != 0, %d\n", granted_qos);
+            goto exit;
+        }
+    }
+    else
+        goto exit;
+
+    topicString.cstring = "pubtopic";
+    while (!toStop)
+    {
+        if (MQTTPacket_read(buf, buflen, getdata) == PUBLISH)
+        {
+            int dup;
+            int qos;
+            int retained;
+            int msgid;
+            int payloadlen_in;
+            char* payload_in;
+            int rc;
+            MQTTString receivedTopic;
+
+            rc = MQTTDeserialize_publish(&dup, &qos, &retained, &msgid, &receivedTopic,
+                    &payload_in, &payloadlen_in, buf, buflen);
+            printf("message arrived %.*s\n", payloadlen_in, payload_in);
+        }
+
+        printf("publishing reading\n");
+        len = MQTTSerialize_publish(buf, buflen, 0, 0, 0, 0, topicString, payload, payloadlen);
+        rc = mysock.send(buf, len);
+    }
+
+    printf("disconnecting\n");
+    len = MQTTSerialize_disconnect(buf, buflen);
+    rc = mysock.send(buf, len);
+
+exit:    
+    eth.disconnect();
+
+    return 0;
+}
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/samples/simple-publish.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/samples/simple-publish.txt	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "mbed.h"
+#include "EthernetInterface.h"
+#include "C12832_lcd.h"
+
+#include "MQTTPacket.h"
+
+DigitalOut myled(LED2);
+C12832_LCD lcd;
+
+int publish()
+{
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+    int rc = 0;
+    char buf[200];
+    int buflen = sizeof(buf);
+    TCPSocketConnection mysock; 
+    MQTTString topicString = MQTTString_initializer;
+    char* payload = "I'm alive!";
+    int payloadlen = strlen(payload);
+    int len = 0;
+    
+    mysock.connect("m2m.eclipse.org", 1883);
+          
+    data.clientID.cstring = "mbed test client - Ian Craggs";
+    data.keepAliveInterval = 20;
+    data.cleansession = 1;
+    data.MQTTVersion = 3;
+
+    len = MQTTSerialize_connect(buf, buflen, &data);
+
+    topicString.cstring = "mbed NXP LPC1768";
+    len += MQTTSerialize_publish(buf + len, buflen - len, 0, 0, 0, 0, topicString, payload, payloadlen);
+
+    len += MQTTSerialize_disconnect(buf + len, buflen - len);
+
+    rc = 0;
+    while (rc < len)
+    {
+        int rc1 = mysock.send(buf, len);
+        if (rc1 == -1)
+        {
+            lcd.printf("Send failed\n");
+            break;
+        }
+        else
+            rc += rc1;
+    }
+    if (rc == len)
+        lcd.printf("Send succeeded\n");
+    wait(0.2);
+
+    return 0;
+}
+
+int main()
+{
+    EthernetInterface eth;
+    eth.init(); //Use DHCP
+    eth.connect();
+    lcd.printf("IP Address is %s\n", eth.getIPAddress());
+    
+    while(1) 
+    {
+        myled = 1;
+        publish();
+        wait(0.2);
+        myled = 0;
+        publish();
+        wait(0.2);
+    }
+    
+    eth.disconnect();
+}
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTPacket/test/test1.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTPacket/test/test1.txt	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,631 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+
+#include "MQTTPacket.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#if !defined(_WINDOWS)
+	#include <sys/time.h>
+  	#include <sys/socket.h>
+	#include <unistd.h>
+  	#include <errno.h>
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define MAXHOSTNAMELEN 256
+#define EAGAIN WSAEWOULDBLOCK
+#define EINTR WSAEINTR
+#define EINPROGRESS WSAEINPROGRESS
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ENOTCONN WSAENOTCONN
+#define ECONNRESET WSAECONNRESET
+#endif
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+struct Options
+{
+	char* connection;         /**< connection to system under test. */
+	char** haconnections;
+	int hacount;
+	int verbose;
+	int test_no;
+} options =
+{
+	"tcp://m2m.eclipse.org:1883",
+	NULL,
+	0,
+	0,
+	0,
+};
+
+void usage()
+{
+
+}
+
+void getopts(int argc, char** argv)
+{
+	int count = 1;
+
+	while (count < argc)
+	{
+		if (strcmp(argv[count], "--test_no") == 0)
+		{
+			if (++count < argc)
+				options.test_no = atoi(argv[count]);
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--connection") == 0)
+		{
+			if (++count < argc)
+			{
+				options.connection = argv[count];
+				printf("\nSetting connection to %s\n", options.connection);
+			}
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--haconnections") == 0)
+		{
+			if (++count < argc)
+			{
+				char* tok = strtok(argv[count], " ");
+				options.hacount = 0;
+				options.haconnections = malloc(sizeof(char*) * 5);
+				while (tok)
+				{
+					options.haconnections[options.hacount] = malloc(strlen(tok) + 1);
+					strcpy(options.haconnections[options.hacount], tok);
+					options.hacount++;
+					tok = strtok(NULL, " ");
+				}
+			}
+			else
+				usage();
+		}
+		else if (strcmp(argv[count], "--verbose") == 0)
+		{
+			options.verbose = 1;
+			printf("\nSetting verbose on\n");
+		}
+		count++;
+	}
+}
+
+
+#define LOGA_DEBUG 0
+#define LOGA_INFO 1
+#include <stdarg.h>
+#include <time.h>
+#include <sys/timeb.h>
+void MyLog(int LOGA_level, char* format, ...)
+{
+	static char msg_buf[256];
+	va_list args;
+	struct timeb ts;
+
+	struct tm *timeinfo;
+
+	if (LOGA_level == LOGA_DEBUG && options.verbose == 0)
+	  return;
+
+	ftime(&ts);
+	timeinfo = localtime(&ts.time);
+	strftime(msg_buf, 80, "%Y%m%d %H%M%S", timeinfo);
+
+	sprintf(&msg_buf[strlen(msg_buf)], ".%.3hu ", ts.millitm);
+
+	va_start(args, format);
+	vsnprintf(&msg_buf[strlen(msg_buf)], sizeof(msg_buf) - strlen(msg_buf), format, args);
+	va_end(args);
+
+	printf("%s\n", msg_buf);
+	fflush(stdout);
+}
+
+
+#if defined(WIN32) || defined(_WINDOWS)
+#define mqsleep(A) Sleep(1000*A)
+#define START_TIME_TYPE DWORD
+static DWORD start_time = 0;
+START_TIME_TYPE start_clock(void)
+{
+	return GetTickCount();
+}
+#elif defined(AIX)
+#define mqsleep sleep
+#define START_TIME_TYPE struct timespec
+START_TIME_TYPE start_clock(void)
+{
+	static struct timespec start;
+	clock_gettime(CLOCK_REALTIME, &start);
+	return start;
+}
+#else
+#define mqsleep sleep
+#define START_TIME_TYPE struct timeval
+/* TODO - unused - remove? static struct timeval start_time; */
+START_TIME_TYPE start_clock(void)
+{
+	struct timeval start_time;
+	gettimeofday(&start_time, NULL);
+	return start_time;
+}
+#endif
+
+
+#if defined(WIN32)
+long elapsed(START_TIME_TYPE start_time)
+{
+	return GetTickCount() - start_time;
+}
+#elif defined(AIX)
+#define assert(a)
+long elapsed(struct timespec start)
+{
+	struct timespec now, res;
+
+	clock_gettime(CLOCK_REALTIME, &now);
+	ntimersub(now, start, res);
+	return (res.tv_sec)*1000L + (res.tv_nsec)/1000000L;
+}
+#else
+long elapsed(START_TIME_TYPE start_time)
+{
+	struct timeval now, res;
+
+	gettimeofday(&now, NULL);
+	timersub(&now, &start_time, &res);
+	return (res.tv_sec)*1000 + (res.tv_usec)/1000;
+}
+#endif
+
+
+#define assert(a, b, c, d) myassert(__FILE__, __LINE__, a, b, c, d)
+#define assert1(a, b, c, d, e) myassert(__FILE__, __LINE__, a, b, c, d, e)
+
+int tests = 0;
+int failures = 0;
+FILE* xml;
+START_TIME_TYPE global_start_time;
+char output[3000];
+char* cur_output = output;
+
+
+void write_test_result()
+{
+	long duration = elapsed(global_start_time);
+
+	fprintf(xml, " time=\"%ld.%.3ld\" >\n", duration / 1000, duration % 1000);
+	if (cur_output != output)
+	{
+		fprintf(xml, "%s", output);
+		cur_output = output;
+	}
+	fprintf(xml, "</testcase>\n");
+}
+
+
+void myassert(char* filename, int lineno, char* description, int value, char* format, ...)
+{
+	++tests;
+	if (!value)
+	{
+		va_list args;
+
+		++failures;
+		printf("Assertion failed, file %s, line %d, description: %s\n", filename, lineno, description);
+
+		va_start(args, format);
+		vprintf(format, args);
+		va_end(args);
+
+		cur_output += sprintf(cur_output, "<failure type=\"%s\">file %s, line %d </failure>\n",
+                        description, filename, lineno);
+	}
+    else
+    	MyLog(LOGA_DEBUG, "Assertion succeeded, file %s, line %d, description: %s", filename, lineno, description);
+}
+
+#define min(a, b) ((a < b) ? a : b)
+
+int checkMQTTStrings(MQTTString a, MQTTString b)
+{
+	if (!a.lenstring.data)
+	{
+		a.lenstring.data = a.cstring;
+		if (a.cstring)
+			a.lenstring.len = strlen(a.cstring);
+	}
+	if (!b.lenstring.data)
+	{
+		b.lenstring.data = b.cstring;
+		if (b.cstring)
+			b.lenstring.len = strlen(b.cstring);
+	}
+	return memcmp(a.lenstring.data, b.lenstring.data, min(a.lenstring.len, b.lenstring.len)) == 0;
+}
+
+
+int checkConnectPackets(MQTTPacket_connectData* before, MQTTPacket_connectData* after)
+{
+	int rc = 0;
+	int start_failures = failures;
+
+	assert("struct_ids should be the same",
+			memcmp(before->struct_id, after->struct_id, 4) == 0, "struct_ids were different %.4s\n", after->struct_id);
+
+	assert("struct_versions should be the same",
+			before->struct_version == after->struct_version, "struct_versions were different\n", rc);
+
+	assert("MQTT versions should be the same",
+			before->MQTTVersion == after->MQTTVersion, "MQTT versions were different\n", rc);
+
+	assert("ClientIDs should be the same",
+			checkMQTTStrings(before->clientID, after->clientID), "ClientIDs were different\n", rc);
+
+	assert("keepAliveIntervals should be the same",
+			before->keepAliveInterval == after->keepAliveInterval, "keepAliveIntervals were different %d\n", after->keepAliveInterval);
+
+	assert("cleansessions should be the same",
+			before->cleansession == after->cleansession, "cleansessions were different\n", rc);
+
+	assert("willFlags should be the same",
+				before->willFlag == after->willFlag, "willFlags were different\n", rc);
+
+	if (before->willFlag)
+	{
+		assert("will struct_ids should be the same",
+				memcmp(before->will.struct_id, after->will.struct_id, 4) == 0, "will struct_ids were different %.4s\n", after->struct_id);
+
+		assert("will struct_versions should be the same",
+				before->will.struct_version == after->will.struct_version, "will struct_versions were different\n", rc);
+
+		assert("topic names should be the same",
+				checkMQTTStrings(before->will.topicName, after->will.topicName), "topic names were different\n", rc);
+
+		assert("messages should be the same",
+				checkMQTTStrings(before->will.message, after->will.message), "messages were different\n", rc);
+
+		assert("retained flags should be the same",
+					before->will.retained == after->will.retained, "retained flags were different\n", rc);
+
+		assert("will qos should be the same",
+					before->will.qos == after->will.qos, "will qos were different\n", rc);
+	}
+
+	assert("usernames should be the same",
+			checkMQTTStrings(before->clientID, after->clientID), "usernames were different\n", rc);
+	assert("passwords should be the same",
+			checkMQTTStrings(before->password, after->password), "passwords were different\n", rc);
+	return failures == start_failures;
+}
+
+int test1(struct Options options)
+{
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	MQTTPacket_connectData data_after = MQTTPacket_connectData_initializer;
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 1 - serialization of connect and back");
+
+	data.clientID.cstring = "me";
+
+	data.keepAliveInterval = 20;
+	data.cleansession = 1;
+	data.username.cstring = "testuser";
+	data.password.cstring = "testpassword";
+
+	data.willFlag = 1;
+	data.will.message.cstring = "will message";
+	data.will.qos = 1;
+	data.will.retained = 0;
+	data.will.topicName.cstring = "will topic";
+
+	rc = MQTTSerialize_connect(buf, buflen, &data);
+	assert("good rc from serialize connect", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_connect(&data_after, buf, buflen);
+	assert("good rc from deserialize connect", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	rc = checkConnectPackets(&data, &data_after);
+	assert("packets should be the same",  rc == 1, "packets were different\n", rc);
+
+/* exit: */
+	MyLog(LOGA_INFO, "TEST1: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test2(struct Options options)
+{
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+
+	unsigned char dup = 0;
+	int qos = 2;
+	unsigned char retained = 0;
+	int msgid = 23;
+	MQTTString topicString = MQTTString_initializer;
+	char *payload = "kkhkhkjkj jkjjk jk jk ";
+	int payloadlen = strlen(payload);
+
+	unsigned char dup2 = 1;
+	int qos2 = 1;
+	unsigned char retained2 = 1;
+	int msgid2 = 3243;
+	MQTTString topicString2 = MQTTString_initializer;
+	char *payload2 = NULL;
+	int payloadlen2 = 0;
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - serialization of publish and back");
+
+	topicString.cstring = "mytopic";
+	rc = MQTTSerialize_publish(buf, buflen, dup, qos, retained, msgid, topicString,
+			payload, payloadlen);
+	assert("good rc from serialize publish", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_publish(&dup2, &qos2, &retained2, &msgid2, &topicString2,
+			&payload2, &payloadlen2, buf, buflen);
+	assert("good rc from deserialize publish", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
+	assert("qoss should be the same", qos == qos2, "qoss were different %d\n", qos2);
+	assert("retaineds should be the same", retained == retained2, "retaineds were different %d\n", retained2);
+	assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
+
+	assert("topics should be the same",
+					checkMQTTStrings(topicString, topicString2), "topics were different %s\n", ""); //topicString2);
+
+	assert("payload lengths should be the same",
+				payloadlen == payloadlen2, "payload lengths were different %d\n", payloadlen2);
+
+	assert("payloads should be the same",
+						memcmp(payload, payload2, payloadlen) == 0, "payloads were different %s\n", "");
+
+/*exit:*/
+	MyLog(LOGA_INFO, "TEST2: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+
+int test3(struct Options options)
+{
+	int i = 0;
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+#define TOPIC_COUNT 2
+
+	int dup = 0;
+	int msgid = 23;
+	int count = TOPIC_COUNT;
+	MQTTString topicStrings[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
+	int req_qoss[TOPIC_COUNT] = {2, 1};
+
+	int dup2 = 1;
+	int msgid2 = 2223;
+	int count2 = 0;
+	MQTTString topicStrings2[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
+	int req_qoss2[TOPIC_COUNT] = {0, 0};
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - serialization of subscribe and back");
+
+	topicStrings[0].cstring = "mytopic";
+	topicStrings[1].cstring = "mytopic2";
+	rc = MQTTSerialize_subscribe(buf, buflen, dup, msgid, count, topicStrings, req_qoss);
+	assert("good rc from serialize subscribe", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_subscribe(&dup2, &msgid2, 2, &count2, topicStrings2, req_qoss2, buf, buflen);
+	assert("good rc from deserialize subscribe", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
+	assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
+
+	assert("count should be the same", count == count2, "counts were different %d\n", count2);
+
+	for (i = 0; i < count2; ++i)
+	{
+		assert("topics should be the same",
+					checkMQTTStrings(topicStrings[i], topicStrings2[i]), "topics were different %s\n", "");
+
+		assert("qoss should be the same", req_qoss[i] == req_qoss2[i], "qoss were different %d\n", req_qoss2[i]);
+	}
+
+/*exit:*/
+	MyLog(LOGA_INFO, "TEST3: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test4(struct Options options)
+{
+	int i = 0;
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+#define TOPIC_COUNT 2
+
+	int msgid = 23;
+	int count = TOPIC_COUNT;
+	int granted_qoss[TOPIC_COUNT] = {2, 1};
+;
+	int msgid2 = 2223;
+	int count2 = 0;
+	int granted_qoss2[TOPIC_COUNT] = {0, 0};
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 4 - serialization of suback and back");
+
+	rc = MQTTSerialize_suback(buf, buflen, msgid, count, granted_qoss);
+	assert("good rc from serialize suback", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_suback(&msgid2, 2, &count2, granted_qoss2, buf, buflen);
+	assert("good rc from deserialize suback", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
+
+	assert("count should be the same", count == count2, "counts were different %d\n", count2);
+
+	for (i = 0; i < count2; ++i)
+		assert("qoss should be the same", granted_qoss[i] == granted_qoss2[i], "qoss were different %d\n", granted_qoss2[i]);
+
+/* exit: */
+	MyLog(LOGA_INFO, "TEST4: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test5(struct Options options)
+{
+	int i = 0;
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+#define TOPIC_COUNT 2
+
+	int dup = 0;
+	int msgid = 23;
+	int count = TOPIC_COUNT;
+	MQTTString topicStrings[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
+
+	int dup2 = 1;
+	int msgid2 = 2223;
+	int count2 = 0;
+	MQTTString topicStrings2[TOPIC_COUNT] = { MQTTString_initializer, MQTTString_initializer };
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - serialization of unsubscribe and back");
+
+	topicStrings[0].cstring = "mytopic";
+	topicStrings[1].cstring = "mytopic2";
+	rc = MQTTSerialize_unsubscribe(buf, buflen, dup, msgid, count, topicStrings);
+	assert("good rc from serialize unsubscribe", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_unsubscribe(&dup2, &msgid2, 2, &count2, topicStrings2, buf, buflen);
+	assert("good rc from deserialize unsubscribe", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("dups should be the same", dup == dup2, "dups were different %d\n", dup2);
+	assert("msgids should be the same", msgid == msgid2, "msgids were different %d\n", msgid2);
+
+	assert("count should be the same", count == count2, "counts were different %d\n", count2);
+
+	for (i = 0; i < count2; ++i)
+		assert("topics should be the same",
+					checkMQTTStrings(topicStrings[i], topicStrings2[i]), "topics were different %s\n", "");
+
+/* exit: */
+	MyLog(LOGA_INFO, "TEST5: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int test6(struct Options options)
+{
+	int rc = 0;
+	char buf[100];
+	int buflen = sizeof(buf);
+
+	int connack_rc = 77;
+
+	int connack_rc2 = 0;
+
+	fprintf(xml, "<testcase classname=\"test1\" name=\"de/serialization\"");
+	global_start_time = start_clock();
+	failures = 0;
+	MyLog(LOGA_INFO, "Starting test 2 - serialization of connack and back");
+
+	rc = MQTTSerialize_connack(buf, buflen, connack_rc);
+	assert("good rc from serialize connack", rc > 0, "rc was %d\n", rc);
+
+	rc = MQTTDeserialize_connack(&connack_rc2, buf, buflen);
+	assert("good rc from deserialize connack", rc == 1, "rc was %d\n", rc);
+
+	/* data after should be the same as data before */
+	assert("dups should be the same", connack_rc == connack_rc2, "dups were different %d\n", connack_rc2);
+
+/* exit: */
+	MyLog(LOGA_INFO, "TEST6: test %s. %d tests run, %d failures.",
+			(failures == 0) ? "passed" : "failed", tests, failures);
+	write_test_result();
+	return failures;
+}
+
+
+int main(int argc, char** argv)
+{
+	int rc = 0;
+ 	int (*tests[])() = {NULL, test1, test2, test3, test4, test5, test6};
+
+	xml = fopen("TEST-test1.xml", "w");
+	fprintf(xml, "<testsuite name=\"test1\" tests=\"%d\">\n", (int)(ARRAY_SIZE(tests) - 1));
+
+	getopts(argc, argv);
+
+ 	if (options.test_no == 0)
+	{ /* run all the tests */
+ 	   	for (options.test_no = 1; options.test_no < ARRAY_SIZE(tests); ++options.test_no)
+			rc += tests[options.test_no](options); /* return number of failures.  0 = test succeeded */
+	}
+	else
+ 	   	rc = tests[options.test_no](options); /* run just the selected test */
+
+ 	if (rc == 0)
+		MyLog(LOGA_INFO, "verdict pass");
+	else
+		MyLog(LOGA_INFO, "verdict fail");
+
+	fprintf(xml, "</testsuite>\n");
+	fclose(xml);
+	return rc;
+}
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTSManager.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTSManager.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,133 @@
+#include "MQTTSManager.h"
+#include "XbeeMonitor.h"
+#include "Utils.h"
+#include "jsmn.h"
+#include <string>
+
+using namespace MQTT;
+
+#define MQTTS_PORT  8883
+
+static const char * topic_update = "garden_update";
+static const char * topic_listen = "garden_status";
+static const char * hostname = "mqtt.mbedhacks.com";
+static const char * clientID = "mbed-sample";
+static const char * username = "mbedhacks";
+static const char * password = "qwer123";
+
+static MQTTThreadedClient * pmqtt = NULL;
+Thread mqttThd(osPriorityNormal, DEFAULT_STACK_SIZE * 2);
+RadioControlData postdata;
+static char tempbuff[100];
+
+static int jsoneq(const char * json, jsmntok_t * tok, const char * s)
+{
+    if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
+        strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
+            return 0;
+    }
+    return -1;    
+}
+
+void messageArrived(MessageData& md)
+{
+    int i, r;
+    
+    jsmn_parser p;
+    jsmntok_t t[100];
+        
+    Message &message = md.message;
+    printf("Arrived Callback 1 : qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id);
+    printf("Payload [%.*s]\r\n", message.payloadlen, (char*)message.payload);
+    
+    // handle payload
+    const char * jsonstring = std::string((const char *) message.payload, message.payloadlen).c_str();
+    
+    jsmn_init(&p);
+    r = jsmn_parse(&p, jsonstring, strlen(jsonstring), t, sizeof(t)/sizeof(t[0]));
+    
+    uint64_t radio_id = 0;
+    int sprinkler_pin = 1; // 0 - turn on sprinkler, 1 - off
+    
+    /* Top level element is an object */
+    if ((r > 0) && (t[0].type == JSMN_OBJECT)) 
+    { 
+        /* Loop over all tokens */
+        for (i = 1; i < r; i++)
+        {
+            if (jsoneq(jsonstring, &t[i], "radioid") == 0)
+            {
+                memset(tempbuff, 0, sizeof(tempbuff));                
+                strncpy(tempbuff, jsonstring + t[i+1].start, t[i+1].end - t[i+1].start);
+                radio_id = strtoull(&tempbuff[0], NULL, 0);
+                i++;                
+            }
+            else if (jsoneq(jsonstring, &t[i], "sprinkler") == 0)
+            {
+                memset(tempbuff, 0, sizeof(tempbuff));
+                strncpy(tempbuff, jsonstring + t[i+1].start, t[i+1].end - t[i+1].start);
+                sprinkler_pin = strtoul(&tempbuff[0], NULL, 0);
+                i++;
+            }
+            else
+            {
+                
+            }
+        }    
+    }
+    
+    // TODO: Send the values to the XBeeMonitor thread
+    printf("Radio ID: %llu\r\n", radio_id);
+    printf("Sprinkler Pin : %d\r\n", sprinkler_pin);
+    postdata.radioID = radio_id;
+    postdata.sprinkler_pin = sprinkler_pin;
+    postRadioControl(postdata);
+}
+
+int mqttsInit(NetworkInterface * net, const char * pem)
+{
+    pmqtt = new MQTTThreadedClient(net, pem);
+    if (pmqtt == NULL) 
+        return -1;
+    
+    MQTTPacket_connectData logindata = MQTTPacket_connectData_initializer;
+    logindata.MQTTVersion = 3;
+    logindata.clientID.cstring = (char *) clientID;
+    logindata.username.cstring = (char *) username;
+    logindata.password.cstring = (char *) password;
+    
+    pmqtt->setConnectionParameters(hostname, MQTTS_PORT, logindata);
+    pmqtt->addTopicHandler(topic_listen, messageArrived);
+    
+    return 0;
+}
+
+void postMQTTUpdate(SensorData &msg)
+{
+    // Serialize data to json string ...
+    if (pmqtt)
+    {
+        PubMessage message;
+        message.qos = QOS0;
+        message.id = 123;
+        
+        strcpy(&message.topic[0], topic_update);
+        size_t numbytes = snprintf(&message.payload[0], MAX_MQTT_PAYLOAD_SIZE,
+                "{\"radio\":%llu,\"status\":{\"sprinkler\":%d,\"humidity\":%d,\"temperature\":%.2f,\"luminance\":%d}}", 
+                msg.deviceaddr,
+                msg.sprinkler,
+                msg.humidity,
+                msg.temperature,
+                msg.luminance);
+        printf("[%s]\r\n", &message.payload[0]);
+        message.payloadlen = numbytes;
+        pmqtt->publish(message);
+    }
+}
+
+int runMQTTS()
+{
+    if ( pmqtt && (mqttThd.start(mbed::callback(pmqtt, &MQTTThreadedClient::startListener)) != osOK ) )
+        return -1;
+    return 0;
+}
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTSManager.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTSManager.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,13 @@
+#ifndef _MQTTS_MANAGER_H_
+#define _MQTTS_MANAGER_H_
+
+
+#include "MQTTThreadedClient.h"
+#include "Sensor.h"
+
+
+int mqttsInit(NetworkInterface * net, const char * pem);
+void postMQTTUpdate(SensorData &msg);
+int runMQTTS();
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTThreadedClient.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTThreadedClient.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,941 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "MQTTThreadedClient.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/error.h"
+
+#ifdef DEBUG
+#define DBG(fmt, args...)    printf(fmt, ## args)
+#else
+#define DBG(fmt, args...)    /* Don't do anything in release builds */
+#endif
+
+static MemoryPool<MQTT::PubMessage, 4> mpool;
+static Queue<MQTT::PubMessage, 4> mqueue;
+
+// SSL/TLS variables
+mbedtls_entropy_context _entropy;
+mbedtls_ctr_drbg_context _ctr_drbg;
+mbedtls_x509_crt _cacert;
+mbedtls_ssl_context _ssl;
+mbedtls_ssl_config _ssl_conf;    
+mbedtls_ssl_session saved_session;
+
+namespace MQTT {
+    
+/**
+ * Receive callback for mbed TLS
+ */
+static int ssl_recv(void *ctx, unsigned char *buf, size_t len)
+{
+    int recv = -1;
+    TCPSocket *socket = static_cast<TCPSocket *>(ctx);
+    socket->set_timeout(DEFAULT_SOCKET_TIMEOUT);
+    recv = socket->recv(buf, len);
+
+    if (NSAPI_ERROR_WOULD_BLOCK == recv) {
+        return MBEDTLS_ERR_SSL_WANT_READ;
+    } else if (recv < 0) {
+        return -1;
+    } else {
+        return recv;
+    }
+}
+
+/**
+ * Send callback for mbed TLS
+ */
+static int ssl_send(void *ctx, const unsigned char *buf, size_t len)
+{
+    int sent = -1;
+    TCPSocket *socket = static_cast<TCPSocket *>(ctx);
+    socket->set_timeout(DEFAULT_SOCKET_TIMEOUT);    
+    sent = socket->send(buf, len);
+
+    if(NSAPI_ERROR_WOULD_BLOCK == sent) {
+        return MBEDTLS_ERR_SSL_WANT_WRITE;
+    } else if (sent < 0) {
+        return -1;
+    } else {
+        return sent;
+    }
+}
+
+#if DEBUG_LEVEL > 0
+/**
+ * Debug callback for mbed TLS
+ * Just prints on the USB serial port
+ */
+static void my_debug(void *ctx, int level, const char *file, int line,
+                     const char *str)
+{
+    const char *p, *basename;
+    (void) ctx;
+
+    /* Extract basename from file */
+    for(p = basename = file; *p != '\0'; p++) {
+        if(*p == '/' || *p == '\\') {
+            basename = p + 1;
+        }
+    }
+
+    if (_debug) {
+        mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str);
+    }
+}
+
+/**
+ * Certificate verification callback for mbed TLS
+ * Here we only use it to display information on each cert in the chain
+ */
+static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
+{
+    const uint32_t buf_size = 1024;
+    char *buf = new char[buf_size];
+    (void) data;
+
+    if (_debug) mbedtls_printf("\nVerifying certificate at depth %d:\r\n", depth);
+    mbedtls_x509_crt_info(buf, buf_size - 1, "  ", crt);
+    if (_debug) mbedtls_printf("%s", buf);
+
+    if (*flags == 0)
+        if (_debug) mbedtls_printf("No verification issue for this certificate\r\n");
+        else {
+            mbedtls_x509_crt_verify_info(buf, buf_size, "  ! ", *flags);
+            if (_debug) mbedtls_printf("%s\n", buf);
+        }
+
+    delete[] buf;
+    return 0;
+}
+#endif
+
+
+void MQTTThreadedClient::setupTLS()    
+{
+        if (useTLS)
+        {
+            mbedtls_entropy_init(&_entropy);
+            mbedtls_ctr_drbg_init(&_ctr_drbg);
+            mbedtls_x509_crt_init(&_cacert);
+            mbedtls_ssl_init(&_ssl);
+            mbedtls_ssl_config_init(&_ssl_conf);        
+            memset( &saved_session, 0, sizeof( mbedtls_ssl_session ) );            
+        }    
+}
+
+void MQTTThreadedClient::freeTLS()
+{
+        if (useTLS)
+        {
+            mbedtls_entropy_free(&_entropy);
+            mbedtls_ctr_drbg_free(&_ctr_drbg);
+            mbedtls_x509_crt_free(&_cacert);
+            mbedtls_ssl_free(&_ssl);
+            mbedtls_ssl_config_free(&_ssl_conf);               
+        }    
+}
+
+int MQTTThreadedClient::initTLS()
+{
+        int ret;
+        
+        DBG("Initializing TLS ...\r\n");
+        DBG("mbedtls_ctr_drdbg_seed ...\r\n");
+        if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy,
+                          (const unsigned char *) DRBG_PERS,
+                          sizeof (DRBG_PERS))) != 0) {
+            mbedtls_printf("mbedtls_crt_drbg_init returned [%x]\r\n", ret);
+            _error = ret;
+            return -1;
+        }
+        DBG("mbedtls_x509_crt_parse ...\r\n");
+        if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *) ssl_ca_pem,
+                           strlen(ssl_ca_pem) + 1)) != 0) {
+            mbedtls_printf("mbedtls_x509_crt_parse returned [%x]\r\n", ret);
+            _error = ret;
+            return -1;
+        }
+
+        DBG("mbedtls_ssl_config_defaults ...\r\n");
+        if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf,
+                        MBEDTLS_SSL_IS_CLIENT,
+                        MBEDTLS_SSL_TRANSPORT_STREAM,
+                        MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
+            mbedtls_printf("mbedtls_ssl_config_defaults returned [%x]\r\n", ret);
+            _error = ret;
+            return -1;
+        }
+
+        DBG("mbedtls_ssl_config_ca_chain ...\r\n");
+        mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL);
+        DBG("mbedtls_ssl_conf_rng ...\r\n");
+        mbedtls_ssl_conf_rng(&_ssl_conf, mbedtls_ctr_drbg_random, &_ctr_drbg);
+
+        /* It is possible to disable authentication by passing
+         * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
+         */
+        DBG("mbedtls_ssl_conf_authmode ...\r\n");         
+        mbedtls_ssl_conf_authmode(&_ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+
+#if DEBUG_LEVEL > 0
+        mbedtls_ssl_conf_verify(&_ssl_conf, my_verify, NULL);
+        mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL);
+        mbedtls_debug_set_threshold(DEBUG_LEVEL);
+#endif
+
+        DBG("mbedtls_ssl_setup ...\r\n");         
+        if ((ret = mbedtls_ssl_setup(&_ssl, &_ssl_conf)) != 0) {
+            mbedtls_printf("mbedtls_ssl_setup returned [%x]\r\n", ret);
+            _error = ret;
+            return -1;
+        }
+        
+        return 0;
+}
+
+int MQTTThreadedClient::doTLSHandshake()
+{
+        int ret;
+        
+        /* Start the handshake, the rest will be done in onReceive() */
+        DBG("Starting the TLS handshake...\r\n");
+        ret = mbedtls_ssl_handshake(&_ssl);
+        if (ret < 0) 
+        {
+            if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
+                ret != MBEDTLS_ERR_SSL_WANT_WRITE) 
+                    mbedtls_printf("mbedtls_ssl_handshake returned [%x]\r\n", ret);
+            else 
+            {
+                // do not close the socket if timed out
+                ret = TIMEOUT;
+            }
+            return ret;
+        }
+
+        /* Handshake done, time to print info */
+        DBG("TLS connection to %s:%d established\r\n", 
+            host.c_str(), port);
+
+        const uint32_t buf_size = 1024;
+        char *buf = new char[buf_size];
+        mbedtls_x509_crt_info(buf, buf_size, "\r    ",
+                        mbedtls_ssl_get_peer_cert(&_ssl));
+                        
+        DBG("Server certificate:\r\n%s\r", buf);
+        // Verify server cert ...
+        uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl);
+        if( flags != 0 )
+        {
+            mbedtls_x509_crt_verify_info(buf, buf_size, "\r  ! ", flags);
+            DBG("Certificate verification failed:\r\n%s\r\r\n", buf);
+            // free server cert ... before error return
+            delete [] buf;
+            return -1;
+        }
+        
+        DBG("Certificate verification passed\r\n\r\n");
+        // delete server cert after verification
+        delete [] buf;
+        
+#if defined(MBEDTLS_SSL_CLI_C)        
+        // TODO: Save the session here for reconnect.
+        if( ( ret = mbedtls_ssl_get_session( &_ssl, &saved_session ) ) != 0 )
+        {
+            mbedtls_printf( "mbedtls_ssl_get_session returned -0x%x\n\n", -ret );
+            hasSavedSession = false;
+            return -1;
+        }  
+#endif        
+        DBG("Session saved for reconnect ...\r\n");     
+        hasSavedSession = true;
+        
+        return 0;
+}
+
+int MQTTThreadedClient::readBytesToBuffer(char * buffer, size_t size, int timeout)
+{
+    int rc;
+
+    if (tcpSocket == NULL)
+        return -1;
+
+    if (useTLS) 
+    {
+        // Do SSL/TLS read
+        rc = mbedtls_ssl_read(&_ssl, (unsigned char *) buffer, size);
+        if (MBEDTLS_ERR_SSL_WANT_READ == rc)
+            return TIMEOUT;
+        else
+            return rc;
+    } else {
+        // non-blocking socket ...
+        tcpSocket->set_timeout(timeout);
+        rc = tcpSocket->recv( (void *) buffer, size);
+
+        // return 0 bytes if timeout ...
+        if (NSAPI_ERROR_WOULD_BLOCK == rc)
+            return TIMEOUT;
+        else
+            return rc; // return the number of bytes received or error
+    }
+}
+
+int MQTTThreadedClient::sendBytesFromBuffer(char * buffer, size_t size, int timeout)
+{
+    int rc;
+    
+    if (tcpSocket == NULL)
+        return -1;
+    
+    if (useTLS) {
+        // Do SSL/TLS write
+        rc =  mbedtls_ssl_write(&_ssl, (const unsigned char *) buffer, size);
+        if (MBEDTLS_ERR_SSL_WANT_WRITE == rc)
+            return TIMEOUT;
+        else
+            return rc;
+    } else {
+
+        // set the write timeout
+        tcpSocket->set_timeout(timeout);
+        rc = tcpSocket->send(buffer, size);
+
+        if ( NSAPI_ERROR_WOULD_BLOCK == rc)
+            return TIMEOUT;
+        else
+            return rc;
+    }
+}
+
+int MQTTThreadedClient::readPacketLength(int* value)
+{
+    int rc = MQTTPACKET_READ_ERROR;
+    unsigned char c;
+    int multiplier = 1;
+    int len = 0;
+    const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
+
+    *value = 0;
+    do
+    {
+        if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+        {
+            rc = MQTTPACKET_READ_ERROR; /* bad data */
+            goto exit;
+        }
+        
+        rc = readBytesToBuffer((char *) &c, 1, DEFAULT_SOCKET_TIMEOUT);
+        if (rc != 1)
+        {
+            rc = MQTTPACKET_READ_ERROR;
+            goto exit;
+        }
+            
+        *value += (c & 127) * multiplier;
+        multiplier *= 128;
+    } while ((c & 128) != 0);
+    
+    rc = MQTTPACKET_READ_COMPLETE;
+        
+exit:
+    if (rc == MQTTPACKET_READ_ERROR )
+        len = -1;
+    
+    return len;
+}
+
+int MQTTThreadedClient::sendPacket(size_t length)
+{
+    int rc = FAILURE;
+    int sent = 0;
+
+    while (sent < length)
+    {
+        rc = sendBytesFromBuffer((char *) &sendbuf[sent], length - sent, DEFAULT_SOCKET_TIMEOUT);
+        if (rc < 0)  // there was an error writing the data
+            break;
+        sent += rc;
+    }
+    
+    if (sent == length)
+        rc = SUCCESS;
+    else
+        rc = FAILURE;
+        
+    return rc;
+}
+/**
+ * Reads the entire packet to readbuf and returns
+ * the type of packet when successful, otherwise
+ * a negative error code is returned.
+ **/
+int MQTTThreadedClient::readPacket()
+{
+    int rc = FAILURE;
+    MQTTHeader header = {0};
+    int len = 0;
+    int rem_len = 0;
+
+    /* 1. read the header byte.  This has the packet type in it */
+    if ( (rc = readBytesToBuffer((char *) &readbuf[0], 1, DEFAULT_SOCKET_TIMEOUT)) != 1)
+        goto exit;
+
+    len = 1;
+    /* 2. read the remaining length.  This is variable in itself */
+    if ( readPacketLength(&rem_len) < 0 )
+        goto exit;
+        
+    len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length into the buffer */
+
+    if (rem_len > (MAX_MQTT_PACKET_SIZE - len))
+    {
+        rc = BUFFER_OVERFLOW;
+        goto exit;
+    }
+
+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+    if (rem_len > 0 && (readBytesToBuffer((char *) (readbuf + len), rem_len, DEFAULT_SOCKET_TIMEOUT) != rem_len))
+        goto exit;
+
+    // Convert the header to type
+    // and update rc
+    header.byte = readbuf[0];
+    rc = header.bits.type;
+    
+exit:
+
+    return rc;    
+}
+
+/**
+ * Read until a specified packet type is received, or untill the specified
+ * timeout dropping packets along the way.
+ **/
+int MQTTThreadedClient::readUntil(int packetType, int timeout)
+{
+    int pType = FAILURE;
+    Timer timer;
+    
+    timer.start();
+    do {
+        pType = readPacket();
+        if (pType < 0)
+            break;
+            
+        if (timer.read_ms() > timeout)
+        {
+            pType = FAILURE;
+            break;
+        }
+    }while(pType != packetType);
+    
+    return pType;    
+}
+
+
+int MQTTThreadedClient::login()
+{
+    int rc = FAILURE;
+    int len = 0;
+
+    if (!isConnected)
+    {
+        DBG("Session not connected! \r\n");
+        return rc;
+    }
+        
+    // Copy the keepAliveInterval value to local
+    // MQTT specifies in seconds, we have to multiply that
+    // amount for our 32 bit timers which accepts ms.
+    keepAliveInterval = (connect_options.keepAliveInterval * 1000);
+    
+    DBG("Login with: \r\n");
+    DBG("\tUsername: [%s]\r\n", connect_options.username.cstring);
+    DBG("\tPassword: [%s]\r\n", connect_options.password.cstring);
+    
+    if ((len = MQTTSerialize_connect(sendbuf, MAX_MQTT_PACKET_SIZE, &connect_options)) <= 0)
+    {
+        DBG("Error serializing connect packet ...\r\n");
+        return rc;
+    }
+    if ((rc = sendPacket((size_t) len)) != SUCCESS)  // send the connect packet
+    {
+        DBG("Error sending the connect request packet ...\r\n");
+        return rc; 
+    }
+    
+    // Wait for the CONNACK 
+    if (readUntil(CONNACK, COMMAND_TIMEOUT) == CONNACK)
+    {
+        unsigned char connack_rc = 255;
+        bool sessionPresent = false;
+        DBG("Connection acknowledgement received ... deserializing respones ...\r\n");
+        if (MQTTDeserialize_connack((unsigned char*)&sessionPresent, &connack_rc, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+            rc = connack_rc;
+        else
+            rc = FAILURE;
+    }
+    else
+        rc = FAILURE;
+
+    if (rc == SUCCESS)
+    {
+        DBG("Connected!!! ... starting connection timers ...\r\n");
+        resetConnectionTimer();
+    }
+    
+    DBG("Returning with rc = %d\r\n", rc);
+    
+    return rc;    
+}
+
+
+void MQTTThreadedClient::disconnect()
+{
+    if (isConnected)
+    {
+        if( useTLS 
+            && ( mbedtls_ssl_session_reset( &_ssl ) != 0 )
+           )
+        {
+            DBG( "Session reset returned an error \r\n");
+        }        
+        
+        isConnected = false;
+        tcpSocket->close();      
+    }
+}
+
+int MQTTThreadedClient::connect()
+{
+    int ret = FAILURE;
+
+    if ((network == NULL) || (tcpSocket == NULL)
+        || host.empty())
+    {
+        DBG("Network settings not set! \r\n");
+        return ret;
+    }
+    
+    if (useTLS) 
+    {
+        if( ( ret = mbedtls_ssl_session_reset( &_ssl ) ) != 0 ) {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret );
+            return ret;
+        }
+#if defined(MBEDTLS_SSL_CLI_C)
+        if ( hasSavedSession && (( ret = mbedtls_ssl_set_session( &_ssl, &saved_session ) ) != 0 )) {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_session returned %d\n\n", ret );
+            return ret;
+        }
+#endif        
+    }
+        
+    tcpSocket->open(network);
+    if (useTLS)
+    {
+        DBG("mbedtls_ssl_set_hostname ...\r\n");         
+        mbedtls_ssl_set_hostname(&_ssl, host.c_str());
+        DBG("mbedtls_ssl_set_bio ...\r\n");         
+        mbedtls_ssl_set_bio(&_ssl, static_cast<void *>(tcpSocket),
+                                   ssl_send, ssl_recv, NULL );
+    }
+    
+    if (( ret = tcpSocket->connect(host.c_str(), port)) < 0 )
+    {
+         DBG("Error connecting to %s:%d with %d\r\n", host.c_str(), port, ret);
+         return ret;
+    }else
+         isConnected = true;
+    
+    if (useTLS) 
+    {
+        
+        if (doTLSHandshake() < 0)
+        {
+            DBG("TLS Handshake failed! \r\n");
+            return FAILURE;
+        }else
+            DBG("TLS Handshake complete!! \r\n");
+    }
+    
+    return login();
+}
+
+void MQTTThreadedClient::setConnectionParameters(const char * chost, uint16_t cport, MQTTPacket_connectData & options)
+{
+    // Copy the settings for reconnection
+    host = chost;
+    port = cport;
+    connect_options = options;    
+}
+
+int MQTTThreadedClient::publish(PubMessage& msg)
+{
+#if 0
+    int id = queue.call(mbed::callback(this, &MQTTThreadedClient::sendPublish), topic, message);
+    // TODO: handle id values when the function is called later
+    if (id == 0)
+        return FAILURE;
+    else
+        return SUCCESS;
+#endif
+    PubMessage *message = mpool.alloc();
+    // Simple copy
+    *message = msg;
+    
+    // Push the data to the thread
+    DBG("[Thread:%d] Pushing data to consumer thread ...\r\n", Thread::gettid());
+    mqueue.put(message);
+    
+    return SUCCESS;
+}
+
+int MQTTThreadedClient::sendPublish(PubMessage& message)
+{
+     MQTTString topicString = MQTTString_initializer;
+     
+     if (!isConnected) 
+     {
+        DBG("[Thread:%d] Not connected!!! ...\r\n", Thread::gettid());
+        return FAILURE;
+     }
+        
+     topicString.cstring = (char*) &message.topic[0];
+     int len = MQTTSerialize_publish(sendbuf, MAX_MQTT_PACKET_SIZE, 0, message.qos, false, message.id,
+              topicString, (unsigned char*) &message.payload[0], (int) message.payloadlen);
+     if (len <= 0)
+     {
+         DBG("[Thread:%d]Failed serializing message ...\r\n", Thread::gettid());
+         return FAILURE;
+     }
+     
+     if (sendPacket(len) == SUCCESS)
+     {
+         DBG("[Thread:%d]Successfully sent publish packet to server ...\r\n", Thread::gettid());
+         return SUCCESS;
+     }
+    
+    DBG("[Thread:%d]Failed to send publish packet to server ...\r\n", Thread::gettid());
+    return FAILURE;
+}
+
+void MQTTThreadedClient::addTopicHandler(const char * topicstr, void (*function)(MessageData &))
+{
+    // Push the subscription into the map ...
+    FP<void,MessageData &> fp;
+    fp.attach(function);
+    
+    topicCBMap.insert(std::pair<std::string, FP<void,MessageData &> >(std::string(topicstr),fp));    
+} 
+
+int MQTTThreadedClient::processSubscriptions()
+{
+    int numsubscribed = 0;
+    
+    if (!isConnected) 
+    {
+            DBG("Session not connected!!\r\n");
+            return 0;
+    }
+    
+    DBG("Processing subscribed topics ....\r\n");
+    
+    std::map<std::string, FP<void, MessageData &> >::iterator it;
+    for(it = topicCBMap.begin(); it != topicCBMap.end(); it++) 
+    {
+        int rc = FAILURE;
+        int len = 0;
+        //TODO: We only subscribe to QoS = 0 for now
+        QoS qos = QOS0;
+
+        MQTTString topic = {(char*)it->first.c_str(), {0, 0}};
+        DBG("Subscribing to topic [%s]\r\n", topic.cstring);
+
+
+        len = MQTTSerialize_subscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos);
+        if (len <= 0) {
+            DBG("Error serializing subscribe packet ...\r\n");
+            continue;
+        }
+
+        if ((rc = sendPacket(len)) != SUCCESS) {
+            DBG("Error sending subscribe packet [%d]\r\n", rc);
+            continue;
+        }
+
+        DBG("Waiting for subscription ack ...\r\n");
+        // Wait for SUBACK, dropping packets read along the way ...
+        if (readUntil(SUBACK, COMMAND_TIMEOUT) == SUBACK) { // wait for suback
+            int count = 0, grantedQoS = -1;
+            unsigned short mypacketid;
+            if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+                rc = grantedQoS; // 0, 1, 2 or 0x80
+            // For as long as we do not get 0x80 ..
+            if (rc != 0x80) 
+            {
+                // Reset connection timers here ...
+                resetConnectionTimer();
+                DBG("Successfully subscribed to %s ...\r\n", it->first.c_str());
+                numsubscribed++;
+            } else {
+                DBG("Failed to subscribe to topic %s ... (not authorized?)\r\n", it->first.c_str());
+            }
+        } else 
+            DBG("Failed to subscribe to topic %s (ack not received) ...\r\n", it->first.c_str());
+    } // end for loop
+    
+    return numsubscribed;    
+}
+
+bool MQTTThreadedClient::isTopicMatched(char* topicFilter, MQTTString& topicName)
+{
+    char* curf = topicFilter;
+    char* curn = topicName.lenstring.data;
+    char* curn_end = curn + topicName.lenstring.len;
+
+    while (*curf && curn < curn_end)
+    {
+        if (*curn == '/' && *curf != '/')
+            break;
+        if (*curf != '+' && *curf != '#' && *curf != *curn)
+            break;
+        if (*curf == '+')
+        {   // skip until we meet the next separator, or end of string
+            char* nextpos = curn + 1;
+            while (nextpos < curn_end && *nextpos != '/')
+                nextpos = ++curn + 1;
+        }
+        else if (*curf == '#')
+            curn = curn_end - 1;    // skip until end of string
+        curf++;
+        curn++;
+    };
+
+    return (curn == curn_end) && (*curf == '\0');
+}
+
+int MQTTThreadedClient::handlePublishMsg()
+{
+    MQTTString topicName = MQTTString_initializer;
+    Message msg;
+    int intQoS;
+    DBG("[Thread:%d]Deserializing publish message ...\r\n", Thread::gettid());
+    if (MQTTDeserialize_publish((unsigned char*)&msg.dup, 
+            &intQoS, 
+            (unsigned char*)&msg.retained, 
+            (unsigned short*)&msg.id, 
+            &topicName,
+            (unsigned char**)&msg.payload, 
+            (int*)&msg.payloadlen, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+    {
+        DBG("[Thread:%d]Error deserializing published message ...\r\n", Thread::gettid());
+        return -1;
+    }
+
+    std::string topic;
+    if (topicName.lenstring.len > 0)
+    {
+        topic = std::string((const char *) topicName.lenstring.data, (size_t) topicName.lenstring.len);
+    }else
+        topic = (const char *) topicName.cstring;
+    
+    DBG("[Thread:%d]Got message for topic [%s], QoS [%d] ...\r\n", Thread::gettid(), topic.c_str(), intQoS);
+    
+    msg.qos = (QoS) intQoS;
+
+    
+    // Call the handlers for each topic 
+    if (topicCBMap.find(topic) != topicCBMap.end())
+    {
+        // Call the callback function 
+        if (topicCBMap[topic].attached())
+        {
+            DBG("[Thread:%d]Invoking function handler for topic ...\r\n", Thread::gettid());
+            MessageData md(topicName, msg);            
+            topicCBMap[topic](md);
+            
+            return 1;
+        }
+    }
+    
+    // TODO: depending on the QoS
+    // we send data to the server = PUBACK or PUBREC
+    switch(intQoS)
+    {
+        case QOS0:
+            // We send back nothing ...
+            break;
+        case QOS1:
+            // TODO: implement
+            break;
+        case QOS2:
+            // TODO: implement
+            break;
+        default:
+            break;
+    }
+    
+    return 0;
+}
+
+void MQTTThreadedClient::resetConnectionTimer()
+{
+    if (keepAliveInterval > 0)
+    {
+        comTimer.reset();
+        comTimer.start();
+    }
+}
+
+bool MQTTThreadedClient::hasConnectionTimedOut()
+{
+    if (keepAliveInterval > 0 ) {
+        // Check connection timer
+        if (comTimer.read_ms() > keepAliveInterval)
+            return true;
+        else
+            return false;
+    }
+
+    return false;
+}
+        
+void MQTTThreadedClient::sendPingRequest()
+{
+    int len = MQTTSerialize_pingreq(sendbuf, MAX_MQTT_PACKET_SIZE);
+    if (len > 0 && (sendPacket(len) == SUCCESS)) // send the ping packet
+    {
+        printf("MQTT Ping request sent successfully ...\r\n");
+    }
+}
+
+void MQTTThreadedClient::startListener()
+{
+    int pType;
+    int numsubs;
+    // Continuesly listens for packets and dispatch
+    // message handlers ...
+    if (useTLS)
+    {
+        initTLS();
+    }
+            
+    while(true)
+    {
+
+        // Attempt to reconnect and login
+        if ( connect() < 0 )
+        {
+            disconnect();
+            // Wait for a few secs and reconnect ...
+            Thread::wait(6000);
+            continue;
+        }
+        
+        numsubs = processSubscriptions();
+        DBG("Subscribed %d topics ...\r\n", numsubs);
+         
+        // loop read    
+        while(true) 
+        {
+            pType = readPacket();
+            switch(pType) 
+            {
+                case TIMEOUT:
+                    // No data available from the network ...
+                    break;
+                case FAILURE:
+                    {
+                        DBG("readPacket returned failure \r\n");
+                        goto reconnect;
+                    }
+                case BUFFER_OVERFLOW: 
+                    {
+                        // TODO: Network error, do we disconnect and reconnect?
+                        DBG("[Thread:%d]Failure or buffer overflow problem ... \r\n", Thread::gettid());
+                        MBED_ASSERT(false);
+                    }
+                    break;
+                /**
+                *  The rest of the return codes below (all positive) is about MQTT
+                 * response codes
+                 **/
+                case CONNACK:
+                case PUBACK:
+                case SUBACK:
+                    break;
+                case PUBLISH: 
+                    {
+                        DBG("[Thread:%d]Publish received!....\r\n", Thread::gettid());
+                        // We receive data from the MQTT server ..
+                        if (handlePublishMsg() < 0) {
+                            DBG("[Thread:%d]Error handling PUBLISH message ... \r\n", Thread::gettid());
+                            break;
+                        }
+                    }
+                    break;
+                case PINGRESP: 
+                    {
+                        printf("MQTT Got ping response ...\r\n");
+                        resetConnectionTimer();
+                    }
+                    break;
+                default:
+                    DBG("[Thread:%d]Unknown/Not handled message from server pType[%d]\r\n", Thread::gettid(), pType);
+            }
+
+            // Check if its time to send a keepAlive packet
+            if (hasConnectionTimedOut()) {
+                // Queue the ping request so that other
+                // pending operations queued above will go first
+                queue.call(this, &MQTTThreadedClient::sendPingRequest);
+            }
+
+            // Check if we have messages on the message queue
+            osEvent evt = mqueue.get(10);
+            if (evt.status == osEventMessage) {
+
+                DBG("[Thread:%d]Got message to publish! ... \r\n", Thread::gettid());
+
+                // Unpack the message
+                PubMessage * message = (PubMessage *)evt.value.p;
+
+                // Send the packet, do not queue the call
+                // like the ping above ..
+                if ( sendPublish(*message) == SUCCESS) {
+                    // Reset timers if we have been able to send successfully
+                    resetConnectionTimer();
+                } else {
+                    // Disconnected?
+                    goto reconnect;
+                }
+
+                // Free the message from mempool  after using
+                mpool.free(message);
+            }
+
+            // Dispatch any queued events ...
+            queue.dispatch(100);
+        } // end while loop
+
+reconnect:
+        // reconnect?
+        DBG("Client disconnected!! ... retrying ...\r\n");
+        disconnect();
+        
+    };
+}
+
+void MQTTThreadedClient::stopListener()
+{
+    // TODO: Set a signal/flag that the running thread 
+    // will check if its ok to stop ...
+}
+
+}
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b MQTTSManager/MQTTThreadedClient.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTTSManager/MQTTThreadedClient.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,197 @@
+#ifndef _MQTT_THREADED_CLIENT_H_
+#define _MQTT_THREADED_CLIENT_H_
+
+#include "mbed.h"
+#include "rtos.h"
+#include "MQTTPacket.h"
+#include "NetworkInterface.h"
+#include "FP.h"
+#include "config.h"
+
+#include <cstdio>
+#include <string>
+#include <map>
+
+//#define MQTT_DEBUG 1
+
+
+#define COMMAND_TIMEOUT 5000
+#define DEFAULT_SOCKET_TIMEOUT 1000
+#define MAX_MQTT_PACKET_SIZE 500
+#define MAX_MQTT_PAYLOAD_SIZE 300
+
+namespace MQTT
+{
+    
+typedef enum { QOS0, QOS1, QOS2 } QoS;
+
+// all failure return codes must be negative
+typedef enum { BUFFER_OVERFLOW = -3, TIMEOUT = -2, FAILURE = -1, SUCCESS = 0 } returnCode;
+
+
+typedef struct
+{
+    QoS qos;
+    bool retained;
+    bool dup;
+    unsigned short id;
+    void *payload;
+    size_t payloadlen;
+}Message, *pMessage;
+
+// TODO:
+// Merge this struct with the one above, in order to use the same
+// data structure for sending and receiving. I need to simplify
+// the PubMessage to not contain pointers like the one above.
+typedef struct
+{
+    char topic[100];
+    QoS qos;
+    unsigned short id;
+    size_t payloadlen;
+    char payload[MAX_MQTT_PAYLOAD_SIZE];
+}PubMessage, *pPubMessage;
+
+struct MessageData
+{
+    MessageData(MQTTString &aTopicName, Message &aMessage)  : message(aMessage), topicName(aTopicName)
+    { }
+    Message &message;
+    MQTTString &topicName;
+};
+
+class PacketId
+{
+public:
+    PacketId()
+    {
+        next = 0;
+    }
+
+    int getNext()
+    {
+        return next = (next == MAX_PACKET_ID) ? 1 : ++next;
+    }
+
+private:
+    static const int MAX_PACKET_ID = 65535;
+    int next;
+};
+
+
+
+class MQTTThreadedClient
+{
+public:
+    MQTTThreadedClient(NetworkInterface * aNetwork, const char * pem = NULL)
+        : network(aNetwork),
+          ssl_ca_pem(pem),
+          port((pem != NULL) ? 8883 : 1883),
+          queue(32 * EVENTS_EVENT_SIZE),
+          isConnected(false),          
+          hasSavedSession(false),
+          useTLS(pem != NULL)
+    {
+        DRBG_PERS = "mbed TLS MQTT client";
+        tcpSocket = new TCPSocket();
+        setupTLS();
+    }
+    
+    ~MQTTThreadedClient()
+    {
+        // TODO: signal the thread to shutdown
+        freeTLS();
+           
+        if (isConnected)
+            disconnect();
+                
+    }
+    /** 
+     *  Sets the connection parameters. Must be called before running the startListener as a thread.
+     *
+     *  @param host - pointer to the host where the MQTT server is running
+     *  @param port - the port number to connect, 1883 for non secure connections, 8883 for 
+     *                secure connections
+     *  @param options - the connect data used for logging into the MQTT server.
+     */
+    void setConnectionParameters(const char * host, uint16_t port, MQTTPacket_connectData & options);
+    int publish(PubMessage& message);
+    
+    void addTopicHandler(const char * topic, void (*function)(MessageData &));
+    template<typename T>
+    void addTopicHandler(const char * topic, T *object, void (T::*member)(MessageData &))
+    {
+        FP<void,MessageData &> fp;
+        fp.attach(object, member);
+
+        topicCBMap.insert(std::pair<std::string, FP<void,MessageData &> >(std::string(topic),fp));  
+    }
+    
+    // TODO: Add unsubscribe functionality.
+    
+    // Start the listener thread and start polling 
+    // MQTT server.
+    void startListener();
+    // Stop the listerner thread and closes connection
+    void stopListener();
+
+protected:
+
+    int handlePublishMsg();
+    void disconnect();  
+    int connect();      
+
+
+private:
+    NetworkInterface * network;
+    const char * ssl_ca_pem;
+    TCPSocket * tcpSocket;
+    PacketId packetid;
+    const char *DRBG_PERS;
+    nsapi_error_t _error;    
+    // Connection options
+    std::string host;
+    uint16_t port;
+    MQTTPacket_connectData connect_options;
+    // Event queue
+    EventQueue queue;
+    bool isConnected;
+    bool hasSavedSession;    
+
+    // TODO: Because I'm using a map, I can only have one handler
+    // for each topic (one that's mapped to the topic string).
+    // Attaching another handler on the same topic is not possible.
+    // In the future, use a vector instead of maps to allow multiple
+    // handlers for the same topic.
+    std::map<std::string, FP<void, MessageData &> > topicCBMap;
+    
+    unsigned char sendbuf[MAX_MQTT_PACKET_SIZE];
+    unsigned char readbuf[MAX_MQTT_PACKET_SIZE];
+
+    unsigned int keepAliveInterval;
+    Timer comTimer;
+
+    // SSL/TLS functions
+    bool useTLS;
+    void setupTLS();
+    int initTLS();    
+    void freeTLS();
+    int doTLSHandshake();
+    
+    int processSubscriptions();
+    int readPacket();
+    int sendPacket(size_t length);
+    int readPacketLength(int* value);
+    int readUntil(int packetType, int timeout);
+    int readBytesToBuffer(char * buffer, size_t size, int timeout);
+    int sendBytesFromBuffer(char * buffer, size_t size, int timeout);
+    bool isTopicMatched(char* topic, MQTTString& topicName);
+    int  sendPublish(PubMessage& message);
+    void resetConnectionTimer();
+    void sendPingRequest();
+    bool hasConnectionTimedOut();
+    int login();
+};
+
+}
+#endif
diff -r 000000000000 -r a1734fe1ec4b NTPClient/NTPClient.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NTPClient/NTPClient.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,185 @@
+/* NTPClient.cpp */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+//Debug is disabled by default
+#if 0
+//Enable debug
+#define __DEBUG__
+#include <cstdio>
+#define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 
+#define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 
+#define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 
+
+#else
+//Disable debug
+#define DBG(x, ...) 
+#define WARN(x, ...)
+#define ERR(x, ...) 
+
+#endif
+#include "NetworkInterface.h"
+#include "NTPClient.h"
+
+#include "UDPSocket.h"
+
+#include "mbed.h" //time() and set_time()
+
+#define NTP_PORT 123
+#define NTP_CLIENT_PORT 0 //Random port
+#define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)
+
+/*NTPClient::NTPClient() : m_sock()
+{
+
+}*/
+
+NTPClient::NTPClient(NetworkInterface * _m_intf, int utcOffset) 
+    : m_intf(_m_intf),
+    utc_offset(utcOffset)
+{
+}
+
+#ifdef htons
+#undef htons
+#endif /* htons */
+#ifdef htonl
+#undef htonl
+#endif /* htonl */
+#ifdef ntohs
+#undef ntohs
+#endif /* ntohs */
+#ifdef ntohl
+#undef ntohl
+#endif /* ntohl */
+
+
+#if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__))
+
+#define htons(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#define ntohs(x) htons(x)
+#define htonl(x) ((((x) & 0xff) << 24) | \
+                     (((x) & 0xff00) << 8) | \
+                     (((x) & 0xff0000UL) >> 8) | \
+                     (((x) & 0xff000000UL) >> 24))
+#define ntohl(x) htonl(x)
+
+#else
+
+#define htons(x)  (x)
+#define htonl(x)  (x)
+#define ntohl(x)  (x)
+#define ntohs(x)  (x)
+
+#endif 
+
+
+NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout)
+{
+#ifdef __DEBUG__
+  time_t ctTime;
+  ctTime = time(NULL);
+  set_time(ctTime);
+  DBG("Time is set to (UTC): %s", ctime(&ctTime));
+#endif
+
+    
+  SocketAddress address(0, port);
+  int r = m_intf->gethostbyname(host, &address);  
+  if (r) {
+        printf("error: 'gethostbyname(\"%s\")' failed with code %d\r\n", host, r);
+  } else if (!address) {
+        printf("error: 'gethostbyname(\"%s\")' returned null IP address\r\n", host);
+  }  
+  //printf ("address: %s\n\r",address.get_ip_address());
+   
+  //Create & bind socket
+  if (m_sock.open(m_intf) < 0) printf ("ERROR sock open \n\r");  
+  m_sock.set_timeout(timeout);  
+
+  struct NTPPacket pkt;  
+  memset (&pkt, 0, sizeof(NTPPacket));   
+
+  //Now ping the server and wait for response
+  DBG("Ping");
+  //Prepare NTP Packet:
+  pkt.li = 0; //Leap Indicator : No warning
+  pkt.vn = 4; //Version Number : 4
+  pkt.mode = 3; //Client mode
+  pkt.stratum = 0; //Not relevant here
+  pkt.poll = 0; //Not significant as well
+  pkt.precision = 0; //Neither this one is
+
+  int ret = m_sock.sendto(address, (char*)&pkt, sizeof(NTPPacket) ); 
+  if (ret < 0 )
+  {
+    ERR("Could not send packet %d", ret);
+    m_sock.close();
+    return NTP_CONN;
+  }
+
+  //Read response
+  DBG("Pong");
+
+  ret = m_sock.recvfrom(&address, (char*)&pkt, sizeof(NTPPacket) );  // LICIO
+  if(ret < 0)
+  {
+    ERR("Could not receive packet %d", ret);
+    m_sock.close();
+    return NTP_CONN;
+  }
+
+  if(ret < sizeof(NTPPacket)) //TODO: Accept chunks
+  {
+    ERR("Receive packet size does not match");
+    m_sock.close();
+    return NTP_PRTCL;
+  }
+
+  if( pkt.stratum == 0)  //Kiss of death message : Not good !
+  {
+    ERR("Kissed to death!");
+    m_sock.close();
+    return NTP_PRTCL;
+  }
+
+  //Correct Endianness
+  pkt.refTm_s = ntohl( pkt.refTm_s ); 
+  pkt.refTm_f = ntohl( pkt.refTm_f );
+  pkt.origTm_s = ntohl( pkt.origTm_s );
+  pkt.origTm_f = ntohl( pkt.origTm_f );
+  pkt.rxTm_s = ntohl( pkt.rxTm_s );
+  pkt.rxTm_f = ntohl( pkt.rxTm_f );
+  pkt.txTm_s = ntohl( pkt.txTm_s );
+  pkt.txTm_f = ntohl( pkt.txTm_f );
+
+  // see RFC 4330 p.13
+  int timeoffset = utc_offset * 60 * 60;  
+  time_t txTm = (time_t)((pkt.txTm_s - NTP_TIMESTAMP_DELTA) + timeoffset);  
+
+  set_time(txTm); 
+
+#ifdef __DEBUG__
+  ctTime = time(NULL);
+  DBG("Time is now (UTC): %s", ctime(&ctTime));
+#endif
+  m_sock.close();
+
+  return NTP_OK;
+}
+
diff -r 000000000000 -r a1734fe1ec4b NTPClient/NTPClient.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NTPClient/NTPClient.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,98 @@
+/* NTPClient.h */
+/* Copyright (C) 2012 mbed.org, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** \file
+NTP Client header file
+*/
+
+#ifndef NTPCLIENT_H_
+#define NTPCLIENT_H_
+
+#include <stdint.h>
+#include "UDPSocket.h"
+
+#define NTP_DEFAULT_PORT 123
+#define NTP_DEFAULT_TIMEOUT 4000
+
+///NTP client results
+enum NTPResult
+{
+  NTP_DNS, ///<Could not resolve name
+  NTP_PRTCL, ///<Protocol error
+  NTP_TIMEOUT, ///<Connection timeout
+  NTP_CONN, ///<Connection error
+  NTP_OK = 0, ///<Success
+};
+
+/** NTP Client to update the mbed's RTC using a remote time server
+*
+*/
+class NTPClient
+{
+public:
+  /**
+  Instantiate the NTP client
+  */
+ // NTPClient();
+  NTPClient(NetworkInterface * _m_intf, int utcOffset = 0);
+  /**Get current time (blocking)
+  Update the time using the server host
+  Blocks until completion
+  @param host NTP server IPv4 address or hostname (will be resolved via DNS)
+  @param port port to use; defaults to 123
+  @param timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
+  @return 0 on success, NTP error code (<0) on failure
+  */
+  NTPResult setTime(const char* host, uint16_t port = NTP_DEFAULT_PORT, uint32_t timeout = NTP_DEFAULT_TIMEOUT); 
+
+private:
+  struct NTPPacket //See RFC 4330 for Simple NTP
+  {
+    //WARN: We are in LE! Network is BE!
+    //LSb first
+    unsigned mode : 3;
+    unsigned vn : 3;
+    unsigned li : 2;
+
+    uint8_t stratum;
+    uint8_t poll;
+    uint8_t precision;
+    //32 bits header
+
+    uint32_t rootDelay;
+    uint32_t rootDispersion;
+    uint32_t refId;
+
+    uint32_t refTm_s;
+    uint32_t refTm_f;
+    uint32_t origTm_s;
+    uint32_t origTm_f;
+    uint32_t rxTm_s;
+    uint32_t rxTm_f;
+    uint32_t txTm_s;
+    uint32_t txTm_f;
+  } __attribute__ ((packed));
+  
+  NetworkInterface * m_intf;  // WiFi interface 
+  int utc_offset; 
+  UDPSocket m_sock;
+};
+
+
+#endif /* NTPCLIENT_H_ */
diff -r 000000000000 -r a1734fe1ec4b README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+# MQTTGateway
diff -r 000000000000 -r a1734fe1ec4b Sensor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sensor.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,41 @@
+#ifndef _SENSOR_H_
+#define _SENSOR_H_
+
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string>
+#include "Utils.h"
+
+// Keep SensorData a POD type
+typedef struct _SensorData
+{
+    uint64_t deviceaddr;
+       
+    uint16_t humidity;
+    float temperature;
+    uint16_t luminance;
+    // Relay value (negative logic)
+    // true = off
+    // false = on
+    bool  sprinkler;
+
+    
+    void debug()
+    {
+        printf("Channel id (lo): [%lX]\r\n", UINT64_HI32(deviceaddr));
+        printf("Channel id (hi): [%lX]\r\n", UINT64_LO32(deviceaddr));
+        printf("Humidity : [%d]\r\n", humidity);
+        printf("Temperature : [%.2f]\r\n", temperature);
+        printf("Luminance : [%d]\r\n", luminance);
+    }    
+} SensorData;
+
+typedef struct _SensorInfo
+{
+    int id;
+    std::string name;
+} SensorInfo;
+
+   
+#endif
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "DigiLogger.h"
+
+#include <stdarg.h>
+
+using namespace DigiLog;
+
+LogLevel DigiLogger::_log_level;
+
+DigiLogger* DigiLogger::current_logger;
+
+/* Base Class constructor */
+DigiLogger::DigiLogger()
+{
+    _log_level = LogLevelNone;
+
+    current_logger = NULL;
+}
+
+/* Class destructor */
+DigiLogger::~DigiLogger()
+{
+    current_logger = NULL;
+}
+
+void DigiLogger::set_level(LogLevel log_level)
+{
+    _log_level = log_level;
+}
+
+LogLevel DigiLogger::get_level()
+{
+    return _log_level;
+}
+
+void DigiLogger::log_format(LogLevel log_level, const char *format, ...)
+{
+    static char buffer[DEBUG_BUFFER_LEN];
+    va_list argp;
+
+    if (current_logger == NULL) {
+        return;
+    }
+
+    if (_log_level < log_level) {
+        return;
+    }
+
+    va_start(argp, format);
+    vsnprintf(buffer, DEBUG_BUFFER_LEN, format, argp);
+    va_end(argp);
+
+    current_logger->log_buffer(buffer);
+}
+
+void DigiLogger::log_buffer(char const * const buffer)
+{
+    (void)(buffer);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/DigiLogger/DigiLogger.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,89 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DIGI_LOGGER_H_)
+#define __DIGI_LOGGER_H_
+
+#include <cstdlib>
+#include <stdio.h>
+
+/**
+ * @defgroup LogLevel
+ * @{
+ */
+/**
+ * Library Logging level.
+ */
+enum LogLevel {
+    LogLevelNone,      /** Level None */
+    LogLevelError,     /** Level Error */
+    LogLevelWarning,   /** Level Warning */
+    LogLevelInfo,      /** Level Info */
+    LogLevelDebug,     /** Level Debug */
+    LogLevelFrameData, /** Level Frame Data */
+    LogLevelAll        /** Level All */
+};
+/**
+ * @}
+ */
+
+#define DEBUG_BUFFER_LEN    200
+
+namespace DigiLog {
+
+class DigiLogger
+{
+    protected:
+
+        /** module log level */
+        static LogLevel _log_level;
+
+        static DigiLogger* current_logger;
+
+        /* Not implemented for base class */
+        virtual void log_buffer(char const * const buffer);
+
+    public:
+
+        /** Class constructor */
+        DigiLogger();
+
+        /** Class destructor */
+        virtual ~DigiLogger();
+
+        /** set_level - set logging level.
+         *
+         *  @param log_level desired overall logging level
+         */
+        static void set_level(LogLevel log_level);
+
+        /** get_level - get logging level.
+         *
+         *  @returns current overall logging level
+         */
+        static LogLevel get_level();
+
+        /** log_format - logs a printf-like message.
+         *
+         *  @param log_level logging level
+         *  @param format ... printf-like message
+         */
+        static void log_format(LogLevel log_level, const char *format, ...);
+
+};
+
+}   /* namespace DigiLog */
+
+#endif /* defined(__DIGI_LOGGER_H_) */
+
+
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "DigiLoggerMbedSerial.h"
+
+using namespace DigiLog;
+
+Serial *DigiLoggerMbedSerial::_log_serial;
+
+/* Class constructor when using a serial port as logging channel */
+DigiLoggerMbedSerial::DigiLoggerMbedSerial(Serial * log_serial, LogLevel log_level)
+{
+    _log_serial = log_serial;
+
+    _log_level = log_level;
+
+    DigiLogger::current_logger = this;
+}
+
+/* Class destructor */
+DigiLoggerMbedSerial::~DigiLoggerMbedSerial()
+{
+    _log_serial = NULL;
+    DigiLogger::current_logger = NULL;
+}
+
+void DigiLoggerMbedSerial::log_buffer(char const * const buffer)
+{
+    if (_log_serial == NULL) {
+        return;
+    }
+
+    _log_serial->printf("%s", buffer);
+    fflush(*_log_serial);
+}
+
+
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/DigiLogger/DigiLoggerMbedSerial.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DIGI_LOGGER_MBED_SERIAL_H_)
+#define __DIGI_LOGGER_MBED_SERIAL_H_
+
+#include "mbed.h"
+#include "DigiLogger.h"
+
+namespace DigiLog {
+
+class DigiLoggerMbedSerial : public DigiLogger
+{
+    protected:
+
+        /** serial port for debugging */
+        static Serial *_log_serial;
+
+        /** log_buffer - logs a buffer through the configured serial port.
+         *
+         *  @param buffer ... buffer to log
+         */
+        virtual void log_buffer(char const * const buffer);
+
+    public:
+
+        /** Class constructor */
+        DigiLoggerMbedSerial(Serial * log_serial, LogLevel log_level = LogLevelInfo);
+
+        /** Class destructor */
+        virtual ~DigiLoggerMbedSerial();
+};
+
+}   /* namespace DigiLog */
+
+#endif /* defined(__DIGI_LOGGER_MBED_SERIAL_H_) */
+
+
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,126 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FrameBuffer.h"
+#include "Utils/Debug.h"
+
+#if !(defined AVOID_DISABLE_IRQS)
+#define disable_irq() __disable_irq()
+#define enable_irq() __enable_irq()
+#else
+#define disable_irq()
+#define enable_irq()
+#endif
+
+FrameBuffer::FrameBuffer(uint8_t size, uint16_t max_payload_len) : _size(size), _head(0), _tail(0), _dropped_frames(0)
+{
+    _frm_buf = new buf_element_t[_size];
+
+    assert(_frm_buf != NULL);
+
+    for (int i = 0; i < _size; i++) {
+        _frm_buf[i].frame = new ApiFrame(max_payload_len - 1);
+        _frm_buf[i].status = FrameStatusFree;
+    }
+}
+
+FrameBuffer::~FrameBuffer()
+{
+    for (int i = 0; i < _size; i++) {
+        delete _frm_buf[i].frame;
+    }
+
+    delete _frm_buf;
+}
+
+ApiFrame *FrameBuffer::get_next_free_frame(void)
+{
+    uint8_t i = _head;
+    ApiFrame *ret = NULL;
+
+    do {
+        if (_frm_buf[i].status == FrameStatusFree || _frm_buf[i].status == FrameStatusComplete) {
+            if (_frm_buf[i].status == FrameStatusComplete) {
+                _dropped_frames++;
+            }
+            _frm_buf[i].status = FrameStatusAssigned;
+            ret = _frm_buf[i].frame;
+            _head = ++i % _size;
+            break;
+        }
+        i++;
+        i = i % _size;
+    } while (i != _head);
+
+    return ret;
+}
+
+bool FrameBuffer::complete_frame(ApiFrame *frame)
+{
+    bool ret = false;
+
+    for (int i = 0; i < _size; i++) {
+        if (_frm_buf[i].frame == frame) {
+            _frm_buf[i].status = FrameStatusComplete;
+            ret = true;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+ApiFrame *FrameBuffer::get_next_complete_frame(void)
+{
+    uint8_t i = _tail;
+    ApiFrame *ret = NULL;
+
+    do {
+        disable_irq();
+        if (_frm_buf[i].status == FrameStatusComplete) {
+            _frm_buf[i].status = FrameStatusAssigned;
+            enable_irq();
+            ret = _frm_buf[i].frame;
+            _tail = ++i % _size;
+            break;
+        }
+        enable_irq();
+        i++;
+        i = i % _size;
+    } while (i != _tail);
+
+    return ret;
+}
+
+bool FrameBuffer::free_frame(ApiFrame *frame)
+{
+    bool ret = false;
+
+    for (int i = 0; i < _size; i++) {
+        if (_frm_buf[i].frame == frame) {
+            _frm_buf[i].status = FrameStatusFree;
+            ret = true;
+            break;
+        }
+    }
+
+    return ret;
+}
+
+uint32_t FrameBuffer::get_dropped_frames_count(void)
+{
+    const uint32_t dropped_frames = _dropped_frames;
+
+    _dropped_frames = 0;
+
+    return dropped_frames;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameBuffer/FrameBuffer.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FRAME_BUFFER_H_)
+#define __FRAME_BUFFER_H_
+
+#include "config.h"
+#include "mbed.h"
+#include "Frames/ApiFrame.h"
+
+#if FRAME_BUFFER_SIZE > 255
+# error "FRAME_BUFFER_SIZE must be lower than 256"
+#endif
+
+typedef struct element {
+    ApiFrame    *frame;
+    uint8_t     status;
+} buf_element_t;
+
+/**
+ *  @class FrameBuffer
+ *  @brief storage class for incoming frames
+ */
+class FrameBuffer
+{
+    public:
+        /** Constructor */
+        FrameBuffer(uint8_t size, uint16_t max_payload_len);
+
+        FrameBuffer(const FrameBuffer& other); /* Intentionally not implemented */
+        /** Destructor */
+        ~FrameBuffer();
+
+        /** get_next_free_frame returns the next free frame
+         *
+         * @returns a pointer to the next free frame */
+        ApiFrame *get_next_free_frame();
+
+        /** complete_frame sets the status of the frame to complete once the
+         *                      data has been set in the buffer.
+         *
+         * @param pointer to the buffer we want to set as complete
+         * @returns true on success, false otherwise
+         */
+        bool complete_frame(ApiFrame *frame);
+
+        /** free_frame makes the frame available to be reused in future
+         *
+         * @param frame to release */
+        bool free_frame(ApiFrame *frame);
+
+        /** get_next_complete_frame returns the pointer to the next complete frame
+         *
+         * @returns the pointer to the selected buffer
+         */
+        ApiFrame *get_next_complete_frame();
+
+        /** get_dropped_frames_count returns the number of dropped frames since latest call to this method
+         *
+         * @returns the number of dropped frames since latest call to this method
+         */
+        uint32_t get_dropped_frames_count();
+
+protected:
+
+        /** frame status */
+        enum FrameStatus {
+            FrameStatusFree = 0,   /**< Free */
+            FrameStatusAssigned,   /**< Assigned */
+            FrameStatusComplete    /**< Complete */
+        };
+
+        /** buffer array */
+        buf_element_t   * _frm_buf;
+
+        uint8_t          _size;
+        
+
+        /** head frame index */
+        uint8_t         _head;
+
+        /** tail frame index for application */
+        uint8_t         _tail;
+
+        /** dropped frames */
+        uint32_t        _dropped_frames;
+};
+
+#endif /* __FRAME_BUFFER_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,208 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FrameHandlers/FH_AtCmdResp.h"
+#include "Frames/ApiFrame.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_AtCmdResp::FH_AtCmdResp() :
+    FrameHandler(ApiFrame::AtCmdResp), at_cmd_resp_cb(NULL)
+{
+}
+
+FH_AtCmdResp::FH_AtCmdResp(ApiFrame::ApiFrameType type) :
+    FrameHandler(type), at_cmd_resp_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_AtCmdResp::~FH_AtCmdResp()
+{
+}
+
+void FH_AtCmdResp::register_at_cmd_resp_cb(at_cmd_resp_cb_t function)
+{
+    at_cmd_resp_cb = function;
+}
+
+void FH_AtCmdResp::unregister_at_cmd_resp_cb()
+{
+    at_cmd_resp_cb = NULL;
+}
+
+void FH_AtCmdResp::process_frame_data(const ApiFrame * const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (at_cmd_resp_cb == NULL) {
+        return;
+    }
+
+    at_cmd_resp_cb(frame->get_data(), frame->get_data_len());
+}
+
+
+/** Class constructor */
+FH_NodeDiscoveryZB::FH_NodeDiscoveryZB() :
+    FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscoveryZB::~FH_NodeDiscoveryZB()
+{
+}
+
+void FH_NodeDiscoveryZB::register_node_discovery_cb(node_discovery_zb_cb_t function)
+{
+    node_discovery_cb = function;
+}
+
+void FH_NodeDiscoveryZB::unregister_node_discovery_cb()
+{
+    node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscoveryZB::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (node_discovery_cb == NULL) {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+        frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+        return;
+    }
+
+    const uint8_t * const data = frame->get_data(); /* The data payload we get here is the full AT command response payload, excluding the frameid. Keep that in mind for the offsets */
+    const uint16_t addr16 = UINT16(data[ATCMD_RESP_NW_ADDR_H_OFFSET], data[ATCMD_RESP_NW_ADDR_L_OFFSET]);
+    const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+    const char * const node_id = (const char *)&data[ATCMD_RESP_NI_OFFSET];
+    RemoteXBeeZB remote = RemoteXBeeZB(addr64, addr16);
+
+    node_discovery_cb(remote, node_id);
+}
+
+
+
+/** Class constructor */
+FH_NodeDiscovery802::FH_NodeDiscovery802() :
+    FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscovery802::~FH_NodeDiscovery802()
+{
+}
+
+void FH_NodeDiscovery802::register_node_discovery_cb(node_discovery_802_cb_t function)
+{
+    node_discovery_cb = function;
+}
+
+void FH_NodeDiscovery802::unregister_node_discovery_cb()
+{
+    node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscovery802::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (node_discovery_cb == NULL) {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+        frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+        return;
+    }
+
+    const uint16_t min_atnd_response_with_data = sizeof (uint16_t) + sizeof(uint64_t);
+    if (frame->get_data_len() < min_atnd_response_with_data) {
+        /* Do not process the ATND "OK" response */
+        return;
+    }
+
+    const uint8_t * const data = frame->get_data();
+    const uint16_t addr16 = UINT16(data[ATCMD_RESP_NW_ADDR_H_OFFSET], data[ATCMD_RESP_NW_ADDR_L_OFFSET]);
+    const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+#if 0
+    const uint8_t signal_strength = data[ATCMD_802_RESP_SIGN_STR_OFFSET];
+#endif
+    const RemoteXBee802 remote = RemoteXBee802(addr64, addr16);
+    const char * const nodeid = (const char *)(&data[ATCMD_802_RESP_NI_OFFSET]);
+
+    node_discovery_cb(remote, nodeid);
+}
+
+/** Class constructor */
+FH_NodeDiscoveryDM::FH_NodeDiscoveryDM() :
+    FH_AtCmdResp(ApiFrame::AtCmdResp), node_discovery_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_NodeDiscoveryDM::~FH_NodeDiscoveryDM()
+{
+}
+
+void FH_NodeDiscoveryDM::register_node_discovery_cb(node_discovery_dm_cb_t function)
+{
+    node_discovery_cb = function;
+}
+
+void FH_NodeDiscoveryDM::unregister_node_discovery_cb()
+{
+    node_discovery_cb = NULL;
+}
+
+
+void FH_NodeDiscoveryDM::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (node_discovery_cb == NULL) {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_CMD_LOW_OFFSET) != 'N' ||
+        frame->get_data_at(ATCMD_RESP_CMD_HIGH_OFFSET) != 'D') {
+        return;
+    }
+
+    if (frame->get_data_at(ATCMD_RESP_STATUS_OFFSET) != AtCmdFrame::AtCmdRespOk) {
+        return;
+    }
+
+    const uint8_t * const data = frame->get_data(); /* The data payload we get here is the full AT command response payload, excluding the frameid. Keep that in mind for the offsets */
+    const uint64_t addr64 = addr64_from_uint8_t(&data[ATCMD_RESP_SH_ADDR_L_OFFSET]);
+    const char * const node_id = (const char *)&data[ATCMD_RESP_NI_OFFSET];
+    RemoteXBeeDM remote = RemoteXBeeDM(addr64);
+
+    node_discovery_cb(remote, node_id);
+}
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_AtCmdResp.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_AT_CMD_RESP_H_)
+#define __FH_AT_CMD_RESP_H_
+
+#include "FrameHandler.h"
+#include "XBee/XBee.h"
+
+namespace XBeeLib {
+typedef void (*at_cmd_resp_cb_t)(const uint8_t * data, uint16_t len);
+
+class FH_AtCmdResp : public FrameHandler
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        at_cmd_resp_cb_t at_cmd_resp_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_AtCmdResp();
+
+        /** Class constructor */
+        FH_AtCmdResp(ApiFrame::ApiFrameType type);
+
+
+        /** Class destructor */
+        virtual ~FH_AtCmdResp();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_at_cmd_resp_cb(at_cmd_resp_cb_t function);
+
+        virtual void unregister_at_cmd_resp_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** Node Discovery Response callback type declaration for ZigBee
+  * @param remote discovered remote node.
+  * @param node_id Node Identifier (NI parameter) of remote.
+  */
+typedef void (*node_discovery_zb_cb_t)(const RemoteXBeeZB& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscoveryZB : public FH_AtCmdResp
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        node_discovery_zb_cb_t node_discovery_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_NodeDiscoveryZB();
+
+        /** Class destructor */
+        virtual ~FH_NodeDiscoveryZB();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_node_discovery_cb(node_discovery_zb_cb_t function);
+
+        virtual void unregister_node_discovery_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** Node Discovery Response callback type declaration for ZigBee
+  * @param remote discovered remote node.
+  * @param node_id Node Identifier (NI parameter) of remote.
+  */
+typedef void (*node_discovery_dm_cb_t)(const RemoteXBeeDM& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscoveryDM : public FH_AtCmdResp
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        node_discovery_dm_cb_t node_discovery_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_NodeDiscoveryDM();
+
+        /** Class destructor */
+        virtual ~FH_NodeDiscoveryDM();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_node_discovery_cb(node_discovery_dm_cb_t function);
+
+        virtual void unregister_node_discovery_cb();
+};
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** Node Discovery Response callback type declaration for 802.15.4
+  * @param remote discovered remote node.
+  * @param node_id Node Identifier (NI parameter) of remote.
+  */
+typedef void (*node_discovery_802_cb_t)(const RemoteXBee802& remote, char const * const node_id);
+/**
+ * @}
+ */
+
+class FH_NodeDiscovery802 : public FH_AtCmdResp
+{
+    private:
+        /** Callback function, invoked (if registered) when an at command response packet is received */
+        node_discovery_802_cb_t node_discovery_cb;
+
+    public:
+
+        /** Class constructor */
+        FH_NodeDiscovery802();
+
+        /** Class destructor */
+        virtual ~FH_NodeDiscovery802();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_node_discovery_cb(node_discovery_802_cb_t function);
+
+        virtual void unregister_node_discovery_cb();
+};
+
+} /* namespace XBeeLib */
+
+#endif /* __FH_AT_CMD_RESP_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampe64b802::FH_IoDataSampe64b802() : FrameHandler(ApiFrame::Io64Bit),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampe64b802::~FH_IoDataSampe64b802()
+{
+
+}
+
+void FH_IoDataSampe64b802::register_io_data_cb(io_data_cb_802_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampe64b802::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+#define IO_SAMPLE_64_802_DATA_OFFSET        10
+
+void FH_IoDataSampe64b802::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const RemoteXBee802 sender = RemoteXBee802(sender64);
+    const IOSample802 ioSample = IOSample802(&datap[IO_SAMPLE_64_802_DATA_OFFSET], frame->get_data_len() - IO_SAMPLE_64_802_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
+
+/** Class constructor */
+FH_IoDataSampe16b802::FH_IoDataSampe16b802() : FrameHandler(ApiFrame::Io16Bit),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampe16b802::~FH_IoDataSampe16b802()
+{
+}
+
+void FH_IoDataSampe16b802::register_io_data_cb(io_data_cb_802_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampe16b802::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+#define IO_SAMPLE_16_802_ADDR16_MSB_OFFSET  0
+#define IO_SAMPLE_16_802_ADDR16_LSB_OFFSET  1
+#define IO_SAMPLE_16_802_DATA_OFFSET        4
+
+void FH_IoDataSampe16b802::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();;
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint16_t sender16 = ADDR16(datap[IO_SAMPLE_16_802_ADDR16_MSB_OFFSET], datap[IO_SAMPLE_16_802_ADDR16_LSB_OFFSET]);
+    const RemoteXBee802 sender = RemoteXBee802(sender16);
+
+    const IOSample802 ioSample = IOSample802(&datap[IO_SAMPLE_16_802_DATA_OFFSET], frame->get_data_len() - IO_SAMPLE_16_802_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSample802.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_802_H_)
+#define __FH_IO_DATA_SAMPLE_802_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSample802;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (802.15.4 modules) callback type declaration
+  * @param remote the remote module that sent the data
+  * @param sample_data a referece to an @ref IOSample802 that can be queried for the IoLines' values
+  */
+typedef void (*io_data_cb_802_t)(const RemoteXBee802& remote, const IOSample802& sample_data);
+/**
+ * @}
+ */
+
+
+class FH_IoDataSampe64b802 : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampe64b802();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampe64b802();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_802_t function);
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_802_t io_data_cb;
+
+};
+
+class FH_IoDataSampe16b802 : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampe16b802();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampe16b802();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_802_t function);
+
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_802_t io_data_cb;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_802_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampeDM::FH_IoDataSampeDM() : FrameHandler(ApiFrame::IoSampleRxZBDM),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampeDM::~FH_IoDataSampeDM()
+{
+}
+
+void FH_IoDataSampeDM::register_io_data_cb(io_data_cb_dm_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampeDM::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+/* DM RX packet offsets */
+#define DM_IO_SAMPLE_DATA_OFFSET            11
+
+void FH_IoDataSampeDM::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();;
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const RemoteXBeeDM sender = RemoteXBeeDM(sender64);
+    const IOSampleDM ioSample = IOSampleDM(&datap[DM_IO_SAMPLE_DATA_OFFSET], frame->get_data_len() - DM_IO_SAMPLE_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleDM.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_DM_H_)
+#define __FH_IO_DATA_SAMPLE_DM_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSampleDM;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (ZigBee modules) callback type declaration
+  * @param remote the remote module that sent the data
+  * @param sample_data a referece to an @ref IOSampleDM that can be queried for the IoLines' values
+  */
+typedef void (*io_data_cb_dm_t)(const RemoteXBeeDM& remote, const IOSampleDM& sample_data);
+/**
+ * @}
+ */
+
+class FH_IoDataSampeDM : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampeDM();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampeDM();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_dm_t function);
+
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_dm_t io_data_cb;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_DM_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_IoDataSampeZB::FH_IoDataSampeZB() : FrameHandler(ApiFrame::IoSampleRxZBDM),
+    io_data_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_IoDataSampeZB::~FH_IoDataSampeZB()
+{
+}
+
+void FH_IoDataSampeZB::register_io_data_cb(io_data_cb_zb_t function)
+{
+    io_data_cb = function;
+}
+
+void FH_IoDataSampeZB::unregister_io_data_cb()
+{
+    io_data_cb = NULL;
+}
+
+/* ZB RX packet offsets */
+#define ZB_IO_SAMPLE_ADDR16_MSB_OFFSET      8
+#define ZB_IO_SAMPLE_ADDR16_LSB_OFFSET      9
+#define ZB_IO_SAMPLE_DATA_OFFSET            11
+
+void FH_IoDataSampeZB::process_frame_data(const ApiFrame *const frame)
+{
+    const uint8_t * const datap = frame->get_data();;
+
+    /* The caller checks that the type matches, so no need to check it here again */
+    if (io_data_cb == NULL) {
+        return;
+    }
+
+    /* We got an IO packet, decode it... */
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint16_t sender16 = ADDR16(datap[ZB_IO_SAMPLE_ADDR16_MSB_OFFSET], datap[ZB_IO_SAMPLE_ADDR16_LSB_OFFSET]);
+    const RemoteXBeeZB sender = RemoteXBeeZB(sender64, sender16);
+    const IOSampleZB ioSample = IOSampleZB(&datap[ZB_IO_SAMPLE_DATA_OFFSET], frame->get_data_len() - ZB_IO_SAMPLE_DATA_OFFSET);
+
+    io_data_cb(sender, ioSample);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_IoDataSampleZB.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_IO_DATA_SAMPLE_ZB_H_)
+#define __FH_IO_DATA_SAMPLE_ZB_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+class IOSampleZB;
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** IO Data Sample reception (ZigBee modules) callback type declaration
+  * @param remote the remote module that sent the data
+  * @param sample_data a referece to an @ref IOSampleZB that can be queried for the IoLines' values
+  */
+typedef void (*io_data_cb_zb_t)(const RemoteXBeeZB& remote, const IOSampleZB& sample_data);
+/**
+ * @}
+ */
+
+class FH_IoDataSampeZB : public FrameHandler
+{
+    public:
+        /** Class constructor */
+        FH_IoDataSampeZB();
+
+        /** Class destructor */
+        virtual ~FH_IoDataSampeZB();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        void register_io_data_cb(io_data_cb_zb_t function);
+
+        void unregister_io_data_cb();
+
+    private:
+        /** Callback function, invoked if registered */
+        io_data_cb_zb_t io_data_cb;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_IO_DATA_SAMPLE_ZB_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FH_ModemStatus.h"
+
+/** Class constructor */
+FH_ModemStatus::FH_ModemStatus() : FrameHandler(ApiFrame::AtModemStatus), modem_status_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_ModemStatus::~FH_ModemStatus()
+{
+}
+
+void FH_ModemStatus::register_modem_status_cb(modem_status_cb_t function)
+{
+    modem_status_cb = function;
+}
+
+void FH_ModemStatus::unregister_modem_status_cb(void)
+{
+    modem_status_cb = NULL;
+}
+
+void FH_ModemStatus::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (modem_status_cb == NULL) {
+        return;
+    }
+
+    modem_status_cb((AtCmdFrame::ModemStatus)frame->get_data_at(0));
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_ModemStatus.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_MODEM_STATUS_H_)
+#define __FH_MODEM_STATUS_H_
+
+#include "Frames/AtCmdFrame.h"
+#include "FrameHandler.h"
+
+typedef void (*modem_status_cb_t)(AtCmdFrame::ModemStatus status);
+
+class FH_ModemStatus : public FrameHandler
+{
+    private:
+        /** Callback function, invoked (if registered) when a modem status packet is received */
+        modem_status_cb_t modem_status_cb;
+
+    public:
+        /** Class constructor */
+        FH_ModemStatus();
+
+        /** Class destructor */
+        virtual ~FH_ModemStatus();
+
+         /** Method called by the stack to process the modem status frame data
+
+             \param frame pointer pointing to api frame that must be processed */
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_modem_status_cb(modem_status_cb_t function);
+
+        virtual void unregister_modem_status_cb(void);
+};
+
+#endif /* __FH_MODEM_STATUS_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,108 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FH_RxPacket802.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacket64b802::FH_RxPacket64b802() : FrameHandler(ApiFrame::RxPacket64Bit),
+    receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacket64b802::~FH_RxPacket64b802()
+{
+}
+
+void FH_RxPacket64b802::register_receive_cb(receive_802_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacket64b802::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* 802.15.4 RX packet offsets */
+#define RX_802_RSSI_OFFSET          8
+#define RX_802_OPTIONS_OFFSET       9
+#define RX_802_DATA_OFFSET          10
+#define RX_802_OVERHEAD             (8+1+1)
+
+#define BROADCAST_PACKET            0x02
+
+void FH_RxPacket64b802::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint8_t rx_options = datap[RX_802_OPTIONS_OFFSET];
+    const RemoteXBee802 sender = RemoteXBee802(sender64);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[RX_802_DATA_OFFSET], frame->get_data_len() - RX_802_OVERHEAD);
+}
+
+
+/** Class constructor */
+FH_RxPacket16b802::FH_RxPacket16b802() : FrameHandler(ApiFrame::RxPacket16Bit),
+    receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacket16b802::~FH_RxPacket16b802()
+{
+}
+
+void FH_RxPacket16b802::register_receive_cb(receive_802_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacket16b802::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* 802.15.4 RX packet offsets */
+#define RX_802_ADDR16_MSB_OFFSET    0
+#define RX_802_ADDR16_LSB_OFFSET    1
+#define RX_802_RSSI_OFFSET2         2
+#define RX_802_OPTIONS_OFFSET2      3
+#define RX_802_DATA_OFFSET2         4
+#define RX_802_OVERHEAD2            (2+1+1)
+
+void FH_RxPacket16b802::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint16_t sender16 = ADDR16(datap[RX_802_ADDR16_MSB_OFFSET], datap[RX_802_ADDR16_LSB_OFFSET]);
+    const uint8_t rx_options = datap[RX_802_OPTIONS_OFFSET2];
+    const RemoteXBee802 sender = RemoteXBee802(sender16);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[RX_802_DATA_OFFSET2], frame->get_data_len() - RX_802_OVERHEAD2);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacket802.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_802_H_)
+#define __FH_RX_PACKET_802_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+  * @param remote the remote module that sent the data
+  * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+  * @param data a pointer to data sent by @b remote.
+  * @param len length (in bytes) of @b data buffer
+  */
+typedef void (*receive_802_cb_t)(const RemoteXBee802& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacket64b802 : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_802_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacket64b802();
+
+        /** Class destructor */
+        virtual ~FH_RxPacket64b802();
+
+        virtual void process_frame_data(const ApiFrame* const frame);
+
+        virtual void register_receive_cb(receive_802_cb_t function);
+
+        virtual void unregister_receive_cb();
+};
+
+class FH_RxPacket16b802 : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_802_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacket16b802();
+
+        /** Class destructor */
+        virtual ~FH_RxPacket16b802();
+
+        virtual void process_frame_data(const ApiFrame *const frame);
+
+        virtual void register_receive_cb(receive_802_cb_t function);
+
+        virtual void unregister_receive_cb();
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_802_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FH_RxPacketDM.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacketDM::FH_RxPacketDM() : FrameHandler(ApiFrame::RxPacketAO0), receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacketDM::~FH_RxPacketDM()
+{
+}
+
+void FH_RxPacketDM::register_receive_cb(receive_dm_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacketDM::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* DM RX packet offsets */
+#define DM_RX_OPTIONS_OFFSET        10
+#define DM_RX_DATA_OFFSET           11
+#define DM_RX_OVERHEAD              (8+2+1)
+
+#define BROADCAST_PACKET            0x02
+
+void FH_RxPacketDM::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint8_t rx_options = datap[DM_RX_OPTIONS_OFFSET];
+    const RemoteXBeeDM sender = RemoteXBeeDM(sender64);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[DM_RX_DATA_OFFSET], frame->get_data_len() - DM_RX_OVERHEAD);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketDM.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_DM_H_)
+#define __FH_RX_PACKET_DM_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+  * @param remote the remote module that sent the data
+  * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+  * @param data a pointer to data sent by @b remote.
+  * @param len length (in bytes) of @b data buffer
+  */
+typedef void (*receive_dm_cb_t)(const RemoteXBeeDM& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacketDM : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_dm_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacketDM();
+
+        /** Class destructor */
+        virtual ~FH_RxPacketDM();
+
+        /** Method called by the stack to process the modem status frame data
+
+            \param frame pointer pointing to api frame that must be processed */
+        virtual void process_frame_data(const ApiFrame* const frame);
+
+        void register_receive_cb(receive_dm_cb_t function);
+
+        void unregister_receive_cb();
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_DM_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FH_RxPacketZB.h"
+
+using namespace XBeeLib;
+
+/** Class constructor */
+FH_RxPacketZB::FH_RxPacketZB() : FrameHandler(ApiFrame::RxPacketAO0), receive_cb(NULL)
+{
+}
+
+/** Class destructor */
+FH_RxPacketZB::~FH_RxPacketZB()
+{
+}
+
+void FH_RxPacketZB::register_receive_cb(receive_zb_cb_t function)
+{
+    receive_cb = function;
+}
+
+void FH_RxPacketZB::unregister_receive_cb(void)
+{
+    receive_cb = NULL;
+}
+
+/* ZB RX packet offsets */
+#define ZB_RX_ADDR16_MSB_OFFSET     8
+#define ZB_RX_ADDR16_LSB_OFFSET     9
+#define ZB_RX_OPTIONS_OFFSET        10
+#define ZB_RX_DATA_OFFSET           11
+#define ZB_RX_OVERHEAD              (8+2+1)
+
+#define BROADCAST_PACKET            0x02
+
+void FH_RxPacketZB::process_frame_data(const ApiFrame *const frame)
+{
+    /* The caller checks that the type matches, so no need to check it here again */
+
+    if (receive_cb == NULL) {
+        return;
+    }
+
+    /* We got a rx packet, decode it... */
+    const uint8_t *datap = frame->get_data();
+    const uint64_t sender64 = addr64_from_uint8_t(datap);
+    const uint16_t sender16 = ADDR16(datap[ZB_RX_ADDR16_MSB_OFFSET], datap[ZB_RX_ADDR16_LSB_OFFSET]);
+    const uint8_t rx_options = datap[ZB_RX_OPTIONS_OFFSET];
+    const RemoteXBeeZB sender = RemoteXBeeZB(sender64, sender16);
+
+    receive_cb(sender, rx_options & BROADCAST_PACKET, &datap[ZB_RX_DATA_OFFSET], frame->get_data_len() - ZB_RX_OVERHEAD);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FH_RxPacketZB.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FH_RX_PACKET_ZB_H_)
+#define __FH_RX_PACKET_ZB_H_
+
+#include "FrameHandler.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/**
+ * @defgroup callback_types "Callback types declaration"
+ * @{
+ */
+/** receive callback type declaration
+  * @param remote the remote module that sent the data
+  * @param broadcast a boolean to tell if the message was broadcast (true) or unicast (false)
+  * @param data a pointer to data sent by @b remote.
+  * @param len length (in bytes) of @b data buffer
+  */
+typedef void (*receive_zb_cb_t)(const RemoteXBeeZB& remote, bool broadcast, const uint8_t *const data, uint16_t len);
+/**
+ * @}
+ */
+
+class FH_RxPacketZB : public FrameHandler
+{
+    private:
+        /** Callback function, invoked if registered */
+        receive_zb_cb_t receive_cb;
+
+    public:
+        /** Class constructor */
+        FH_RxPacketZB();
+
+        /** Class destructor */
+        virtual ~FH_RxPacketZB();
+
+        /** Method called by the stack to process the modem status frame data
+
+            \param frame pointer pointing to api frame that must be processed */
+        virtual void process_frame_data(const ApiFrame* const frame);
+
+        void register_receive_cb(receive_zb_cb_t function);
+
+        void unregister_receive_cb();
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __FH_RX_PACKET_ZB_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "FrameHandler.h"
+
+FrameHandler::FrameHandler(ApiFrame::ApiFrameType t) : _type(t)
+{
+}
+
+FrameHandler::~FrameHandler()
+{
+}
+
+ApiFrame::ApiFrameType FrameHandler::get_type() const
+{
+    return _type;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/FrameHandlers/FrameHandler.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__FRAME_HANDLER_H_)
+#define __FRAME_HANDLER_H_
+
+#include "Frames/ApiFrame.h"
+
+/** Class for the frame handlers */
+class FrameHandler
+{
+    friend class ApiFrame;
+
+    public:
+        /** Class constructor
+         *
+         * @param type frame type handled by this frame handler
+         */
+        FrameHandler(ApiFrame::ApiFrameType type);
+
+        FrameHandler(const FrameHandler& other); /* Intentionally not implemented */
+        /** Class destructor */
+        virtual ~FrameHandler();
+
+        /** get_type returns the type of frames handled by this handler
+         *
+         * @returns the frame type handled by the handler
+         */
+        ApiFrame::ApiFrameType get_type() const;
+
+        /** process_frame_data method called by the library to process the
+         *                     the incoming frames if the type matches.
+         *
+         * @param frame pointer pointing to the api frame that must be processed
+         */
+        virtual void process_frame_data(const ApiFrame *const frame) = 0;
+
+    protected:
+        /** frame type handled by this handler */
+        ApiFrame::ApiFrameType   _type;
+};
+
+#endif /* defined(__FRAME_HANDLER_H_) */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/802_Frames.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/802_Frames.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "802_Frames.h"
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define OPTIONS_LEN               1
+#define TX_REQUEST_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + OPTIONS_LEN)
+#define TX_REQUEST_OVERHEAD2      (FRAME_ID_LEN + ADDR16_LEN + OPTIONS_LEN)
+
+/** Class constructor */
+TxFrame802::TxFrame802(uint64_t addr, uint8_t tx_options,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the tx options byte
+     * and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = tx_options;
+
+    if (len) {
+        memcpy(&frame_data[10], data, len);
+    }
+
+    set_api_frame(TxReq64Bit, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrame802::TxFrame802(uint16_t addr16, uint8_t tx_options,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD2 + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 16bit remote address, the tx options byte
+     * and the frame data */
+
+    frame_data[0] = _frame_id;
+    frame_data[1] = (uint8_t)(addr16 >> 8);
+    frame_data[2] = (uint8_t)addr16;
+    frame_data[3] = tx_options;
+
+    if (len) {
+        memcpy(&frame_data[4], data, len);
+    }
+
+    set_api_frame(TxReq16Bit, frame_data, TX_REQUEST_OVERHEAD2 + len);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/802_Frames.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/802_Frames.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__802_FRAMES_H_)
+#define __802_FRAMES_H_
+
+#include "ApiFrame.h"
+
+class TxFrame802 : public ApiFrame
+{
+    public:
+        /** Class constructor */
+        TxFrame802(uint64_t addr, uint8_t tx_options, const uint8_t *const data, uint16_t len);
+        TxFrame802(uint16_t addr16, uint8_t tx_options, const uint8_t *const data, uint16_t len);
+
+    protected:
+};
+
+#endif /* __802_FRAMES_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/ApiFrame.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/ApiFrame.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,132 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "mbed.h"
+#include "XBee/XBee.h"
+#include "ApiFrame.h"
+
+using namespace XBeeLib;
+
+uint8_t ApiFrame::last_frame_id = 0;
+
+ApiFrame::ApiFrame(void)
+{
+    this->_type = Invalid;
+    this->_data = NULL;
+    this->_data_frame_len = 0;
+    this->_alloc_data = false;
+    _frame_id = get_next_frame_id();
+}
+
+ApiFrame::ApiFrame(uint16_t len)
+{
+    this->_type = Invalid;
+    this->_data = new uint8_t[len];
+    this->_alloc_data = true;
+    this->_data_frame_len = len;
+    this->_frame_id = get_next_frame_id();
+}
+
+uint8_t ApiFrame::get_next_frame_id(void)
+{
+    last_frame_id++;
+    if (last_frame_id == 0) {
+        last_frame_id++;
+    }
+
+    return last_frame_id;
+}
+
+ApiFrame::ApiFrame(ApiFrameType type, const uint8_t *data, uint16_t len)
+{
+    this->_data = NULL;
+    set_api_frame(type, data, len);
+}
+
+void ApiFrame::set_api_frame(ApiFrameType type, const uint8_t *data, uint16_t len)
+{
+    this->_type = type;
+    this->_data_frame_len = len;
+    if (this->_data) {
+        delete _data;
+    }
+    this->_data = new uint8_t[len];
+    this->_alloc_data = true;
+    assert(this->_data != NULL);
+    memcpy((void *)this->_data, data, len);
+}
+
+ApiFrame::~ApiFrame()
+{
+    if (this->_data != NULL && this->_alloc_data) {
+        delete[] this->_data;
+    }
+}
+
+void ApiFrame::dump(void) const
+{
+#if defined(ENABLE_LOGGING)
+    digi_log(LogLevelFrameData, "API frame: type %02x, len %d\r\n", this->_type, this->_data_frame_len);
+    for (int i = 0; i < this->_data_frame_len; i++)
+        digi_log(LogLevelFrameData, "%02x ", this->_data[i]);
+    digi_log(LogLevelFrameData, "\r\n");
+#endif
+}
+
+void ApiFrame::dump_if(ApiFrameType type)
+{
+    if (_type != type) {
+        return;
+    }
+    dump();
+}
+
+ApiFrame::ApiFrameType ApiFrame::get_frame_type() const
+{
+    return _type;
+}
+
+void ApiFrame::set_frame_type(ApiFrameType type)
+{
+    _type = type;
+}
+
+uint16_t ApiFrame::get_data_len() const
+{
+    return _data_frame_len;
+}
+
+void ApiFrame::set_data_len(uint16_t len)
+{
+    _data_frame_len = len;
+}
+
+const uint8_t *ApiFrame::get_data() const
+{
+    return _data;
+}
+
+uint8_t ApiFrame::get_data_at(uint16_t index) const
+{
+    return *(_data + index);
+}
+
+void ApiFrame::set_data(uint8_t d, uint16_t index)
+{
+    *(_data + index) = d;
+}
+
+/* Returns the frame_id of this frame */
+uint8_t ApiFrame::get_frame_id() const
+{
+    return _frame_id;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/ApiFrame.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/ApiFrame.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,177 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__API_FRAME_H_)
+#define __API_FRAME_H_
+
+#include "XBee/Addresses.h"
+
+/** Class for XBee API frames */
+class ApiFrame
+{
+    /** Static variable that contains the last frame ID value assigned */
+    static uint8_t      last_frame_id;
+
+        public:
+        /** List of API frames. Note that not all frames are supported by all radios */
+        enum ApiFrameType {
+
+            TxReq64Bit      = 0x00,     /**< TxReq64Bit: Only for 802.15.4 modules */
+            TxReq16Bit      = 0x01,     /**< TxReq16Bit: Only for 802.15.4 modules */
+            AtCmd           = 0x08,     /**< AtCmd */
+            AtCmdQueuePV    = 0x09,     /**< AtCmdQueuePV */
+            TxReqZBDM       = 0x10,     /**< TxReqZBDM: Only for ZigBee and DigiMesh modules */
+            ExpAddrCmd      = 0x11,     /**< ExpAddrCmd: Only for ZigBee modules and DigiMesh */
+            RemoteCmdReq    = 0x17,     /**< RemoteCmdReq */
+            CreateSrcRoute  = 0x21,     /**< CreateSrcRoute */
+            RxPacket64Bit   = 0x80,     /**< RxPacket64Bit: Only for 802.15.4 modules */
+            RxPacket16Bit   = 0x81,     /**< RxPacket16Bit: Only for 802.15.4 modules */
+            Io64Bit         = 0x82,     /**< Io64Bit: Only for 802.15.4 modules */
+            Io16Bit         = 0x83,     /**< Io16Bit */
+            AtCmdResp       = 0x88,     /**< AtCmdResp */
+            TxStatus        = 0x89,     /**< TxStatus */
+            AtModemStatus   = 0x8A,     /**< AtModemStatus */
+            TxStatusZBDM    = 0x8B,     /**< TxStatusZBDM: Only for ZigBee and DigiMesh modules */
+            RouteInfo       = 0x8D,     /**< RouteInfo: Only for DigiMesh modules */
+            AggregateAddr   = 0x8E,     /**< AggregateAddr: Only for DigiMesh modules */
+            RxPacketAO0     = 0x90,     /**< RxPacketAO0: Only for ZigBee and DigiMesh modules */
+            RxPacketAO1     = 0x91,     /**< RxPacketAO1: Only for ZigBee and DigiMesh modules */
+            IoSampleRxZBDM  = 0x92,     /**< IoSampleRxZBDM: Only for ZigBee and DigiMesh modules */
+            SensorRxIndAO0  = 0x94,     /**< SensorRxIndAO0: Only for ZigBee modules */
+            NodeIdentIndAO0 = 0x95,     /**< NodeIdentIndAO0: Only for ZigBee and DigiMesh modules */
+            RemoteCmdResp   = 0x97,     /**< RemoteCmdResp */
+            OtaFwUpStatus   = 0xA0,     /**< OtaFwUpStatus */
+            RouteRecInd     = 0xA1,     /**< RouteRecInd */
+            Many2OneRRInd   = 0xA3,     /**< Many2OneRRInd */
+            Invalid         = ~0,       /**< Invalid */
+        };
+
+        /** Default constructor */
+        ApiFrame();
+
+        /** Constructor
+         *
+         * @param len length of the API frame (will allocate len bytes).
+         */
+        ApiFrame(uint16_t len);
+
+        /** Constructor
+         *
+         * @param type frame type of this api frame.
+         * @param data pointer to frame data payload.
+         * @param len length of the payload.
+         */
+        ApiFrame(ApiFrameType type, const uint8_t *data, uint16_t len);
+
+        /** Destructor */
+        ~ApiFrame();
+
+        ApiFrame(const ApiFrame& other); /* Intentionally not implemented */
+
+        /** get_frame_type gets the type of the frame
+         *
+         * @returns the type of this frame.
+         */
+        ApiFrameType get_frame_type() const;
+
+        /** dump dumps the information of this frame */
+        void dump() const;
+
+        /** dump_if dumps the information of the frame if the frame type matches
+         *          with the parameter.
+         *
+         * @param type dump the frame info/data if the frame type matches with type.
+         */
+        void dump_if(ApiFrameType type);
+
+
+        /** set_frame_type sets the type of the frame to type.
+         *
+         * @param type the type we want to set on the frame.
+         */
+        void set_frame_type(ApiFrameType type);
+
+        /** get_data_len gets the length of the frame data payload.
+         *
+         * @returns the length of the data payload.
+         */
+        uint16_t get_data_len() const;
+
+        /** set_data_len sets the length of the frame data payload.
+         *
+         * @param len the length of the data payload will be set on this frame.
+         */
+        void set_data_len(uint16_t len);
+
+        /** get_data returns a pointer to the frame data payload.
+         *
+         * @returns a pointer to the frame data payload.
+         */
+        const uint8_t *get_data() const;
+
+        /** get_data_at returns the byte at index offset.
+         *
+         * @param index offset of the byte we want to get.
+         * @returns the byte at index offset.
+         */
+        uint8_t get_data_at(uint16_t index) const;
+
+        /** set_data sets data byte at the specified index or offset.
+         *
+         * @param data byte that will be set at index position.
+         * @param index offset of the byte we want to set.
+         */
+        void set_data(uint8_t data, uint16_t index);
+
+        /** get_frame_id returns the frame id of this frame.
+         *
+         * @returns the frame id of this frame.
+         */
+        uint8_t get_frame_id() const;
+
+        static uint8_t get_current_frame_id()
+        {
+            return last_frame_id;
+        }
+
+    protected:
+        /** Type of this frame */
+        ApiFrameType        _type;
+
+        /** length of the payload, excluding the frame type */
+        uint16_t            _data_frame_len;
+
+        /** pointer to the frame data */
+        uint8_t             *_data;
+
+        /** True if the constructor allocates the data. Needed to delete it on the destructor */
+        bool                _alloc_data;
+
+        /** Frame ID of this frame */
+        uint8_t             _frame_id;
+
+        /** get_next_frame_id - returns the next frame ID secuentially, skipping the value 0
+         *
+         *  @returns the next frame ID that should be assigned to a frame
+         */
+        uint8_t get_next_frame_id();
+
+        /** set_api_frame sets several members
+         *
+         * @param type frame type of this api frame.
+         * @param data pointer to frame data payload.
+         * @param len length of the payload.
+         */
+        void set_api_frame(ApiFrameType type, const uint8_t *data, uint16_t len);
+};
+
+#endif /* __API_FRAME_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/AtCmdFrame.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/AtCmdFrame.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "mbed.h"
+#include "Utils/Debug.h"
+#include "AtCmdFrame.h"
+
+#define AT_CMD_LEN              2
+#define AT_CMD_ID_LEN           1
+
+void AtCmdFrame::build_at_cmd_frame(const char *cmd, const uint8_t *cmd_params, uint8_t payload_len, bool reverse)
+{
+    uint8_t frame_data[AT_CMD_LEN + AT_CMD_ID_LEN + payload_len];
+
+    frame_data[0] = _frame_id;
+    frame_data[1] = cmd[0];
+    frame_data[2] = cmd[1];
+    if (payload_len) {
+        if (reverse) {
+            rmemcpy(&frame_data[3], cmd_params, payload_len);
+        } else {
+            memcpy(&frame_data[3], cmd_params, payload_len);
+        }
+    }
+
+    set_api_frame(AtCmd, frame_data, AT_CMD_LEN + AT_CMD_ID_LEN + payload_len);
+}
+
+AtCmdFrame::AtCmdFrame(const char * const cmd, uint32_t cmd_param)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    uint8_t len;
+    if (cmd_param <= 0xFF) {
+        len = 1;
+    } else if (cmd_param <= 0xFFFF) {
+        len = 2;
+    } else if (cmd_param <= 0xFFFFFF) {
+        len = 3;
+    } else {
+        len = 4;
+    }
+    build_at_cmd_frame(cmd, (uint8_t *)&cmd_param, len);
+}
+
+AtCmdFrame::AtCmdFrame(const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_frame(cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote, const char * const cmd, uint32_t cmd_param)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(remote, ADDR16_UNKNOWN, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote, const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(remote, ADDR16_UNKNOWN, cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint16_t remote, const char * const cmd, uint32_t cmd_param)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(ADDR64_UNASSIGNED, remote, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint16_t remote, const char * const cmd, const uint8_t * cmd_param, uint16_t param_len)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(ADDR64_UNASSIGNED, remote, cmd, cmd_param, param_len, false);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, uint32_t cmd_param)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(remote64, remote16, cmd, (uint8_t *)&cmd_param, 4);
+}
+
+AtCmdFrame::AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd,
+                           const uint8_t * cmd_param, uint16_t param_len)
+{
+    assert(cmd != NULL);
+    assert(strlen(cmd) == AT_CMD_LEN);
+
+    build_at_cmd_remote_frame(remote64, remote16, cmd, cmd_param, param_len, false);
+}
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define OPTIONS_LEN               1
+#define AT_CMD_LEN                2
+#define REM_AT_CMD_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + \
+                                   ADDR16_LEN + OPTIONS_LEN + \
+                                   AT_CMD_LEN)
+
+void AtCmdFrame::build_at_cmd_remote_frame(uint64_t remote64, uint16_t remote16,
+                const char *const cmd, const uint8_t *const cmd_params, uint8_t params_len, bool reverse)
+{
+    uint8_t frame_data[REM_AT_CMD_OVERHEAD + params_len];
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     *  the options byte, the command and the command params */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&remote64, sizeof remote64);
+    frame_data[9] = (uint8_t)(remote16 >> 8);
+    frame_data[10] = (uint8_t)remote16;
+    frame_data[11] = 0x02; /* TODO Options */
+    frame_data[12] = cmd[0];
+    frame_data[13] = cmd[1];
+
+    if (params_len) {
+        if (reverse) {
+            rmemcpy(&frame_data[14], cmd_params, params_len);
+        } else {
+            memcpy(&frame_data[14], cmd_params, params_len);
+        }
+    }
+
+    set_api_frame(RemoteCmdReq, frame_data, REM_AT_CMD_OVERHEAD + params_len);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/AtCmdFrame.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/AtCmdFrame.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,168 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__AT_CMD_FRAME_H_)
+#define __AT_CMD_FRAME_H_
+
+#include "ApiFrame.h"
+
+#define REM_AT_CMD_RESP_FRM_ID_OFFSET   0
+#define REM_AT_CMD_RESP_STATUS_OFFSET   13
+#define REM_AT_CMD_RESP_CMD_DATA_OFFSET 14
+#define REM_AT_CMD_RESP_OVERHEAD        14 /* ID + ADDR64 + ADDR16 + CMD + status */
+
+#define ATCMD_RESP_FRAME_ID_OFFSET      0
+#define ATCMD_RESP_CMD_LOW_OFFSET       1
+#define ATCMD_RESP_CMD_HIGH_OFFSET      2
+#define ATCMD_RESP_STATUS_OFFSET        3
+#define ATCMD_RESP_DATA_OFFSET          4
+#define ATCMD_RESP_NW_ADDR_H_OFFSET     4
+#define ATCMD_RESP_NW_ADDR_L_OFFSET     5
+#define ATCMD_RESP_SH_ADDR_L_OFFSET     6
+#define ATCMD_RESP_SH_ADDR_H_OFFSET     10
+#define ATCMD_RESP_NI_OFFSET            14
+
+#define ATCMD_RESP_OVERHEAD             4 /* ID + CMD + status */
+
+#define ATCMD_802_RESP_SIGN_STR_OFFSET  14
+#define ATCMD_802_RESP_NI_OFFSET        15
+
+#define MAX_NI_PARAM_LEN                20
+
+/** Class for the AT command api frames. Derived from ApiFrame */
+class AtCmdFrame : public ApiFrame
+{
+    public:
+
+        /**
+         * AtCmdResp
+         */
+        enum AtCmdResp {
+            AtCmdRespOk             = 0,     /**< Ok */
+            AtCmdRespError          = 1,     /**< Error */
+            AtCmdRespInvalidCmd     = 2,     /**< Invalid Command */
+            AtCmdRespInvalidParam   = 3,     /**< Invalid Parameter */
+            AtCmdRespTxFailure      = 4,     /**< Tx Failure */
+            AtCmdRespLenMismatch    = 0xfd,  /**< Length Mismatch (Error generated by the library) */
+            AtCmdRespInvalidAddr    = 0xfe,  /**< Invalid Address (Error generated by the library) */
+            AtCmdRespTimeout        = 0xff,   /**< Timeout (Error generated by the library) */
+        };
+
+        /**
+         * ModemStatus
+         */
+        enum ModemStatus {
+            HwReset         = 0,     /**< Hardware reset */
+            WdReset         = 1,     /**< Watchdog timer reset */
+            JoinedNW        = 2,     /**< Joined network (routers and end devices) */
+            Disassociated   = 3,     /**< Disassociated */
+            SyncLost        = 4,     /**< Synchronization Lost */
+            CoordRealign    = 5,     /**< Coordinator realignment */
+            CoordStarted    = 6,     /**< Coordinator started */
+            NwSecKeyUpdated = 7,     /**< Network security key was updated */
+            NwWokeUp        = 0x0B,  /**< NwWokeUp */
+            NwToSleep       = 0x0C,  /**< NwToSleep */
+            VccExceeded     = 0x0D,  /**< VccExceeded: PRO S2B only? */
+            ModConfChangeJoinInProg = 0x11, /**< Modem configuration changed while join in progress */
+        };
+
+        /** Class constructor
+         *
+         * @param cmd at command of the frame
+         * @param cmd_param command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(const char * const cmd, const uint32_t cmd_param);
+
+        /** Class constructor
+         *
+         * @param cmd at command of the frame
+         * @param cmd_param pointer to command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+        /** Class constructor
+         *
+         * @param remote 64 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param command parameter
+         */
+        AtCmdFrame(uint64_t remote, const char * const cmd, uint32_t cmd_param);
+
+        /** Class constructor
+         *
+         * @param remote 64 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param pointer to command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(uint64_t remote, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+        /** Class constructor
+         *
+         * @param remote 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param command parameter
+         */
+        AtCmdFrame(uint16_t remote, const char * const cmd, uint32_t cmd_param);
+
+        /** Class constructor
+         *
+         * @param remote 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param pointer to command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(uint16_t remote, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+        /** Class constructor
+         *
+         * @param remote 64 bit address of the remote device where we want to run the command
+         * @param remote 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param command parameter
+         */
+        AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, uint32_t cmd_param);
+
+        /** Class constructor
+         *
+         * @param remote 64 bit address of the remote device where we want to run the command
+         * @param remote 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_param pointer to command parameter
+         * @param param_len length of the command param
+         */
+        AtCmdFrame(uint64_t remote64, uint16_t remote16, const char * const cmd, const uint8_t * cmd_param = NULL, uint16_t param_len = 0);
+
+    protected:
+        /** build_at_cmd_frame method used by the constructors to create the at command frame
+         *
+         * @param cmd at command of the frame
+         * @param cmd_params pointer to command parameter
+         * @param param_len length of the command param
+         */
+        void build_at_cmd_frame(const char *cmd, const uint8_t *cmd_params, uint8_t payload_len, bool reverse = true);
+
+        /** build_at_cmd_remote_frame method used by the constructors to create the at command frame
+         *
+         * @param remote64 64 bit address of the remote device where we want to run the command
+         * @param remote16 16 bit address of the remote device where we want to run the command
+         * @param cmd at command of the frame
+         * @param cmd_params pointer to command parameter
+         * @param param_len length of the command param
+         */
+        void build_at_cmd_remote_frame(uint64_t remote64, uint16_t remote16,
+                const char *const cmd, const uint8_t *const cmd_params, uint8_t payload_len, bool reverse = true);
+};
+
+#endif /* __AT_CMD_FRAME_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "DigiMeshFrames.h"
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define BROADCAST_RADIOUS_LEN     1
+#define OPTIONS_LEN               1
+#define TX_REQUEST_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + \
+                                   ADDR16_LEN + BROADCAST_RADIOUS_LEN + \
+                                   OPTIONS_LEN)
+#define SOURCE_EP_LEN             1
+#define DEST_EP_LEN               1
+#define CLUSTER_ID_LEN            2
+#define PROFILE_ID_LEN            2
+
+#define EXP_ADDR_OVERHEAD         (TX_REQUEST_OVERHEAD + SOURCE_EP_LEN + \
+                                   DEST_EP_LEN + CLUSTER_ID_LEN + \
+                                   PROFILE_ID_LEN)
+
+/** Class constructor */
+TxFrameDM::TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad, uint8_t tx_opt,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = broadcast_rad;
+    frame_data[12] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[13], data, len);
+    }
+
+    set_api_frame(TxReqZBDM, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrameDM::TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[EXP_ADDR_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the end point source and destination addresses, the cluster and profile IDs,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = source_ep;
+    frame_data[12] = dest_ep;
+    frame_data[13] = (uint8_t)(cluster_id >> 8);
+    frame_data[14] = (uint8_t)cluster_id;
+    frame_data[15] = (uint8_t)(profile_id >> 8);
+    frame_data[16] = (uint8_t)profile_id;
+    frame_data[17] = broadcast_rad;
+    frame_data[18] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[19], data, len);
+    }
+
+    set_api_frame(ExpAddrCmd, frame_data, EXP_ADDR_OVERHEAD + len);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/DigiMeshFrames.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DIGIMESH_FRAME_H_)
+#define __DIGIMESH_FRAME_H_
+
+#include "ApiFrame.h"
+
+class TxFrameDM : public ApiFrame
+{
+    public:
+        /** Class constructor */
+        TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad,
+                    uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+
+        /** Class constructor */
+        TxFrameDM(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+};
+
+#endif /* __DIGIMESH_FRAME_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,88 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "ZigbeeFrames.h"
+
+#define FRAME_ID_LEN              1
+#define ADDR64_LEN                8
+#define ADDR16_LEN                2
+#define BROADCAST_RADIOUS_LEN     1
+#define OPTIONS_LEN               1
+#define TX_REQUEST_OVERHEAD       (FRAME_ID_LEN + ADDR64_LEN + \
+                                   ADDR16_LEN + BROADCAST_RADIOUS_LEN + \
+                                   OPTIONS_LEN)
+#define SOURCE_EP_LEN             1
+#define DEST_EP_LEN               1
+#define CLUSTER_ID_LEN            2
+#define PROFILE_ID_LEN            2
+
+#define EXP_ADDR_OVERHEAD         (TX_REQUEST_OVERHEAD + SOURCE_EP_LEN + \
+                                   DEST_EP_LEN + CLUSTER_ID_LEN + \
+                                   PROFILE_ID_LEN)
+
+/** Class constructor */
+TxFrameZB::TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad, uint8_t tx_opt,
+                const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[TX_REQUEST_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = broadcast_rad;
+    frame_data[12] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[13], data, len);
+    }
+
+    set_api_frame(TxReqZBDM, frame_data, TX_REQUEST_OVERHEAD + len);
+}
+
+/** Class constructor */
+TxFrameZB::TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len)
+{
+    uint8_t frame_data[EXP_ADDR_OVERHEAD + len];
+
+    _frame_id = get_next_frame_id();
+
+    /* copy the frame id, the 64bit remote address, the 16bit network address,
+     * the end point source and destination addresses, the cluster and profile IDs,
+     * the broad cast radious, the options byte and the frame data */
+
+    frame_data[0] = _frame_id;
+    rmemcpy(&frame_data[1], (const uint8_t *)&addr, sizeof addr);
+    frame_data[9] = (uint8_t)(addr16 >> 8);
+    frame_data[10] = (uint8_t)addr16;
+    frame_data[11] = source_ep;
+    frame_data[12] = dest_ep;
+    frame_data[13] = (uint8_t)(cluster_id >> 8);
+    frame_data[14] = (uint8_t)cluster_id;
+    frame_data[15] = (uint8_t)(profile_id >> 8);
+    frame_data[16] = (uint8_t)profile_id;
+    frame_data[17] = broadcast_rad;
+    frame_data[18] = tx_opt;
+
+    if (len) {
+        memcpy(&frame_data[19], data, len);
+    }
+
+    set_api_frame(ExpAddrCmd, frame_data, EXP_ADDR_OVERHEAD + len);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Frames/ZigbeeFrames.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__ZIGBEE_FRAME_H_)
+#define __ZIGBEE_FRAME_H_
+
+#include "ApiFrame.h"
+
+class TxFrameZB : public ApiFrame
+{
+    public:
+        /** Class constructor */
+        TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t broadcast_rad,
+                    uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+
+        /** Class constructor */
+        TxFrameZB(uint64_t addr, uint16_t addr16, uint8_t source_ep, uint8_t dest_ep,
+                  uint16_t cluster_id, uint16_t profile_id, uint8_t broadcast_rad,
+                  uint8_t tx_opt, const uint8_t *const data, uint16_t len);
+};
+
+#endif /* __ZIGBEE_FRAME_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IO.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IO.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef __IO_H_
+#define __IO_H_
+
+#define DR_PWM_MAX_VAL      0x3FF
+
+namespace XBeeLib {
+
+/**
+ * @defgroup IoMode
+ * @{
+ */
+/**
+ * IoMode
+ */
+enum IoMode {
+    Disabled         = 0,  /**< Disabled */
+    SpecialFunc      = 1,  /**< Special Function */
+    Adc              = 2,  /**< Adc */
+    Pwm              = 2,  /**< Pwm */
+    DigitalInput     = 3,  /**< Digital Input */
+    DigitalOutLow    = 4,  /**< Digital Out Low */
+    DigitalOutHigh   = 5,  /**< Digital Out High */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup DioVal
+ * @{
+ */
+/**
+ * DioVal
+ */
+enum DioVal {
+    Low     = 0,      /**< Low Value */
+    High    = 1,      /**< High Value */
+};
+/**
+ * @}
+ */
+
+}   /* namespace XBeeLib */
+
+
+#endif /* __IO_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSample802.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSample802.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "IO/IOSample802.h"
+#include "Utils/Debug.h"
+
+#define IO_SAMPLE_802_DIGITAL_INPUTS_MASK   0x01FF
+#define IO_SAMPLE_802_DIGITAL_INPUTS_COUNT  9
+#define IO_SAMPLE_802_MIN_SIZE              (2 + 2)
+
+using namespace XBeeLib;
+
+IOSample802::IOSample802(const uint8_t* const raw_data, size_t size)
+{
+    if (raw_data == NULL || size == 0) {
+        _channel_mask = 0;
+        return;
+    }
+    assert(size >= IO_SAMPLE_802_MIN_SIZE);
+    assert(size <= sizeof _sampled_data);
+
+    _channel_mask = UINT16(raw_data[1], raw_data[2]);
+    _sampled_data_size = size - 3;
+    memcpy(&_sampled_data[0], &raw_data[3], _sampled_data_size);
+}
+
+IOSample802::~IOSample802()
+{
+
+}
+
+RadioStatus IOSample802::get_dio(XBee802::IoLine line, DioVal* const dio_value) const
+{
+    if (line > XBee802::DI8) {
+        digi_log(LogLevelError, "get_dio: Pin %d not supported as IO\r\n", line);
+        return Failure;
+    }
+
+    const uint16_t mask = 1 << line;
+    if (mask & _channel_mask) {
+        const uint8_t digital_channels = get_dio_channels();
+
+        *dio_value = digital_channels & mask ? High : Low;
+        return Success;
+    }
+    return Failure;
+}
+
+RadioStatus IOSample802::get_adc(XBee802::IoLine line, uint16_t* const val) const
+{
+    if (line > XBee802::DIO5_AD5) {
+        digi_log(LogLevelError, "get_adc: Pin %d not supported as ADC\r\n", line);
+        return Failure;
+    }
+    const uint8_t analog_mask = _channel_mask >> IO_SAMPLE_802_DIGITAL_INPUTS_COUNT;
+    const uint8_t line_mask = 1 << line;
+    const bool adc_present = line_mask & analog_mask;
+    if (!adc_present) {
+        return Failure;
+    }
+
+    uint8_t analog_data_idx = dio_channels_present() == 0 ? 0 : 2;
+    uint8_t line_sample = 0;
+
+    while (analog_data_idx < _sampled_data_size) {
+        if (analog_mask & (1 << line_sample)) {
+            if (line_sample == line) {
+                /* Write the analog value */
+                *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+                break;
+            }
+            analog_data_idx += 2;
+        }
+        line_sample++;
+    }
+
+    return Success;
+}
+
+inline bool IOSample802::dio_channels_present(void) const
+{
+    return _channel_mask & IO_SAMPLE_802_DIGITAL_INPUTS_MASK;
+}
+
+inline uint8_t IOSample802::get_dio_channels(void) const
+{
+    if (dio_channels_present()) {
+        return UINT16(_sampled_data[0], _sampled_data[1]);
+    } else {
+        return 0;
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSample802.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSample802.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef _IO_IOSAMPLE802_H_
+#define _IO_IOSAMPLE802_H_
+
+#define MAX_IO_SAMPLE_802_LEN   100 //(2 + 2 * 20)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in 802.15.4 modules */
+class IOSample802 {
+    public:
+        /** Class constructor
+         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the Io16Bit (0x83) or Io64Bit (0x82) frames
+         *  @param size size (in bytes) of raw_data
+         */
+        IOSample802(const uint8_t* const raw_data = NULL, size_t size = 0);
+
+        /** Class destructor */
+        ~IOSample802();
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(XBee802::IoLine line, DioVal* const dio_value) const;
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from the ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(XBee802::IoLine line, uint16_t* const val) const;
+
+        /** is_valid - checks if the IOSample802 object has at least one DIO or ADC sample.
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid()
+        {
+            return _channel_mask != 0;
+        }
+
+    protected:
+        uint16_t _channel_mask;
+        uint8_t _sampled_data[MAX_IO_SAMPLE_802_LEN];
+        uint8_t _sampled_data_size;
+
+        inline bool dio_channels_present(void) const;
+        inline uint8_t get_dio_channels(void) const;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLE802_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSampleDM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSampleDM.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "IO/IOSampleDM.h"
+
+#define IO_SAMPLE_DM_MIN_SIZE              (2 + 1 + 2)
+
+using namespace XBeeLib;
+
+IOSampleDM::IOSampleDM(const uint8_t* const raw_data, size_t size)
+{
+    if (raw_data == NULL || size == 0) {
+        _digital_mask = 0;
+        _analog_mask = 0;
+        return;
+    }
+    assert(size >= IO_SAMPLE_DM_MIN_SIZE);
+    assert(size <= sizeof _sampled_data);
+
+    _digital_mask = UINT16(raw_data[1], raw_data[2]);
+    _analog_mask = raw_data[3];
+    _sampled_data_size = size - 4;
+    memcpy(&_sampled_data[0], &raw_data[4], _sampled_data_size);
+}
+
+IOSampleDM::~IOSampleDM()
+{
+
+}
+
+RadioStatus IOSampleDM::get_dio(XBeeDM::IoLine line, DioVal* const dio_value) const
+{
+    const uint16_t mask = 1 << line;
+    if (mask & _digital_mask) {
+        const uint16_t digital_channels = get_digital_channels();
+
+        *dio_value = digital_channels & mask ? High : Low;
+        return Success;
+    }
+    return Failure;
+}
+
+RadioStatus IOSampleDM::get_adc(XBeeDM::IoLine line, uint16_t* const val) const
+{
+    const uint8_t line_mask = 1 << line;
+    const bool adc_present = line_mask & _analog_mask;
+    if (!adc_present) {
+        return Failure;
+    }
+
+    uint8_t analog_data_idx = _digital_mask == 0 ? 0 : 2;
+    uint8_t line_sample = 0;
+
+    while (analog_data_idx < _sampled_data_size) {
+        if (_analog_mask & (1 << line_sample)) {
+            if (line_sample == line) {
+                /* Write the analog value */
+                *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+                break;
+            }
+            analog_data_idx += 2;
+        }
+        line_sample++;
+    }
+
+    return Success;
+}
+
+inline uint16_t IOSampleDM::get_digital_channels(void) const
+{
+    if (_digital_mask == 0) {
+        return 0;
+    }
+    return UINT16(_sampled_data[0], _sampled_data[1]);
+}
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSampleDM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSampleDM.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef _IO_IOSAMPLEDM_H_
+#define _IO_IOSAMPLEDM_H_
+
+#define MAX_IO_SAMPLE_DM_LEN   (2 + 2 * 5)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in ZigBee modules */
+class IOSampleDM {
+    public:
+        /** Class constructor
+         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the IoSampleRxZBDM (0x92) frames
+         *  @param size size (in bytes) of raw_data.
+         */
+        IOSampleDM(const uint8_t* const raw_data = NULL, size_t size = 0);
+
+        /** Class destructor */
+        ~IOSampleDM();
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(XBeeDM::IoLine line, DioVal* const dio_value) const;
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from the ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(XBeeDM::IoLine line, uint16_t* const val) const;
+
+        /** is_valid - checks if the IOSampleDM object has at least one DIO or ADC sample.
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid()
+        {
+            return _digital_mask != 0 || _analog_mask != 0;
+        }
+
+    protected:
+        uint16_t _digital_mask;
+        uint8_t _analog_mask;
+        uint8_t _sampled_data[MAX_IO_SAMPLE_DM_LEN];
+        uint8_t _sampled_data_size;
+
+        inline uint16_t get_digital_channels(void) const;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLEDM_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSampleZB.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSampleZB.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "IO/IOSampleZB.h"
+
+#define IO_SAMPLE_ZB_MIN_SIZE              (2 + 1 + 2)
+
+using namespace XBeeLib;
+
+IOSampleZB::IOSampleZB(const uint8_t* const raw_data, size_t size)
+{
+    if (raw_data == NULL || size == 0) {
+        _digital_mask = 0;
+        _analog_mask = 0;
+        return;
+    }
+    assert(size >= IO_SAMPLE_ZB_MIN_SIZE);
+    assert(size <= sizeof _sampled_data);
+
+    _digital_mask = UINT16(raw_data[1], raw_data[2]);
+    _analog_mask = raw_data[3];
+    _sampled_data_size = size - 4;
+    memcpy(&_sampled_data[0], &raw_data[4], _sampled_data_size);
+}
+
+IOSampleZB::~IOSampleZB()
+{
+
+}
+
+RadioStatus IOSampleZB::get_dio(XBeeZB::IoLine line, DioVal* const dio_value) const
+{
+    const uint16_t mask = 1 << line;
+    if (mask & _digital_mask) {
+        const uint16_t digital_channels = get_digital_channels();
+
+        *dio_value = digital_channels & mask ? High : Low;
+        return Success;
+    }
+    return Failure;
+}
+
+RadioStatus IOSampleZB::get_adc(XBeeZB::IoLine line, uint16_t* const val) const
+{
+    const uint8_t line_mask = 1 << line;
+    const bool adc_present = line_mask & _analog_mask;
+    if (!adc_present) {
+        return Failure;
+    }
+
+    uint8_t analog_data_idx = _digital_mask == 0 ? 0 : 2;
+    uint8_t line_sample = 0;
+
+    while (analog_data_idx < _sampled_data_size) {
+        if (_analog_mask & (1 << line_sample)) {
+            if (line_sample == line) {
+                /* Write the analog value */
+                *val = UINT16(_sampled_data[analog_data_idx], _sampled_data[analog_data_idx + 1]);
+                break;
+            }
+            analog_data_idx += 2;
+        }
+        line_sample++;
+    }
+
+    return Success;
+}
+
+inline uint16_t IOSampleZB::get_digital_channels(void) const
+{
+    if (_digital_mask == 0) {
+        return 0;
+    }
+    return UINT16(_sampled_data[0], _sampled_data[1]);
+}
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/IO/IOSampleZB.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/IO/IOSampleZB.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef _IO_IOSAMPLEZB_H_
+#define _IO_IOSAMPLEZB_H_
+
+#define MAX_IO_SAMPLE_ZB_LEN   (2 + 2 * 5)
+
+namespace XBeeLib {
+
+/** Class to handle the incoming IO Data Samples in ZigBee modules */
+class IOSampleZB {
+    public:
+        /** Class constructor
+         *  @param raw_data The IO Sample data, as returned by an "IS" command response or in the IoSampleRxZBDM (0x92) frames
+         *  @param size size (in bytes) of raw_data.
+         */
+        IOSampleZB(const uint8_t* const raw_data = NULL, size_t size = 0);
+
+        /** Class destructor */
+        ~IOSampleZB();
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(XBeeZB::IoLine line, DioVal* const dio_value) const;
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from the ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(XBeeZB::IoLine line, uint16_t* const val) const;
+
+        /** is_valid - checks if the IOSampleZB object has at least one DIO or ADC sample.
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid()
+        {
+            return _digital_mask != 0 || _analog_mask != 0;
+        }
+
+    protected:
+        uint16_t _digital_mask;
+        uint8_t _analog_mask;
+        uint8_t _sampled_data[MAX_IO_SAMPLE_ZB_LEN];
+        uint8_t _sampled_data_size;
+
+        inline uint16_t get_digital_channels(void) const;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* _IO_IOSAMPLEZB_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "RemoteXBee.h"
+
+using namespace XBeeLib;
+
+RemoteXBee::RemoteXBee()
+{
+    _dev_addr64 = ADDR64_UNASSIGNED;
+    _dev_addr16 = ADDR16_UNKNOWN;
+}
+
+RemoteXBee::RemoteXBee(uint64_t remote64) : _dev_addr64(remote64)
+{
+    _dev_addr16 = ADDR16_UNKNOWN;
+}
+
+RemoteXBee::~RemoteXBee()
+{
+}
+
+uint64_t RemoteXBee::get_addr64() const
+{
+    return _dev_addr64;
+}
+
+uint16_t RemoteXBee::get_addr16() const
+{
+    return _dev_addr16;
+}
+
+RemoteXBee802::RemoteXBee802() : RemoteXBee()
+{
+}
+
+RemoteXBee802::RemoteXBee802(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBee802::RemoteXBee802(uint16_t remote16) : RemoteXBee()
+{
+    _dev_addr16 = remote16;
+}
+
+RemoteXBee802::RemoteXBee802(uint64_t remote64, uint16_t remote16) : RemoteXBee(remote64)
+{
+    _dev_addr16 = remote16;
+}
+
+RemoteXBee802::~RemoteXBee802()
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB() : RemoteXBee()
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBeeZB::RemoteXBeeZB(uint64_t remote64, uint16_t remote16) : RemoteXBee(remote64)
+{
+    _dev_addr16 = remote16;
+}
+
+RemoteXBeeZB::~RemoteXBeeZB()
+{
+}
+
+RemoteXBeeDM::RemoteXBeeDM() : RemoteXBee()
+{
+}
+
+RemoteXBeeDM::RemoteXBeeDM(uint64_t remote64) : RemoteXBee(remote64)
+{
+}
+
+RemoteXBeeDM::~RemoteXBeeDM()
+{
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/RemoteXBee/RemoteXBee.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,182 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_REMOTE_H_)
+#define __XBEE_REMOTE_H_
+
+#include "XBee/Addresses.h"
+
+namespace XBeeLib {
+
+/** Class for Remote XBee modules. Not to be used directly. */
+class RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a remote device (connected wirelessly). No address set.
+         */
+        RemoteXBee();
+
+        /** Class constructor for a remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBee(uint64_t remote64);
+
+        /** Class destructor */
+        ~RemoteXBee();
+
+        /** get_addr64 - returns the 64bit address of the remote device
+         *
+         *  @returns the 64bit address of the remote device
+         */
+        uint64_t get_addr64() const;
+
+        /** get_addr16 - returns the 16bit address of the remote device
+         *
+         *  @returns the 16bit address of the remote device
+         */
+        uint16_t get_addr16() const;
+
+        /** operator == overload so the object can be compared to equal */
+        inline bool operator == (const RemoteXBee &b) const
+        {
+            return ((b._dev_addr16 == _dev_addr16) &&
+                    (b._dev_addr64 == _dev_addr64));
+        }
+
+        /** operator != overload so the object can be compared to not equal */
+        inline bool operator != (const RemoteXBee &b) const
+        {
+            return !(this == &b);
+        }
+
+        /** is_valid_addr16b - checks if the RemoteXBee object has a valid 16b address
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid_addr16b() const
+        {
+            return (_dev_addr16 != ADDR16_UNKNOWN);
+        }
+
+        /** is_valid_addr64b - checks if the RemoteXBee object has a valid 64b address
+         *  @returns true if valid, false otherwise
+         */
+        inline bool is_valid_addr64b() const
+        {
+            return !(_dev_addr64 == ADDR64_UNASSIGNED);
+        }
+
+
+    protected:
+        /** Remote Device 64 bit address */
+        uint64_t      _dev_addr64;
+
+        /** Remote Device 16 bit address */
+        uint16_t    _dev_addr16;
+};
+
+class FH_NodeDiscovery802;
+/** Class for 802.15.4 Remote XBee modules */
+class RemoteXBee802 : public RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a 802.15.4 remote device (connected wirelessly). No address set.
+         */
+        RemoteXBee802();
+
+        /** Class constructor for a 802.15.4 remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBee802(uint64_t remote64);
+
+        /** Class constructor for a 802.15.4 remote device (connected wirelessly) using 16bit addressing
+         * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+         */
+        RemoteXBee802(uint16_t remote16);
+
+        /** Class destructor */
+        ~RemoteXBee802();
+
+        inline bool is_valid(void)
+        {
+            return is_valid_addr64b() || is_valid_addr16b();
+        }
+
+    protected:
+
+        friend FH_NodeDiscovery802;
+        friend class XBee802;
+
+        /** Class constructor for a 802.15.4 remote device (connected wirelessly) for which both the 64-bit and 16-bit addresses are known.
+         * This constructor is only used by FH_NodeDiscovery802 class.
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+         */
+        RemoteXBee802(uint64_t remote64, uint16_t remote16);
+};
+
+/** Class for ZigBee Remote XBee modules */
+class RemoteXBeeZB : public RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a ZigBee remote device (connected wirelessly). No address set.
+         */
+        RemoteXBeeZB();
+
+       /** Class constructor for a ZigBee remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBeeZB(uint64_t remote64);
+
+        /** Class constructor for a ZigBee remote device (connected wirelessly) using 64bit and 16b addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         * @param remote16 the 16-bit address (ATMY parameter) of the remote XBee module
+         */
+        RemoteXBeeZB(uint64_t remote64, uint16_t remote16);
+
+        /** Class destructor */
+        ~RemoteXBeeZB();
+
+        inline bool is_valid(void)
+        {
+            return is_valid_addr64b();
+        }
+};
+
+/** Class for DigiMesh Remote XBee modules */
+class RemoteXBeeDM : public RemoteXBee
+{
+    public:
+
+         /** Default Class constructor for a DigiMesh remote device (connected wirelessly). No address set.
+         */
+        RemoteXBeeDM();
+
+       /** Class constructor for a DigiMesh remote device (connected wirelessly) using 64bit addressing
+         * @param remote64 the 64-bit address (ATSH and ATSL parameters) of the remote XBee module
+         */
+        RemoteXBeeDM(uint64_t remote64);
+
+        /** Class destructor */
+        ~RemoteXBeeDM();
+
+        inline bool is_valid(void)
+        {
+            return is_valid_addr64b();
+        }
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* defined(__XBEE_REMOTE_H_) */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Utils/Debug.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Utils/Debug.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DEBUG_H_)
+#define __DEBUG_H_
+
+#include "config.h"
+
+#if defined(ENABLE_LOGGING)
+
+#include "DigiLogger.h"
+
+#define digi_log(...)  DigiLog::DigiLogger::log_format(__VA_ARGS__);
+#else
+#define digi_log(...)  do {} while(0)
+#endif
+
+#if defined(ENABLE_ASSERTIONS)
+#include "mbed.h"
+#if !(defined assert)
+#define assert(expr)            if (!(expr)) {                                      \
+                                    digi_log(LogLevelNone, "Assertion failed: %s, file %s, line %d\n", \
+                                         #expr, __FILE__, __LINE__);                \
+                                    mbed_die();                                     \
+                                }
+#endif
+#else
+#define assert(expr)
+#endif
+
+#endif /* __DEBUG_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Utils/Utils.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Utils/Utils.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "Utils.h"
+#include <string.h>
+
+void rmemcpy(uint8_t * const dest, const uint8_t * const src, uint16_t bytes)
+{
+    uint8_t *destp = dest + bytes - 1;
+    uint8_t *srcp = (uint8_t *)src;
+
+    while (destp >= dest)
+        *destp-- = *srcp++;
+}
+
+uint64_t addr64_from_uint8_t(const uint8_t * const data, bool big_endian = true)
+{
+    int64_t addr64;
+    if (big_endian) {
+        rmemcpy((uint8_t *)&addr64, data, 8);
+    } else {
+        memcpy((uint8_t *)&addr64, data, 8);
+    }
+    return addr64;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/Utils/Utils.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/Utils/Utils.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__XB_UTILS_H_)
+#define __XB_UTILS_H_
+
+#include <stdint.h>
+
+/** Buils an uint16_t out of 2 single bytes */
+#define UINT16(msb,lsb)     (uint16_t)(((msb) << 8) | (lsb))
+/** Buils an uint64_t out of 2 uint32_t */
+#define UINT64(msb,lsb)     (uint64_t)(((uint64_t)(msb) << 32) | (lsb))
+
+#define UINT64_HI32(u64)     (uint32_t)((u64) >> 32)
+#define UINT64_LO32(u64)     (uint32_t)((u64) & 0xFFFFFFFF)
+
+#define UNUSED_PARAMETER(a)  ((void)(a))
+
+/** rmemcpy - like memcpy but copies the bytes in reverse order
+ *
+ *  @param dest pointer with the destination address
+ *  @param src pointer with the source address
+ *  @param bytes number of bytes that will be copied
+ */
+void rmemcpy(uint8_t * const dest, const uint8_t * const src, uint16_t bytes);
+
+#endif /* __XB_UTILS_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/Addresses.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/Addresses.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef __ADDRESSES_H_
+#define __ADDRESSES_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#include "Utils/Utils.h"
+
+/* Some commonly used addresses */
+#define ADDR64_BROADCAST         ((uint64_t)0x000000000000FFFF)
+#define ADDR64_COORDINATOR       ((uint64_t)0x0000000000000000)
+#define ADDR64_UNASSIGNED        ((uint64_t)0xFFFFFFFFFFFFFFFF)
+
+#define ADDR16_UNKNOWN           ((uint16_t)0xFFFE)
+#define ADDR16_BROADCAST         ((uint16_t)0xFFFF)
+
+/** Macro used to create a 16bit data type from 2 bytes */
+#define ADDR16(msb,lsb)             UINT16(msb,lsb)
+
+uint64_t addr64_from_uint8_t(const uint8_t * const data, bool big_endian = true);
+
+#endif /* __ADDRESSES_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/AtCommands.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/AtCommands.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,144 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+
+#define GET_CMD_RESP(fr, radio_location)    (radio_location == RadioRemote ? fr->get_data_at(REM_AT_CMD_RESP_STATUS_OFFSET) \
+                                                                   : fr->get_data_at(ATCMD_RESP_STATUS_OFFSET))
+
+#define GET_DATA_LEN(fr, radio_location)    (radio_location == RadioRemote ? (fr->get_data_len() - REM_AT_CMD_RESP_OVERHEAD) \
+                                                                   : (fr->get_data_len() - ATCMD_RESP_OVERHEAD))
+
+#define GET_DATA_OFF(radio_location)        (radio_location == RadioRemote ? REM_AT_CMD_RESP_CMD_DATA_OFFSET \
+                                                                   : ATCMD_RESP_DATA_OFFSET)
+
+using namespace XBeeLib;
+
+/** Method that sends an AT command to the module and waits for the command response.
+ *  @returns the AT command response */
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame,
+     uint8_t *const buf, uint16_t *const len, RadioLocation radio_location, bool reverse)
+{
+    AtCmdFrame::AtCmdResp resp = AtCmdFrame::AtCmdRespTimeout;
+    ApiFrame *resp_frame;
+    ApiFrame::ApiFrameType expected_type =
+            (frame->get_frame_type() == ApiFrame::AtCmd) ?
+            ApiFrame::AtCmdResp : ApiFrame::RemoteCmdResp;
+
+    send_api_frame(frame);
+
+    /* Wait for the AT command response packet */
+    resp_frame = get_this_api_frame(frame->get_frame_id(), expected_type);
+    if (resp_frame == NULL) {
+        return resp;
+    }
+
+    resp = (AtCmdFrame::AtCmdResp)GET_CMD_RESP(resp_frame, radio_location);
+    if (resp == AtCmdFrame::AtCmdRespOk) {
+        if (buf != NULL && len != NULL) {
+
+            /* Copy the command response data */
+            uint16_t new_len = GET_DATA_LEN(resp_frame, radio_location);
+
+            *len = (*len < new_len) ? *len : new_len;
+
+            /* rmemcpy makes the endian change */
+            if (reverse) {
+                rmemcpy(buf, resp_frame->get_data() + GET_DATA_OFF(radio_location), *len);
+            } else {
+                memcpy(buf, resp_frame->get_data() + GET_DATA_OFF(radio_location), *len);
+            }
+        }
+    } else {
+        digi_log(LogLevelWarning, "send_at_cmd bad response: 0x%x\r\n", resp);
+    }
+
+    /* Once processed, remove the frame from the buffer */
+    _framebuf_syncr.free_frame(resp_frame);
+    return resp;
+}
+
+/** Method that sends an AT command to the module and waits for the command response.
+ *  @returns the AT command response */
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame)
+{
+    return send_at_cmd(frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint8_t *data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, data, &len);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint16_t *data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, (uint8_t *)data, &len);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::send_at_cmd(AtCmdFrame *frame, uint32_t *data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(frame, (uint8_t *)data, &len);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len != sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::get_param(const char * const param, uint32_t * const data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame cmd_frame = AtCmdFrame(param);
+
+    *data = 0; /* Set to zero, send_at_cmd() only writes the necessary bytes, so if only 1 is written all the remaining 3 should be 0. */
+    AtCmdFrame::AtCmdResp atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee::set_param(const char * const param, uint32_t data)
+{
+    AtCmdFrame cmd_frame = AtCmdFrame(param, data);
+    return send_at_cmd(&cmd_frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::set_param(const char * const param, const uint8_t * data, uint16_t len)
+{
+    AtCmdFrame cmd_frame = AtCmdFrame(param, data, len);
+    return send_at_cmd(&cmd_frame, NULL, NULL);
+}
+
+AtCmdFrame::AtCmdResp XBee::get_param(const char * const param, uint8_t * const data, uint16_t * const len)
+{
+    AtCmdFrame cmd_frame = AtCmdFrame(param);
+    return send_at_cmd(&cmd_frame, data, len, RadioLocal, false);
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/RadioConfig.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/RadioConfig.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,366 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "Frames/ApiFrame.h"
+
+using namespace XBeeLib;
+
+RadioStatus XBee::write_config(void)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("WR");
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee::set_power_level(uint8_t  level)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    if (level > 4) {
+        return Failure;
+    }
+
+    cmdresp = set_param("PL", level);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee::get_power_level(uint8_t * const  level)
+{
+    if (level == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("PL", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *level = var32;
+    return Success;
+}
+
+RadioStatus XBee::software_reset(void)
+{
+    volatile uint16_t * const rst_cnt_p = &_wd_reset_cnt;
+    const uint16_t init_rst_cnt = *rst_cnt_p;
+
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("FR");
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "software_reset failed!\r\n");
+        return Failure;
+    }
+
+    return wait_for_module_to_reset(rst_cnt_p, init_rst_cnt);
+}
+
+RadioStatus XBee::set_node_identifier(const char * const node_id)
+{
+    if (node_id == NULL) {
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+    const size_t str_len = strlen(node_id);
+
+    if(str_len > 20 || str_len < 1) {
+        return Failure;
+    }
+
+    cmdresp = set_param("NI", (const uint8_t *)node_id, str_len);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee::get_node_identifier(char * const node_id)
+{
+    if (node_id == NULL) {
+        return Failure;
+    }
+
+    uint16_t max_ni_length = 20;
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = get_param("NI", (uint8_t *)node_id, &max_ni_length);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    node_id[max_ni_length] = '\0';
+    return Success;
+}
+
+RadioStatus XBee::enable_network_encryption(bool enable)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("EE", enable);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+RadioStatus XBee::set_network_encryption_key(const uint8_t * const key, const uint16_t length)
+{
+    if (key == NULL || length == 0 || length > 16) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("KY", key, length);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+uint16_t XBee::get_hw_version() const
+{
+    return _hw_version;
+}
+
+uint16_t XBee::get_fw_version() const
+{
+    return _fw_version;
+}
+
+void XBee::set_tx_options(uint8_t options)
+{
+    _tx_options = options;
+}
+
+uint8_t XBee::get_tx_options() const
+{
+    return _tx_options;
+}
+
+RadioStatus XBee::start_node_discovery()
+{
+    RadioStatus status;
+    uint16_t nd_timeout;
+
+    status = get_node_discovery_timeout(&nd_timeout);
+    if (status != Success) {
+	    return status;
+    }
+
+    _nd_timeout = nd_timeout;
+
+    _nd_timer.start();
+
+    AtCmdFrame cmd_frame = AtCmdFrame("ND");
+    send_api_frame(&cmd_frame);
+
+    return Success;
+}
+
+bool XBee::is_node_discovery_in_progress()
+{
+    const int nd_timer = _nd_timer.read_ms();
+
+    if (nd_timer == 0)
+        return false;
+
+    if (nd_timer > _nd_timeout) {
+        _nd_timer.stop();
+        _nd_timer.reset();
+    }
+
+    return true;
+}
+
+void XBee::_get_remote_node_by_id(const char * const node_id, uint64_t * const addr64, uint16_t * const addr16)
+{
+    *addr64 = ADDR64_UNASSIGNED;
+    *addr16 = ADDR16_UNKNOWN;
+    if (node_id == NULL) {
+        return;
+    }
+    const size_t node_id_len = strlen(node_id);
+    if (node_id_len == 0 || node_id_len > MAX_NI_PARAM_LEN) {
+        return;
+    }
+
+    const uint16_t old_timeout = _timeout_ms;
+
+    RadioStatus status;
+    uint16_t nd_timeout;
+	bool wait_for_complete_timeout;
+
+    status = get_node_discovery_timeout(&nd_timeout, &wait_for_complete_timeout);
+    if (status != Success) {
+	    return;
+    }
+	_timeout_ms = nd_timeout;
+
+    Timer nd_timer = Timer();
+
+    nd_timer.start();
+
+    AtCmdFrame atnd_frame = AtCmdFrame("ND", (const uint8_t *)node_id, strlen(node_id));
+    const uint8_t frame_id = atnd_frame.get_frame_id();
+    _node_by_ni_frame_id = frame_id;
+    send_api_frame(&atnd_frame);
+
+    ApiFrame * const resp_frame = get_this_api_frame(frame_id, ApiFrame::AtCmdResp);
+    _timeout_ms = old_timeout;
+
+    _node_by_ni_frame_id = 0;
+
+    if (resp_frame == NULL) {
+        digi_log(LogLevelWarning, "_get_remote_node_by_id: timeout when waiting for ATND response");
+        return;
+    }
+
+    if (resp_frame->get_data_len() < sizeof (uint16_t) + sizeof (uint64_t)) {
+        /* In 802.15.4 this might be the OK or Timeout message with no information */
+        digi_log(LogLevelInfo, "_get_remote_node_by_id: node not found\r\n", __FUNCTION__, node_id);
+        _framebuf_syncr.free_frame(resp_frame);
+        return;
+    }
+
+    const AtCmdFrame::AtCmdResp resp = (AtCmdFrame::AtCmdResp)resp_frame->get_data_at(ATCMD_RESP_STATUS_OFFSET);
+    if (resp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelWarning, "_get_remote_node_by_id: send_at_cmd bad response: 0x%x\r\n", resp);
+        _framebuf_syncr.free_frame(resp_frame);
+        return;
+    }
+
+    rmemcpy((uint8_t *)addr16, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET, sizeof *addr16);
+    rmemcpy((uint8_t *)addr64, resp_frame->get_data() + ATCMD_RESP_DATA_OFFSET + sizeof *addr16, sizeof *addr64);
+    _framebuf_syncr.free_frame(resp_frame);
+
+    if (wait_for_complete_timeout) {
+        while (nd_timer.read_ms() < nd_timeout) {
+            wait_ms(10);
+        }
+    }
+
+    return;
+}
+
+RadioStatus XBee::config_node_discovery(uint16_t backoff_ms, uint8_t options)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("NT", (uint8_t)(backoff_ms / 100));
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    cmdresp = set_param("NO", (uint8_t)options);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    cmdresp = set_param("AC");
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee::get_config_node_discovery(uint16_t * const backoff_ms, uint8_t * const options)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("NT", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *backoff_ms = var32;
+
+    cmdresp = get_param("NO", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *options = var32;
+    return Success;
+}
+
+RadioStatus XBee::_get_iosample(const RemoteXBee& remote, uint8_t * const io_sample, uint16_t * const len)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    /* Force a sample read */
+    cmdresp = get_param(remote, "IS", io_sample, len);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "_get_iosample error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee::config_io_sample_destination(const RemoteXBee& remote, const RemoteXBee& destination)
+{
+    uint32_t dh;
+    uint32_t dl;
+
+    if (destination.is_valid_addr64b()) {
+        const uint64_t dest64 = destination.get_addr64();
+        dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF);
+        dl = (uint32_t)((dest64 & 0xFFFFFFFF));
+    } else if (destination.is_valid_addr16b()) {
+        const uint16_t destAddr16 = destination.get_addr16();
+        dh = 0;
+        dl = destAddr16;
+    } else {
+        digi_log(LogLevelError, "send_io_sample_to: Invalid destination");
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param(remote, "DH", dh);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "send_io_sample_to error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    cmdresp = set_param(remote, "DL", dl);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "send_io_sample_to error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee::set_io_sample_rate(const RemoteXBee& remote, const float seconds)
+{
+    const float max_seconds = 65.535;
+
+    if (seconds > max_seconds) {
+        digi_log(LogLevelError, "XBee::set_io_sample_rate error seconds rate exceeds maximum %d:\r\n", max_seconds);
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+    const uint16_t milliseconds = seconds * 1000;
+
+    cmdresp = set_param(remote, "IR", milliseconds);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "XBee::set_io_sample_rate error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/XBee.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/XBee.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,880 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeLib.h"
+#include "FrameHandlers/FH_ModemStatus.h"
+
+/* States for the state machine that processes incoming data on the serial port */
+#define WAITING_FOR_START_FRAME (0)
+#define WAITING_FOR_LENGTH_MSB  (1)
+#define WAITING_FOR_LENGTH_LSB  (2)
+#define WAITING_FOR_PAYLOAD     (3)
+#define WAITING_FOR_CHECKSUM    (4)
+
+#define IS_API2()               (_mode == ModeAPI2)
+#define IS_API_MODE()           (_mode == ModeAPI1 || _mode == ModeAPI2)
+
+using namespace XBeeLib;
+
+#if defined(FRAME_BUFFER_SIZE_SYNCR)
+#if FRAME_BUFFER_SIZE_SYNCR < 2
+#error "FRAME_BUFFER_SIZE_SYNCR must be at least 2"
+#endif
+#else
+#define FRAME_BUFFER_SIZE_SYNCR     1
+#endif
+
+#define MAX_FRAME_PAYLOAD_LEN_SYNCR (1  /* type */         + 1  /* id */       + 2 /* at cmd*/    + 1 /* status */    + 2 /* MY sender */ + \
+                                     8  /* 64b sender */   + 20 /* max id */   + 1 /* null ter */ + 2 /* MY parent */ + 1  /* dev type */ + \
+                                     1  /* source event */ + 2  /* prof. id */ + 2 /* man. id */)
+
+FrameBuffer XBee::_framebuf_app(FRAME_BUFFER_SIZE, MAX_FRAME_PAYLOAD_LEN);
+FrameBuffer XBee::_framebuf_syncr(FRAME_BUFFER_SIZE_SYNCR, MAX_FRAME_PAYLOAD_LEN_SYNCR);
+
+#if defined(DEVICE_SERIAL_FC)
+bool XBee::check_radio_flow_control()
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t value;
+
+    if (_serial_flow_type == SerialBase::RTSCTS || _serial_flow_type == SerialBase::CTS) {
+        cmdresp = get_param("D7", &value);
+        if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+            digi_log(LogLevelError, "Could not read CTS configuration. Error %d\r\n", cmdresp);
+            return false;
+        } else if (value != 1) {
+            digi_log(LogLevelError, "Bad CTS configuration. Radio 'D7' param is %d and should be 1\r\n", value);
+            return false;
+        }
+    }
+
+    if (_serial_flow_type == SerialBase::RTSCTS || _serial_flow_type == SerialBase::RTS) {
+        cmdresp = get_param("D6", &value);
+        if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+            digi_log(LogLevelError, "Could not read RTS configuration. Error %d\r\n", cmdresp);
+            return false;
+        } else if (value != 1) {
+            digi_log(LogLevelError, "Bad RTS configuration. Radio 'D6' param is %d and should be 1\r\n", value);
+            return false;
+        }
+    }
+
+    return true;
+}
+#endif
+
+/* Class constructor */
+XBee::XBee(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+    _mode(ModeUnknown), _hw_version(0), _fw_version(0), _timeout_ms(SYNC_OPS_TIMEOUT_MS), _dev_addr64(ADDR64_UNASSIGNED),
+    _reset(NULL), _tx_options(0), _hw_reset_cnt(0), _wd_reset_cnt(0), _modem_status_handler(NULL), _modem_status(AtCmdFrame::HwReset), _initializing(true), _node_by_ni_frame_id(0)
+{
+
+    if (reset != NC) {
+        _reset = new DigitalOut(reset, 1);
+    }
+
+    _uart = new RawSerial(tx, rx);
+    _uart->baud(baud);
+
+    _serial_flow_type = SerialBase::Disabled;
+#if defined(DEVICE_SERIAL_FC)
+    if (rts != NC && cts != NC) {
+        _serial_flow_type = SerialBase::RTSCTS;
+        _uart->set_flow_control(_serial_flow_type, rts, cts);
+    } else if (rts != NC && cts == NC) {
+        _serial_flow_type = SerialBase::RTS;
+        _uart->set_flow_control(_serial_flow_type, rts);
+    } else if (rts == NC && cts != NC) {
+        _serial_flow_type = SerialBase::CTS;
+        _uart->set_flow_control(_serial_flow_type, cts);
+    }
+#endif
+    /* Enable the reception of bytes on the serial interface by providing a cb */
+    _uart->attach(this, &XBee::uart_read_cb, Serial::RxIrq);
+
+    for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+        _fhandlers[i] = NULL;
+    }
+}
+
+/* Class destructor */
+XBee::~XBee()
+{
+    unregister_modem_status_cb();
+
+    if (_uart != NULL) {
+        delete _uart;
+    }
+    if (_reset != NULL) {
+        delete _reset;
+    }
+}
+
+#include <inttypes.h>
+
+RadioStatus XBee::init(void)
+{
+    AtCmdFrame::AtCmdResp cmd_resp;
+    uint32_t var32;
+
+    _initializing = true;
+
+    const unsigned int max_reset_retries = 3;
+    RadioStatus reset_status;
+    for (unsigned int i = 0; i < max_reset_retries; i++) {
+        reset_status = device_reset();
+        if (reset_status == Success) {
+            break;
+        }
+    }
+    if (reset_status != Success) {
+        return reset_status;
+    }
+
+    /* Check if radio is in API1 or API2 _mode */
+    cmd_resp = get_param("AP", &var32);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    _mode = (RadioMode)var32;
+
+    /* Read the device unique 64b address */
+    uint32_t serialn_high, serialn_low;
+    cmd_resp = get_param("SH", &serialn_high);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    cmd_resp = get_param("SL", &serialn_low);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    _dev_addr64 = ((uint64_t)serialn_high << 32) | serialn_low;
+
+    /* Read some important parameters */
+    cmd_resp = get_param("HV", &var32);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    _hw_version = var32;
+
+    cmd_resp = get_param("VR", &var32);
+    if (cmd_resp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    _fw_version = var32;
+
+    digi_log(LogLevelInfo, "mode:   %02x\r\n", (uint8_t)_mode);
+    digi_log(LogLevelInfo, "HV:     %04x\r\n", _hw_version);
+    digi_log(LogLevelInfo, "VR:     %04x\r\n", _fw_version);
+    digi_log(LogLevelInfo, "ADDR64: %08x:%08x\r\n", UINT64_HI32(_dev_addr64), UINT64_LO32(_dev_addr64));
+
+#if defined(DEVICE_SERIAL_FC)
+    bool valid_radio_fc = check_radio_flow_control();
+    assert(valid_radio_fc == true);
+#endif
+
+    _initializing = false;
+    if (_modem_status_handler != NULL) {
+        const ApiFrame frame = ApiFrame(ApiFrame::AtModemStatus, (uint8_t *)&_modem_status, sizeof(_modem_status));
+        _modem_status_handler->process_frame_data(&frame);
+    }
+
+    return Success;
+}
+
+uint64_t XBee::get_addr64() const
+{
+    return _dev_addr64;
+}
+
+RadioStatus XBee::hardware_reset()
+{
+    if (_reset != NULL) {
+        volatile uint16_t * const rst_cnt_p = &_hw_reset_cnt;
+        const uint16_t init_rst_cnt = *rst_cnt_p;
+        *_reset = 0;
+        wait_ms(10);
+        *_reset = 1;
+        return wait_for_module_to_reset(rst_cnt_p, init_rst_cnt);
+    }
+
+    return Failure;
+}
+
+RadioStatus XBee::device_reset()
+{
+    if (hardware_reset() == Success) {
+        return Success;
+    }
+
+    return software_reset();
+}
+
+RadioStatus XBee::wait_for_module_to_reset(volatile uint16_t *rst_cnt_p, uint16_t init_rst_cnt)
+{
+    Timer timer = Timer();
+    timer.start();
+
+    while (*rst_cnt_p == init_rst_cnt && timer.read_ms() < RESET_TIMEOUT_MS) {
+        wait_ms(100);
+    }
+
+    if (*rst_cnt_p == init_rst_cnt) {
+        digi_log(LogLevelWarning, "Reset Timeout\r\n");
+        return Failure;
+    }
+    return Success;
+}
+
+/** Callback function called when data is received on the serial port */
+void XBee::uart_read_cb(void)
+{
+    static uint8_t rxstate = WAITING_FOR_START_FRAME;
+    static uint16_t framelen = 0;
+    static uint16_t bytes_read;
+    static uint8_t chksum;
+    static ApiFrame *frame = NULL;
+    static bool last_byte_escaped = false;
+    static FrameBuffer * framebuf = NULL;
+
+    while (_uart->readable()) {
+        uint8_t data = _uart->getc();
+
+        if (IS_API2() && rxstate != WAITING_FOR_START_FRAME) {
+            if (last_byte_escaped) {
+                data = data ^ DR_ESCAPE_XOR_BYTE;
+                last_byte_escaped = false;
+            } else if (data == DR_ESCAPE_BYTE) {
+                last_byte_escaped = true;
+                continue;
+            }
+        }
+
+        switch (rxstate) {
+            case WAITING_FOR_START_FRAME:
+                if (data == DR_START_OF_FRAME) {
+                    rxstate = WAITING_FOR_LENGTH_MSB;
+                }
+                break;
+
+            case WAITING_FOR_LENGTH_MSB:
+                framelen = data << 8;
+                rxstate = WAITING_FOR_LENGTH_LSB;
+                break;
+
+            case WAITING_FOR_LENGTH_LSB:
+                framelen |= data;
+                rxstate = WAITING_FOR_PAYLOAD;
+                bytes_read = 0;
+                chksum = 0;
+                /* Sanity check that the frame is smaller than... */
+                if (framelen > MAX_FRAME_PAYLOAD_LEN) {
+                    digi_log(LogLevelDebug, "framelen=%d too long\r\n", framelen);
+                    digi_log(LogLevelWarning, "Frame dropped, frame too long. Increase MAX_FRAME_PAYLOAD_LEN define\r\n");
+                    rxstate = WAITING_FOR_START_FRAME;
+                }
+                break;
+
+            case WAITING_FOR_PAYLOAD:
+                #define CACHED_SIZE 3
+                static uint8_t frame_cached[CACHED_SIZE];
+
+                if (framelen <= CACHED_SIZE) {
+                    if (!bytes_read) {
+                        const ApiFrame::ApiFrameType frame_type = (ApiFrame::ApiFrameType)data;
+                        switch (frame_type)
+                        {
+                            case ApiFrame::AtCmdResp:
+                            case ApiFrame::RemoteCmdResp:
+                            case ApiFrame::TxStatusZBDM:
+                            case ApiFrame::TxStatus:
+                                framebuf = &_framebuf_syncr;
+                                break;
+
+                            case ApiFrame::RxPacket64Bit:
+                            case ApiFrame::RxPacket16Bit:
+                            case ApiFrame::Io64Bit:
+                            case ApiFrame::Io16Bit:
+                            case ApiFrame::AtModemStatus:
+                            case ApiFrame::RxPacketAO0:
+                            case ApiFrame::IoSampleRxZBDM:
+                                framebuf = &_framebuf_app;
+                                break;
+
+                            case ApiFrame::RxPacketAO1:
+                            case ApiFrame::SensorRxIndAO0:
+                            case ApiFrame::NodeIdentIndAO0:
+                            case ApiFrame::OtaFwUpStatus:
+                            case ApiFrame::RouteRecInd:
+                            case ApiFrame::Many2OneRRInd:
+                            case ApiFrame::TxReq64Bit:
+                            case ApiFrame::TxReq16Bit:
+                            case ApiFrame::AtCmd:
+                            case ApiFrame::AtCmdQueuePV:
+                            case ApiFrame::TxReqZBDM:
+                            case ApiFrame::ExpAddrCmd:
+                            case ApiFrame::RemoteCmdReq:
+                            case ApiFrame::CreateSrcRoute:
+                            case ApiFrame::Invalid:
+                            case ApiFrame::RouteInfo:
+                            case ApiFrame::AggregateAddr:
+                                framebuf = NULL;
+                                break;
+                        }
+
+                        if (framebuf == NULL) {
+                            digi_log(LogLevelWarning, "Discarding not supported frame type %02x\r\n", frame_type);
+                            rxstate = WAITING_FOR_START_FRAME;
+                        } else {
+                            frame = framebuf->get_next_free_frame();
+                            if (frame == NULL) {
+                                /* It's not possible to achive this condition as we discard older frames and only one frame can be used by syncr. commands */
+                                assert(frame != NULL);
+                                rxstate = WAITING_FOR_START_FRAME;
+                            } else {
+                                frame->set_data_len(framelen - 1);
+                            }
+
+                            frame->set_frame_type(frame_type);
+                        }
+                    } else {
+                        frame->set_data(data, bytes_read - 1);
+                    }
+                    chksum += data;
+                    bytes_read++;
+                    if (bytes_read == framelen) {
+                        rxstate = WAITING_FOR_CHECKSUM;
+                    }
+                    break;
+                }
+
+
+                if (bytes_read < CACHED_SIZE) {
+                    frame_cached[bytes_read] = data;
+                }
+                else if (bytes_read == CACHED_SIZE) {
+                    const ApiFrame::ApiFrameType frame_type = (ApiFrame::ApiFrameType)frame_cached[0];
+                    switch (frame_type)
+                    {
+                        case ApiFrame::RemoteCmdResp:
+                        case ApiFrame::TxStatusZBDM:
+                        case ApiFrame::TxStatus:
+                            framebuf = &_framebuf_syncr;
+                            break;
+
+                        case ApiFrame::AtCmdResp:
+                            if ((frame_cached[1] != _node_by_ni_frame_id ) && (frame_cached[2] == 'N') && (data == 'D'))
+                            {
+                                framebuf = &_framebuf_app;
+                            } else {
+                                framebuf = &_framebuf_syncr;
+                            }
+                            break;
+
+                        case ApiFrame::RxPacket64Bit:
+                        case ApiFrame::RxPacket16Bit:
+                        case ApiFrame::Io64Bit:
+                        case ApiFrame::Io16Bit:
+                        case ApiFrame::AtModemStatus:
+                        case ApiFrame::RxPacketAO0:
+                        case ApiFrame::IoSampleRxZBDM:
+                            framebuf = &_framebuf_app;
+                            break;
+
+                        case ApiFrame::RxPacketAO1:
+                        case ApiFrame::SensorRxIndAO0:
+                        case ApiFrame::NodeIdentIndAO0:
+                        case ApiFrame::OtaFwUpStatus:
+                        case ApiFrame::RouteRecInd:
+                        case ApiFrame::Many2OneRRInd:
+                        case ApiFrame::TxReq64Bit:
+                        case ApiFrame::TxReq16Bit:
+                        case ApiFrame::AtCmd:
+                        case ApiFrame::AtCmdQueuePV:
+                        case ApiFrame::TxReqZBDM:
+                        case ApiFrame::ExpAddrCmd:
+                        case ApiFrame::RemoteCmdReq:
+                        case ApiFrame::CreateSrcRoute:
+                        case ApiFrame::Invalid:
+                        case ApiFrame::RouteInfo:
+                        case ApiFrame::AggregateAddr:
+                            framebuf = NULL;
+                            break;
+                    }
+
+                    if (framebuf == NULL) {
+                        digi_log(LogLevelWarning, "Discarding not supported frame type %02x\r\n", frame_type);
+                        rxstate = WAITING_FOR_START_FRAME;
+                    } else {
+                        frame = framebuf->get_next_free_frame();
+                        if (frame == NULL) {
+                            /* It's not possible to achive this condition as we discard older frames and only one frame can be used by syncr. commands */
+                            assert(frame != NULL);
+                            rxstate = WAITING_FOR_START_FRAME;
+                        } else {
+                            frame->set_data_len(framelen - 1);
+                        }
+
+                        frame->set_frame_type(frame_type);
+                        frame->set_data(frame_cached[1], 0);
+                        frame->set_data(frame_cached[2], 1);
+                        frame->set_data(data, 2);
+                    }
+                } else {
+                    frame->set_data(data, bytes_read - 1);
+                }
+                chksum += data;
+                bytes_read++;
+                if (bytes_read == framelen) {
+                    rxstate = WAITING_FOR_CHECKSUM;
+                }
+                break;
+
+            case WAITING_FOR_CHECKSUM:
+                chksum += data;
+                if (chksum == 0xFF) {
+                    /* We got a valid frame!! */
+                    frame->dump();
+
+                    /* If its a _modem status frame, process it to update the status info of the library.
+                     * The frame is also queued to allow processing it other handlers registered.
+                     * Note that radio_status_update() has to be fast to minimize the impact of processing
+                     * the funcion here */
+                    if (frame->get_frame_type() == ApiFrame::AtModemStatus) {
+                        radio_status_update((AtCmdFrame::ModemStatus)frame->get_data_at(0));
+                        if (_initializing) {
+                            framebuf->free_frame(frame);
+                        } else {
+                            framebuf->complete_frame(frame);
+                        }
+                    } else {
+                        framebuf->complete_frame(frame);
+                        /* Note, the frame will be released elsewhere, once it has been processed */
+                    }
+                } else {
+                    framebuf->free_frame(frame);
+                    digi_log(LogLevelWarning, "Checksum error, got %02x, %02x\r\n", data, chksum);
+                }
+                /* Intentional fall-through */
+            default:
+                rxstate = WAITING_FOR_START_FRAME;
+                break;
+        }
+    }
+    /* TODO, signal the thread processing incoming frames */
+}
+
+/* This is a pure virtual function, but exists here because its called from this class to
+ * to update the status of the object, and can be called before the construction of the
+ * object has been completed and the virtual functions filled */
+void XBee::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+    UNUSED_PARAMETER(modem_status);
+}
+
+void XBee::set_timeout(uint16_t timeout_ms)
+{
+    this->_timeout_ms = timeout_ms;
+}
+
+uint16_t XBee::get_timeout(void) const
+{
+    return _timeout_ms;
+}
+
+ApiFrame * XBee::get_this_api_frame(uint8_t id, ApiFrame::ApiFrameType type,
+                                          ApiFrame::ApiFrameType type2)
+{
+    Timer timer = Timer();
+    timer.start();
+
+    while (timer.read_ms() < _timeout_ms) {
+        ApiFrame * frame = _framebuf_syncr.get_next_complete_frame();
+        if (frame == NULL) {
+            wait_ms(10);
+            continue;
+        }
+
+        if ((frame->get_frame_type() != type) &&
+            (frame->get_frame_type() != type2)) {
+            _framebuf_syncr.complete_frame(frame);
+            wait_ms(1);
+            continue;
+        }
+
+        if (frame->get_data_at(ATCMD_RESP_FRAME_ID_OFFSET) != id) {
+            _framebuf_syncr.complete_frame(frame);
+            wait_ms(1);
+            continue;
+        }
+
+        /* frame found */
+        return frame;
+    }
+
+    digi_log(LogLevelWarning, "Frame type: %02x, id: %02x, timeout\r\n", (uint8_t)type, id);
+
+    return NULL;
+}
+
+void XBee::send_byte_escaping_if(uint8_t data)
+{
+    if (IS_API2()) {
+        switch (data) {
+            case DR_START_OF_FRAME:
+            case DR_ESCAPE_BYTE:
+            case DR_XON_BYTE:
+            case DR_XOFF_BYTE:
+                _uart->putc(DR_ESCAPE_BYTE);
+                _uart->putc(data ^ DR_ESCAPE_XOR_BYTE);
+                break;
+            default:
+                _uart->putc(data);
+        }
+    } else {
+        _uart->putc(data);
+    }
+}
+
+void XBee::send_api_frame(ApiFrame *frame)
+{
+    uint8_t chksum;
+    const uint8_t *data;
+    uint16_t bytes_sent = 0, frame_len;
+
+    frame->dump();
+
+    frame_len = 1 + frame->get_data_len(); /* frame type + frame payload */
+    data = frame->get_data();
+
+    /* Send the start of frame delimiter */
+    _uart->putc(DR_START_OF_FRAME);
+
+    /* Now the length */
+    send_byte_escaping_if((uint8_t)(frame_len >> 8));
+    send_byte_escaping_if((uint8_t)frame_len);
+
+    /* Send the Frame type and then the payload */
+    chksum = (uint8_t)frame->get_frame_type();
+    send_byte_escaping_if(chksum);
+    bytes_sent++;
+
+    /* And now, send the packet payload */
+    while (bytes_sent++ < frame_len) {
+        chksum += *data;
+        send_byte_escaping_if(*data++);
+    }
+
+    /* And finally send the checksum */
+    send_byte_escaping_if(~chksum);
+}
+
+RadioStatus XBee::register_frame_handler(FrameHandler *const handler)
+{
+    if (handler != NULL) {
+        for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+            if (_fhandlers[i] != NULL) {
+                continue;
+            }
+            _fhandlers[i] = handler;
+            return Success;
+        }
+    }
+
+    digi_log(LogLevelError, "No more Frame Handlers available. Increase MAX_FRAME_HANDLERS define\r\n");
+
+    return Failure;
+}
+
+RadioStatus XBee::unregister_frame_handler(FrameHandler *const handler)
+{
+    int i;
+
+    if (handler != NULL) {
+        for (i = 0; i < MAX_FRAME_HANDLERS; i++) {
+            if (_fhandlers[i] == handler) {
+                break;
+            }
+        }
+
+        if (i == MAX_FRAME_HANDLERS) {
+            return Failure;
+        }
+
+        do {
+            if (i == MAX_FRAME_HANDLERS - 1) {
+                _fhandlers[i] = NULL;
+            } else {
+                _fhandlers[i] = _fhandlers[i + 1];
+            }
+        } while (++i < MAX_FRAME_HANDLERS);
+    }
+
+    return Success;
+}
+
+XBee::RadioProtocol XBee::get_radio_protocol(void) const
+{
+    enum HardwareVersion {
+#ifdef EXTRA_XBEE_PROTOCOLS
+        X09_009 = 0x01,
+        X09_019 = 0x02,
+        XH9_009 = 0x03,
+        XH9_019 = 0x04,
+        X24_009 = 0x05,
+        X24_019 = 0x06,
+        X09_001 = 0x07,
+        XH9_001 = 0x08,
+        X08_004 = 0x09,
+        XC09_009 = 0x0A,
+        XC09_038 = 0x0B,
+        X24_038 = 0x0C,
+        X09_009_TX = 0x0D,
+        X09_019_TX = 0x0E,
+        XH9_009_TX = 0x0F,
+        XH9_019_TX = 0x10,
+        X09_001_TX = 0x11,
+        XH9_001_TX = 0x12,
+        XT09B_XXX = 0x13,
+        XT09_XXX = 0x14,
+        XC08_009 = 0x15,
+        XC08_038 = 0x16,
+#endif
+        XB24_AXX_XX = 0x17,
+        XBP24_AXX_XX = 0x18,
+        XB24_BXIX_XXX = 0x19,
+        XBP24_BXIX_XXX = 0x1A,
+#ifdef EXTRA_XBEE_PROTOCOLS
+        XBP09_DXIX_XXX = 0x1B,
+        XBP09_XCXX_XXX = 0x1C,
+        XBP08_DXXX_XXX = 0x1D,
+#endif
+        XBP24B = 0x1E,
+#ifdef EXTRA_XBEE_PROTOCOLS
+        XB24_WF = 0x1F,
+        AMBER_MBUS = 0x20,
+#endif
+        XBP24C = 0x21,
+        XB24C = 0x22,
+#ifdef EXTRA_XBEE_PROTOCOLS
+        XSC_GEN3 = 0x23,
+        SRD_868_GEN3 = 0x24,
+        ABANDONATED = 0x25,
+        SMT_900LP = 0x26,
+        WIFI_ATHEROS = 0x27,
+        SMT_WIFI_ATHEROS = 0x28,
+        SMT_475LP = 0x29,
+        XBEE_CELL_TH = 0x2A,
+        XLR_MODULE = 0x2B,
+        XB900HP_NZ = 0x2C,
+        XBP24C_TH_DIP = 0x2D,
+        XB24C_TH_DIP = 0x2E,
+        XLR_BASEBOARD = 0x2F,
+        XBP24C_S2C_SMT = 0x30
+#endif
+    };
+    const bool fw_4_bytes_len = _fw_version > 0x0FFF && _fw_version < 0xFFFF;
+    const uint8_t fw_nibble_3 = (_fw_version >> (4 * 3)) & 0x000F;
+    const uint8_t fw_nibble_1 = (_fw_version >> (4 * 1)) & 0x000F;
+    const uint8_t fw_nibble_0 = (_fw_version >> (4 * 0)) & 0x000F;
+    const uint8_t hw_version_msb = _hw_version >> 8;
+
+    if (hw_version_msb == XB24_AXX_XX || hw_version_msb == XBP24_AXX_XX) {
+#ifdef EXTRA_XBEE_PROTOCOLS
+        if (fw_4_bytes_len && fw_nibble_3 == 8) {
+            return DigiMesh;
+        }
+        return Raw_802_15_4;
+#else
+        if (!(fw_4_bytes_len && fw_nibble_3 == 8)) {
+            return Raw_802_15_4;
+        }
+#endif
+    } else if (hw_version_msb == XB24_BXIX_XXX || hw_version_msb == XBP24_BXIX_XXX) {
+        if (fw_4_bytes_len && ((fw_nibble_3 == 1 && fw_nibble_1 == 2 && fw_nibble_0 == 0) || fw_nibble_3 == 2)) {
+            return ZigBee;
+        }
+#ifdef EXTRA_XBEE_PROTOCOLS
+        if (fw_4_bytes_len && fw_nibble_3 == 3) {
+            return SmartEnergy;
+        }
+        return ZNet;
+    } else if (hw_version_msb == XBP09_DXIX_XXX) {
+        if (fw_4_bytes_len && (fw_nibble_3 == 8 || fw_nibble_1 == 8))  {
+            return DigiMesh;
+        }
+        return DigiPoint;
+    } else if (hw_version_msb == XBP08_DXXX_XXX) {
+        return DigiPoint;
+#endif
+    } else if (hw_version_msb == XBP24B) {
+#ifdef EXTRA_XBEE_PROTOCOLS
+        if (fw_4_bytes_len && fw_nibble_3 == 3) {
+            return SmartEnergy;
+        }
+        return ZigBee;
+#else
+        if (!(fw_4_bytes_len && fw_nibble_3 == 3)) {
+            return ZigBee;
+        }
+#endif
+#ifdef EXTRA_XBEE_PROTOCOLS
+    } else if (hw_version_msb == XB24_WF || hw_version_msb == WIFI_ATHEROS || hw_version_msb == SMT_WIFI_ATHEROS) {
+        return XBeeWiFi;
+#endif
+    } else if (hw_version_msb == XBP24C || hw_version_msb == XB24C) {
+        if (fw_4_bytes_len && fw_nibble_3 == 2) {
+            return Raw_802_15_4;
+        }
+#ifdef EXTRA_XBEE_PROTOCOLS
+        if (fw_4_bytes_len && fw_nibble_3 == 5) {
+            return SmartEnergy;
+        }
+        return ZigBee;
+#else
+        if (!(fw_4_bytes_len && fw_nibble_3 == 5)) {
+            return ZigBee;
+        }
+#endif
+#ifdef EXTRA_XBEE_PROTOCOLS
+    } else if (hw_version_msb == XSC_GEN3 || hw_version_msb == SRD_868_GEN3) {
+        if (fw_4_bytes_len && fw_nibble_3 == 8) {
+            return DigiMesh;
+        } else if (fw_4_bytes_len && fw_nibble_3 == 1) {
+            return DigiPoint;
+        }
+        return None;
+    } else if (hw_version_msb == XBEE_CELL_TH) {
+        return None;
+    } else if (hw_version_msb == XLR_MODULE) {
+        return None;
+    } else if (hw_version_msb == XLR_BASEBOARD) {
+        return None;
+    } else if (hw_version_msb == XB900HP_NZ) {
+        return DigiPoint;
+    } else if (hw_version_msb == XBP24C_TH_DIP || hw_version_msb == XB24C_TH_DIP || hw_version_msb == XBP24C_S2C_SMT) {
+        if (fw_4_bytes_len && fw_nibble_3 == 9) {
+            return DigiMesh;
+        }
+        if (fw_4_bytes_len && fw_nibble_3 == 5) {
+            return SmartEnergy;
+        }
+        if (fw_4_bytes_len && fw_nibble_3 == 2) {
+            return Raw_802_15_4;
+        }
+        return ZigBee;
+    }
+#else
+    }
+#endif
+
+    return None;
+}
+
+#define TX_STATUS_OFFSET_ZB     4
+#define TX_STATUS_OFFSET_802    1
+
+TxStatus XBee::send_data(ApiFrame *frame)
+{
+    TxStatus resp = TxStatusTimeout;
+    ApiFrame *resp_frame;
+
+    send_api_frame(frame);
+
+    /* Wait for the transmit status response packet */
+    resp_frame = get_this_api_frame(frame->get_frame_id(),
+                    ApiFrame::TxStatusZBDM, ApiFrame::TxStatus);
+    if (resp_frame == NULL) {
+        return resp;
+    }
+
+    uint8_t index = resp_frame->get_frame_type() == ApiFrame::TxStatusZBDM ?
+            TX_STATUS_OFFSET_ZB : TX_STATUS_OFFSET_802;
+
+    resp = (TxStatus)resp_frame->get_data_at(index);
+
+    /* Once processed, remove the frame from the buffer */
+    _framebuf_syncr.free_frame(resp_frame);
+
+    return resp;
+}
+
+TxStatus XBee::send_data_broadcast(const uint8_t *const data, uint16_t len, bool syncr)
+{
+    const RemoteXBee remoteDevice = RemoteXBee(ADDR64_BROADCAST);
+    return send_data(remoteDevice, data, len, syncr);
+}
+
+uint32_t XBee::process_rx_frames()
+{
+    ApiFrame *frame = NULL;
+
+    while ((frame = _framebuf_app.get_next_complete_frame()) != NULL) {
+        for (int i = 0; i < MAX_FRAME_HANDLERS; i++) {
+
+            if (_fhandlers[i] == NULL) {
+                /* No more handlers, break here */
+                break;
+            }
+
+            /* Check if frame and handler match, if not... go for the next one */
+            if (frame->get_frame_type() != _fhandlers[i]->get_type()) {
+                continue;
+            }
+
+            _fhandlers[i]->process_frame_data(frame);
+        }
+
+        /* Once processed, remove the frame from the buffer */
+        _framebuf_app.free_frame(frame);
+    }
+
+    const uint32_t dropped_frames = _framebuf_app.get_dropped_frames_count();
+    if (dropped_frames != 0) {
+        digi_log(LogLevelWarning, "process_rx_frames: %d frames dropped!!!\r\n", dropped_frames);
+    }
+
+    return dropped_frames;
+}
+
+void XBee::register_modem_status_cb(modem_status_cb_t function)
+{
+    if (_modem_status_handler == NULL) {
+        _modem_status_handler = new FH_ModemStatus();
+        register_frame_handler(_modem_status_handler);
+    }
+    _modem_status_handler->register_modem_status_cb(function);
+}
+
+void XBee::unregister_modem_status_cb()
+{
+    if (_modem_status_handler != NULL) {
+        _modem_status_handler->unregister_modem_status_cb();
+        unregister_frame_handler(_modem_status_handler);
+        delete _modem_status_handler;
+        _modem_status_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+int XBee::get_AI(void)
+{
+    uint32_t atai;
+    const AtCmdFrame::AtCmdResp status = get_param("AI", &atai);
+
+    if (status != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "get_association_indication() failed with %d\r\n", status);
+        return -1;
+    }
+    return atai;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee/XBee.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee/XBee.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,714 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__DIGI_RADIO_H_)
+#define __DIGI_RADIO_H_
+
+#include <stdint.h>
+#include "config.h"
+#include "Utils/Debug.h"
+#include "Frames/AtCmdFrame.h"
+#include "FrameHandlers/FrameHandler.h"
+#include "FrameHandlers/FH_ModemStatus.h"
+#include "FrameBuffer/FrameBuffer.h"
+#include "Addresses.h"
+#include "RemoteXBee/RemoteXBee.h"
+#include "IO/IO.h"
+
+#define MAX_FRAME_HANDLERS      4
+#define RESET_TIMEOUT_MS        5000
+
+#define DR_API_FRAME_OVERHEAD   4       /* Start of frame + frame len + checksum */
+#define DR_MIN_API_FRAME_LEN    4
+#define DR_START_OF_FRAME       0x7E
+#define DR_ESCAPE_BYTE          0x7D
+#define DR_XON_BYTE             0x11
+#define DR_XOFF_BYTE            0x13
+#define DR_ESCAPE_XOR_BYTE      0x20
+
+/* TODO, verify these flags work in all modules */
+#define DISABLE_RETRIES_AND_ROUTE_REPAIR    0x01
+#define ENABLE_APS_ENCRYPTION               0x20
+#define USE_EXTENDED_TX_TIMEOUT             0x40
+
+namespace XBeeLib {
+
+/**
+ * @defgroup RadioStatus
+ * @{
+ */
+/**
+ * RadioStatus
+ */
+enum RadioStatus {
+    Success         = 0,    /**< Success */
+    Failure         = -1,   /**< Failure */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup TxStatus
+ * @{
+ */
+/**
+ * TxStatus
+ */
+enum TxStatus {
+    TxStatusSuccess            = 0,     /**< Success */
+    TxStatusAckFail            = 1,     /**< MAC ACK Failure */
+    TxStatusCCAFail            = 2,     /**< CCA Failure */
+    TxStatusInvDestEP          = 0x15,  /**< Invalid destination endpoint */
+    TxStatusNwAckFail          = 0x21,  /**< Network ACK Failure */
+    TxStatusNotJoinNw          = 0x22,  /**< Not Joined to Network */
+    TxStatusSelfAddr           = 0x23,  /**< Self-addressed */
+    TxStatusAddrNotFound       = 0x24,  /**< Address Not Found */
+    TxStatusRouteNotFound      = 0x25,  /**< Route Not Found */
+    TxStatusBroadSrcFail2Heard = 0x26,  /**< Broadcast source failed to hear a neighbor relay the message */
+    TxStatusInvBindTableIdx    = 0x2B,  /**< Invalid binding table index */
+    TxStatusResourceError      = 0x2C,  /**< Resource error lack of free buffers, timers, etc. */
+    TxStatusAttBroadcWithAPS   = 0x2D,  /**< Attempted broadcast with APS transmission */
+    TxStatusAttUnicWithAPSEE0  = 0x2E,  /**< Attempted unicast with APS transmission, but EE=0 */
+    TxStatusResourceError2     = 0x31,  /**< TxStatusResourceError2 */
+    TxStatusInternalError      = 0x32,  /**< Resource error lack of free buffers, timers, etc. */
+    TxStatusPayloadTooLarge    = 0x74,  /**< Data payload too large */
+    TxStatusIndirectMsgUnReq   = 0x75,  /**< Indirect message unrequested */
+    TxStatusInvalidAddr        = 0xfe,  /**< Invalid Address (Error generated by the library) */
+    TxStatusTimeout            = 0xff,  /**< Timeout (Error generated by the library) */
+};
+/**
+ * @}
+ */
+
+/**
+ * @defgroup RadioLocation
+ * @{
+ */
+/**
+ * RadioLocation
+ */
+enum RadioLocation {
+    RadioLocal     = 0,     /**< Local Radio */
+    RadioRemote    = 1,     /**< Remote Radio */
+};
+/**
+ * @}
+ */
+
+/** Parent Class for XBee modules, not to be directly used */
+class XBee
+{
+    private:
+    /** wait_for_module_to_reset - waits until a Modem Status packet with a reset status
+     * is received, or the timeout expires.
+     *
+     *  @returns
+     *     Success if a Modem Status was received,
+     *     Failure otherwise
+     */
+    RadioStatus wait_for_module_to_reset(volatile uint16_t *rst_cnt_p, uint16_t init_rst_cnt);
+
+    protected:
+    /** buffer to store the received frames */
+    static FrameBuffer _framebuf_app;
+    static FrameBuffer _framebuf_syncr;
+
+    public:
+
+        /**
+         * RadioMode
+         */
+        enum RadioMode {
+            ModeUnknown     = 0,  /**< Unknown */
+            ModeAPI1        = 1,  /**< API1 */
+            ModeAPI2        = 2,  /**< API2 */
+            ModeTransparent = 3,  /**< Transparent */
+            ModeBootloader  = 4,  /**< Bootloader */
+        };
+
+        /** Class constructor
+         * @param tx the TX pin of the UART that will interface the XBee module
+         * @param rx the RX pin of the UART that will interface the XBee module
+         * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+         * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+         * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+         * */
+        XBee(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+        XBee(const XBee& other); /* Intentionally not implemented */
+        /** Class destructor */
+        virtual ~XBee();
+
+        /** init-  initializes object
+         * This function must be called just after creating the object so it initializes internal data.
+         * @returns
+         *         Success if the module has been properly initialized and is ready to process data.
+         *         Failure otherwise.
+         */
+        RadioStatus init();
+
+        /** get_addr64 - returns the 64bit address of the local device
+         *
+         *  @returns the 64bit address of the local device
+         */
+        uint64_t get_addr64() const;
+
+        /** hardware_reset - performs a hardware reset. The reset GPIO must have
+         * been provided to the constructor
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus hardware_reset();
+
+        /** software_reset - performs a firmware reset
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus software_reset();
+
+        /** device_reset - performs a hardware reset if there is a GPIO connected to the
+         * reset line of the device. Otherwise, performs a firmware reset.
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+#if defined(UNIT_TEST)
+        virtual
+#endif
+        RadioStatus device_reset();
+
+        /** set_tx_options - sets the transmit options byte, used with the transmit frames.
+         *                   Valid flags are:
+         *                       - DISABLE_RETRIES_AND_ROUTE_REPAIR
+         *                       - ENABLE_APS_ENCRYPTION
+         *                       - USE_EXTENDED_TX_TIMEOUT
+         *
+         *  @param options variable with the option flags
+         */
+        void set_tx_options(uint8_t options);
+
+        /** get_tx_options - returns the tx options byte configured in the library.
+         *
+         *  @returns the tx options byte configured in the library.
+         */
+        uint8_t get_tx_options() const;
+
+        /************************ Configuration member methods *************************/
+        /** write_config - write settings to non volatile memory
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus write_config();
+
+        /** config_io_sample_destination - configures to which node a remote module will send its IO Samples to.
+         * @Note: this will modify 'remote' DH and DL parameters, if the remote node is configured in transparent mode this could lead to unwanted behavior.
+         * Consult the module's reference manual for more information.
+         *
+         *  @param remote remote device that will be sending the IO Samples
+         *  @param destination remote device that will be receiving the IO Samples sent by 'remote'
+         *  @returns the result of the data transfer
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus config_io_sample_destination(const RemoteXBee& remote, const RemoteXBee& destination);
+
+        /** set_io_sample_rate - configures how often the IO Samples should be sent to the destination (see @ref send_io_sample_to).
+         *
+         *  @param remote remote device that will be sending the IO Samples
+         *  @param seconds the IO Sample sending rate in seconds (granularity is of 1 millisecond). Maximum is 65.535 seconds.
+         *  @returns the result of the data transfer
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_io_sample_rate(const RemoteXBee& remote, float seconds);
+
+        /** set_power_level - sets the power level at which the radio will transmit
+         *
+         *  @param level power level at which the radio will transmit
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_power_level(uint8_t level);
+
+        /** get_power_level - reads the power level configured in the radio
+         *
+         *  @param level pointer where the read power level will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_power_level(uint8_t * const level);
+
+        /** get_hw_version - gets the hardware version of the radio
+         *
+         *  @returns the hardware version of the radio
+         */
+        uint16_t get_hw_version() const;
+
+        /** get_fw_version - gets the firmware version of the radio
+         *
+         *  @returns the firmware version of the radio
+         */
+        uint16_t get_fw_version() const;
+
+        /** set_node_identifier - configures the Node Identifier string
+         *
+         *  @param node_id NULL-terminated string with the Node Identifier that will be set on the module. Up to 20 characters length (21 with NULL-terminator).
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_node_identifier(const char * const node_id);
+
+        /** get_node_identifier - reads the configured Node Identifier string
+         *
+         *  @param node_id Pointer to where to store the read Node Identifier, it must point to a buffer with at least 21-bytes length.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_node_identifier(char * const node_id);
+
+        /** enable_network_encryption - Enable network encryption.
+         *
+         *  @param enable whether to enable this feature or not
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus enable_network_encryption(bool enable);
+
+        /** set_network_encryption_key - Sets the 128-bit AES key used for encryption and decryption. Setting it to 0 will cause the coordinator to transmit the network key in the clear to joining devices, and will cause joining devices to acquire the network key in the clear when joining.
+         *  It is not recommended to set the key programmatically, because it could be read through the raw serial port bits.
+         *  @param key pointer to the 128-bit AES key
+         *  @param length size of the buffer pointed by 'key'
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_network_encryption_key(const uint8_t * const key, const uint16_t length);
+
+        /** start_node_discovery - starts a node discovery operation. The responses
+         * have to be processes on the callback function that have to be registered
+         * for that purpose.
+         *
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus start_node_discovery();
+
+        /** is_node_discovery_in_progress - checks if node discovery is in progress.
+         *  @returns true if node discovery is in progress, false otherwise
+         */
+        bool is_node_discovery_in_progress();
+
+#define XBEEZB_ND_OPTION_APPEND_DD          (1 << 0)
+#define XBEEZB_ND_OPTION_SELF_RESPONSE      (1 << 1)
+#define XBEE802_ND_OPTION_SELF_RESPONSE     (1 << 0)
+#define XBEEDM_ND_OPTION_APPEND_DD          (1 << 0)
+#define XBEEDM_ND_OPTION_SELF_RESPONSE      (1 << 1)
+#define XBEEDM_ND_OPTION_INCLUDE_RSSI       (1 << 2)
+
+        /** config_node_discovery - configures the node discovery operation
+         *
+         *  @param backoff_ms max allowed time for devices in the network to answer
+         *                    to the Node Discovery request
+         *  @param  options node discovery options (flags)
+         *              XBEE802_ND_OPTION_SELF_RESPONSE - to allow the module self responding (802.15.4 only)
+         *              XBEEZB_ND_OPTION_SELF_RESPONSE - to allow the module self responding (ZigBee only)
+         *              XBEEZB_ND_OPTION_APPEND_DD - to append the DD value to the response (ZigBee only)
+         *              XBEEDM_ND_OPTION_INCLUDE_RSSI - to include RSSI information in response (DigiMesh only)
+         *              XBEEDM_ND_OPTION_SELF_RESPONSE - to allow the module self responding (DigiMesh only)
+         *              XBEEDM_ND_OPTION_APPEND_DD - to append the DD value to the response (DigiMesh only)
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+         RadioStatus config_node_discovery(uint16_t backoff_ms, uint8_t options = 0);
+
+         /** get_config_node_discovery - reads the configuration of the node discovery
+          * settings
+          *
+          *  @param backoff_ms pointer where the configured node discovery back-off time value will be stored
+          *  @param  options pointer whre the node discovery options (flags) will be saved
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+         RadioStatus get_config_node_discovery(uint16_t * const backoff_ms, uint8_t * const options);
+
+        /** set_timeout - sets the timeout in ms, used by sync methods
+         *
+         *  @param timeout_ms new timeout in ms
+         */
+        void set_timeout(uint16_t timeout_ms);
+
+        /** get_timeout - gets the timeout in ms configured in the library. This value
+         *                is used in sync commands
+         *
+         *  @returns the configured timeout value in ms
+         */
+        uint16_t get_timeout() const;
+
+        /* ... */
+
+        /*********************** send_data member methods ************************/
+        /** send_data - sends data to a remote device
+         *
+         *  @param remote remote device
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr = true) = 0;
+
+        /** send_data_broadcast - sends data to all devices in the network, using the broadcast address.
+         *
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data_broadcast(const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** set_param - sets a parameter in the local radio by sending an AT command and waiting for the response.
+         *
+         *  @param param parameter to be set.
+         *  @param data the parameter value (4 bytes) to be set.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp set_param(const char * const param, uint32_t data);
+
+        /** set_param - sets a parameter in the local radio by sending an AT command and waiting for the response.
+         *
+         *  @param param parameter to be set.
+         *  @param data the parameter value byte array (len bytes) to be set.
+         *  @param len number of bytes of the parameter value.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp set_param(const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+        /** get_param - gets a parameter from the local radio by sending an AT command and waiting for the response.
+         *
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (4 bytes) will be stored.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp get_param(const char * const param, uint32_t * const data);
+
+        /** get_param - gets a parameter from the local radio by sending an AT command and waiting for the response.
+         *
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param value will be stored.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp get_param(const char * const param, uint8_t * const data, uint16_t * const len);
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value (4 bytes) to be set.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data) = 0;
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value byte array (len bytes) to be set.
+         *  @param len number of bytes of the parameter value.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0) = 0;
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (4 bytes) will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data) = 0;
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param value will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len) = 0;
+
+        /** process_rx_frames - method that processes the frames queued in the reception
+         *                      buffer. Calls the process_frame_data method of the frame
+         *                      handlers registered
+         *
+         *  @returns Number of dropped frames since latest call to this method.
+         */
+        uint32_t process_rx_frames();
+
+        /** register_modem_status_cb - registers the callback function that will be called
+         * when a Modem Status packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_modem_status_cb(modem_status_cb_t function);
+
+        /** unregister_modem_status_cb - removes the Modem Status reception callback */
+        void unregister_modem_status_cb();
+
+    protected:
+
+#define EXTRA_XBEE_PROTOCOLS
+
+        enum RadioProtocol {
+            None,
+            ZigBee,
+            Raw_802_15_4,
+#ifdef EXTRA_XBEE_PROTOCOLS
+            XBeeWiFi,
+            DigiMesh,
+            SmartEnergy,
+            DigiPoint,
+            ZNet,
+#endif
+        };
+        /** send_byte_escaping_if - sends a byte, through the serial interface, to
+         * the radio, escaping the byte if the working mode of the radio is API2.
+         *
+         *  @param line PWM line being set
+         *  @param data the byte that will be send to radio
+         */
+        void send_byte_escaping_if(uint8_t data);
+
+        /** uart_read_cb - serial interface callback, called when data is received on
+         * the serial port. The function parses the incoming data and, when a good
+         * frame is detected, saves it in the frame list
+         */
+        void uart_read_cb();
+
+        /** get_this_api_frame - searches in the FrameBuffer for an incoming frame
+         *                       with frameid equal to id and frame type equal to type
+         *                       or type2. If after timeout the frame hast not been found,
+         *                       returns.
+         *
+         *  @param id id of the frame we are looking for.
+         *  @param type tye type we expect the frame to be.
+         *  @param type2 alternative valid type, if provided.
+         *  @returns a pointer to the frame found in the FrameBuffer or a null pointer if
+         *           the frame has not been found and the timeout expired.
+         */
+        ApiFrame * get_this_api_frame(uint8_t id, ApiFrame::ApiFrameType type,
+                    ApiFrame::ApiFrameType type2 = ApiFrame::Invalid);
+
+        /** send_api_frame - method to send, over the serial port, an API frame
+         *
+         * @param frame pointer to the frame that will be sent.
+         */
+#if defined(UNIT_TEST)
+        virtual
+#endif
+        void send_api_frame(ApiFrame *frame);
+
+        /** update_radio_status - method called when a modem status frame is received
+         *  to update the internal status variables of the library.
+         *  @note This is not a pure virtual function because it can be called while
+         *        the object is being constructed and we need the implementation of the
+         *        base class.
+         *
+         *  @param status byte with the status received in the modem status frame
+         */
+        virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+        /** Method used internaly by the derived classes to transmit data to
+         * remote nodes, waiting for the answer from the device
+         *
+         *  @param frame frame that will be sent to the radio (have to be a
+         *         proper transmit frame
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data(ApiFrame *frame);
+
+        /** send_at_cmd - sends an AT command to the radio and waits for the response.
+         *
+         *  @param frame api frame with the command and command params.
+         *  @param buf pointer where the param response (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param response will be stored.
+         *  @param radio_location radio location, either RadioLocal or RadioRemote.
+         *  @param reverse reverse the byte ordering of the response saved in buf.
+         *  @returns the command response status.
+         */
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame,
+                    uint8_t *const buf, uint16_t *const len, RadioLocation radio_location = RadioLocal, bool reverse = true);
+
+        /* send_at_cmd - methods used internally by other methods */
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame);
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint8_t *data);
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint16_t *data);
+        AtCmdFrame::AtCmdResp send_at_cmd(AtCmdFrame *frame, uint32_t *data);
+
+        /** register_frame_handler - registers an object to handle incoming frames from
+         *                           the radio.
+         *  @note For any type of frame more than one handler can be registered and all
+         *        of them are called, sequentially, when a frame of that type arrives.
+         *
+         *  @param handler pointer to the frame handler object
+         *  @returns the result of the registration
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus register_frame_handler(FrameHandler *const handler);
+
+        /** unregister_frame_handler - removes a previously registered frame handler
+         *
+         *  @param handler pointer to the frame handler object
+         *  @returns the result of the unregister operation
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus unregister_frame_handler(FrameHandler *const handler);
+
+        /** get_radio_protocol - returns the RF protocol that the connected module uses
+         *                       based on its firmware and hardware versions
+         *
+         *  @returns a RadioProtocol enum.
+         */
+        RadioProtocol get_radio_protocol(void) const;
+
+        /** _get_iosample - forces an io_sample read (reads all digital and analog inputs)
+         *
+         *  @param remote remote device
+         *  @param io_sample buffer where the io_sample response is copied
+         *  @param len pointer where the length of the io_sample response is stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus _get_iosample(const RemoteXBee& remote, uint8_t * const io_sample, uint16_t * const len);
+
+        void _get_remote_node_by_id(const char * const node_id, uint64_t * addr64, uint16_t * addr16);
+
+        /** check_radio_flow_control - checks that the radio has the CTS "D7" and RTS "D6" pins configured
+         *                       according to the serial hardware flow control selected by the user
+         *
+         *  @returns true if check success.
+         */
+        bool check_radio_flow_control();
+
+        /** get_AI - reads the AI parameter.
+         *
+         *  @returns
+         *      -1 if an error occurred when reading AI.
+         *      0-0xFF the AI value.
+         */
+        int get_AI(void);
+
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms) = 0;
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout) = 0;
+
+        /** serial hardware flow control selected by the user (RTSCTS, RTS,CTS) */
+        SerialBase::Flow _serial_flow_type;
+
+        /** Operating mode of the module (API1, API2,...) */
+        RadioMode   _mode;
+
+        /** Hardware version value of the radio */
+        uint16_t    _hw_version;
+
+        /** Firmware version value of the radio */
+        uint16_t    _fw_version;
+
+        /** Timeout in ms for sync operations (when we wait for a response) */
+        uint16_t    _timeout_ms;
+
+        /** Device 64 bit address (SH, SL) */
+        uint64_t      _dev_addr64;
+
+        /** Serial Interface, use RawSerial as we dont use the streams */
+        RawSerial   *_uart;
+
+        /** IO connected to the radio reset line */
+        DigitalOut  *_reset;
+
+        /** Transmit options byte */
+        uint8_t     _tx_options;
+
+        /** Array of frame handler pointers. We use an array instead of a vector or other
+         *  data structure to save memory and avoid dynamic memory allocation, to avoid
+         *  memory fragmentation */
+        FrameHandler *_fhandlers[MAX_FRAME_HANDLERS];
+
+        /** Hardware reset counter, automatically updated by the library */
+        volatile uint16_t    _hw_reset_cnt;
+
+        /** Watchdog reset counter, automatically updated by the library */
+        volatile uint16_t    _wd_reset_cnt;
+
+        /** Frame handler used for the Modem Status packets. Automatically registered when a callback
+         *  function is registered */
+        FH_ModemStatus  *_modem_status_handler;
+
+        /** Latest modem status received */
+        AtCmdFrame::ModemStatus _modem_status;
+
+        /** Library is initializing */
+        bool _initializing;
+
+        /** Timer used for node discovery */
+        Timer _nd_timer;
+
+        /** node discovery timeout */
+        int _nd_timeout;
+
+        /** If a _get_remote_node_by_id() is in progress, this keeps the expected frame id */
+        uint8_t _node_by_ni_frame_id;
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* defined(__DIGI_RADIO_H_) */
+
+
+
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee802/XBee802.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee802/XBee802.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,615 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+#include "XBee802.h"
+#include "IO/IOSample802.h"
+#include "Frames/802_Frames.h"
+#include "FrameHandlers/FH_ModemStatus.h"
+
+using namespace XBeeLib;
+
+/* Class constructor */
+XBee802::XBee802(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+        XBee(tx, rx, reset, rts, cts, baud),
+        _nd_handler(NULL), _rx_64b_handler(NULL), _rx_16b_handler(NULL),
+        _io_data_64b_handler(NULL), _io_data_16b_handler(NULL)
+{
+
+}
+
+/* Class destructor */
+XBee802::~XBee802()
+{
+    unregister_node_discovery_cb();
+    unregister_receive_cb();
+    unregister_io_sample_cb();
+}
+
+RadioStatus XBee802::init()
+{
+    RadioStatus retval = XBee::init();
+    uint16_t addr16;
+    RadioStatus error = get_network_address(&addr16);
+    if (error == Success) {
+        digi_log(LogLevelInfo, "ADDR16: %04x\r\n", addr16);
+    } else {
+        digi_log(LogLevelInfo, "ADDR16: UNKNOWN\r\n");
+    }
+
+    const RadioProtocol radioProtocol = get_radio_protocol();
+    if (radioProtocol != Raw_802_15_4) {
+        digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", Raw_802_15_4, radioProtocol);
+        retval = Failure;
+    }
+    assert(radioProtocol == Raw_802_15_4);
+
+    return retval;
+}
+
+RadioStatus XBee802::set_channel(uint8_t  channel)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    /* Pro and Non-Pro modules have different channels available. The at 
+       command will return an error if the selected channel is not available */
+    cmdresp = set_param("CH", channel);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee802::get_channel(uint8_t * const  channel)
+{
+    if (channel == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("CH", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *channel = var32;
+    return Success;
+}
+
+RadioStatus XBee802::set_panid(uint16_t  panid)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("ID", panid);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee802::get_panid(uint16_t * const  panid)
+{
+    if (panid == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("ID", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *panid = var32;
+    return Success;
+}
+
+RadioStatus XBee802::get_network_address(uint16_t * const  addr16)
+{
+    if (addr16 == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("MY", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *addr16 = var32;
+    return Success;
+}
+
+RadioStatus XBee802::set_network_address(uint16_t  addr16)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("MY", addr16);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBee802::get_node_discovery_timeout(uint16_t * const timeout_ms)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("NT", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *timeout_ms = (uint16_t)var32;
+
+    /* No N? command available for this protocol. Add a fix 1s guard time */
+    *timeout_ms += 1000;
+
+    return Success;
+}
+
+RadioStatus XBee802::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
+{
+    const RadioStatus status = get_node_discovery_timeout(timeout_ms);
+
+    /* This protocol requires to wait for the complete timeout before attempting
+       to execute other commands */
+    *wait_for_complete_timeout = true;
+
+    return status;
+}
+
+void XBee802::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+    /* Update the radio status variables */
+    if (modem_status == AtCmdFrame::HwReset) {
+        _hw_reset_cnt++;
+    } else if (modem_status == AtCmdFrame::WdReset) {
+        _wd_reset_cnt++;
+    }
+
+    _modem_status = modem_status;
+
+    digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
+}
+
+TxStatus XBee802::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr)
+{
+    if (remote.is_valid_addr64b()) {
+        const uint64_t remote64 =  remote.get_addr64();
+
+        digi_log(LogLevelDebug, "send_data ADDR64: %08x:%08x\r\n", UINT64_HI32(remote64), UINT64_LO32(remote64));
+
+        TxFrame802 frame = TxFrame802(remote64, _tx_options, data, len);
+
+        if (syncr) {
+            return send_data(&frame);
+        } else {
+            frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+            send_api_frame(&frame);
+            return TxStatusSuccess;
+        }
+    }
+
+    if (remote.is_valid_addr16b()) {
+        const uint16_t remote16 = remote.get_addr16();
+
+        digi_log(LogLevelDebug, "send_data ADDR16: %04x\r\n", remote16);
+
+        TxFrame802 frame = TxFrame802(remote16, _tx_options, data, len);
+
+        if (syncr) {
+            return send_data(&frame);
+        } else {
+            frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+            send_api_frame(&frame);
+            return TxStatusSuccess;
+        }
+    }
+
+    return TxStatusInvalidAddr;
+}
+
+XBee802::AssocStatus XBee802::get_assoc_status(void)
+{
+    return (AssocStatus)get_AI();
+}
+
+RemoteXBee802 XBee802::get_remote_node_by_id(const char * const node_id)
+{
+    uint64_t addr64;
+    uint16_t addr16;
+
+    _get_remote_node_by_id(node_id, &addr64, &addr16);
+    return RemoteXBee802(addr64, addr16);
+}
+
+void XBee802::register_node_discovery_cb(node_discovery_802_cb_t function)
+{
+    if (_nd_handler == NULL) {
+        _nd_handler = new FH_NodeDiscovery802();
+        register_frame_handler(_nd_handler);
+    }
+    _nd_handler->register_node_discovery_cb(function);
+}
+
+void XBee802::unregister_node_discovery_cb()
+{
+    if (_nd_handler != NULL) {
+        _nd_handler->unregister_node_discovery_cb();
+        unregister_frame_handler(_nd_handler);
+        delete _nd_handler;
+        _nd_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+void XBee802::register_receive_cb(receive_802_cb_t function)
+{
+    if (_rx_64b_handler == NULL) {
+        _rx_64b_handler = new FH_RxPacket64b802();
+        register_frame_handler(_rx_64b_handler);
+    }
+    _rx_64b_handler->register_receive_cb(function);
+
+    if (_rx_16b_handler == NULL) {
+        _rx_16b_handler = new FH_RxPacket16b802();
+        register_frame_handler(_rx_16b_handler);
+    }
+    _rx_16b_handler->register_receive_cb(function);
+}
+
+void XBee802::unregister_receive_cb()
+{
+    if (_rx_64b_handler != NULL) {
+        _rx_64b_handler->unregister_receive_cb();
+        unregister_frame_handler(_rx_64b_handler);
+        delete _rx_64b_handler;
+        _rx_64b_handler = NULL; /* as delete does not set to NULL */
+    }
+
+    if (_rx_16b_handler != NULL) {
+        _rx_16b_handler->unregister_receive_cb();
+        unregister_frame_handler(_rx_16b_handler);
+        delete _rx_16b_handler;
+        _rx_16b_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+void XBee802::register_io_sample_cb(io_data_cb_802_t function)
+{
+    if (_io_data_64b_handler == NULL) {
+        _io_data_64b_handler = new FH_IoDataSampe64b802();
+        register_frame_handler(_io_data_64b_handler);
+    }
+    _io_data_64b_handler->register_io_data_cb(function);
+
+    if (_io_data_16b_handler == NULL) {
+        _io_data_16b_handler = new FH_IoDataSampe16b802();
+        register_frame_handler(_io_data_16b_handler);
+    }
+    _io_data_16b_handler->register_io_data_cb(function);
+}
+
+void XBee802::unregister_io_sample_cb()
+{
+    if (_io_data_64b_handler != NULL) {
+        _io_data_64b_handler->unregister_io_data_cb();
+        unregister_frame_handler(_io_data_64b_handler);
+        delete _io_data_64b_handler;
+        _io_data_64b_handler = NULL; /* as delete does not set to NULL */
+    }
+
+    if (_io_data_16b_handler != NULL) {
+        _io_data_16b_handler->unregister_io_data_cb();
+        unregister_frame_handler(_io_data_16b_handler);
+        delete _io_data_16b_handler;
+        _io_data_16b_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+AtCmdFrame::AtCmdResp XBee802::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data)
+{
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse;
+
+    if (remote.is_valid_addr64b()) {
+        const uint64_t dev_addr64 =  remote.get_addr64();
+
+        AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param);
+        atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote);
+    } else if (remote.is_valid_addr16b()) {
+        const uint16_t dev_addr16 = remote.get_addr16();
+
+        AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param);
+        atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote);
+    } else {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBee802::set_param(const RemoteXBee& remote, const char * const param, uint32_t data)
+{
+    if (remote.is_valid_addr64b()) {
+        const uint64_t dev_addr64 =  remote.get_addr64();
+
+        AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param, data);
+        return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+    }
+
+    if (remote.is_valid_addr16b()) {
+        const uint16_t dev_addr16 = remote.get_addr16();
+
+        AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param, data);
+        return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+    }
+
+    return AtCmdFrame::AtCmdRespInvalidAddr;
+}
+
+AtCmdFrame::AtCmdResp XBee802::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len)
+{
+    if (remote.is_valid_addr64b()) {
+        const uint64_t dev_addr64 =  remote.get_addr64();
+
+        AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param, data, len);
+        return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+    }
+
+    if (remote.is_valid_addr16b()) {
+        const uint16_t dev_addr16 = remote.get_addr16();
+
+        AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param, data, len);
+        return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+    }
+
+    return AtCmdFrame::AtCmdRespInvalidAddr;
+}
+
+AtCmdFrame::AtCmdResp XBee802::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len)
+{
+    if (remote.is_valid_addr64b()) {
+        uint64_t dev_addr64 = remote.get_addr64();
+
+        AtCmdFrame cmd_frame = AtCmdFrame(dev_addr64, param);
+        return send_at_cmd(&cmd_frame, data, len, RadioRemote, false);
+    }
+
+    if (remote.is_valid_addr16b()) {
+        uint16_t dev_addr16 = remote.get_addr16();
+
+        AtCmdFrame cmd_frame = AtCmdFrame(dev_addr16, param);
+        return send_at_cmd(&cmd_frame, data, len, RadioRemote, false);
+    }
+
+    return AtCmdFrame::AtCmdRespInvalidAddr;
+}
+
+static void get_dio_cmd(XBee802::IoLine line, char * const iocmd)
+{
+    if (line >= XBee802::PWM0) {
+        iocmd[0] = 'P';
+        iocmd[1] = '0' + line - XBee802::PWM0;
+    } else {
+        iocmd[0] = 'D';
+        iocmd[1] = '0' + line;
+    }
+    iocmd[2] = '\0';
+}
+
+RadioStatus XBee802::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3];
+
+    get_dio_cmd(line, iocmd);
+
+    cmdresp = set_param(remote, iocmd, (uint8_t)mode);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBee802::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3];
+
+    get_dio_cmd(line, iocmd);
+
+    uint32_t var32;
+    cmdresp = get_param(remote, iocmd, &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *mode = (IoMode)var32;
+
+    return Success;
+}
+
+RadioStatus XBee802::set_dio(const RemoteXBee& remote, IoLine line, DioVal val)
+{
+    if (line > DI8) {
+        digi_log(LogLevelError, "set_dio: Pin %d not supported as IO\r\n", line);
+        return Failure;
+    }
+
+    if (val == Low) {
+        return set_pin_config(remote, line, DigitalOutLow);
+    } else {
+        return set_pin_config(remote, line, DigitalOutHigh);
+    }
+}
+
+RadioStatus XBee802::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)
+{
+    return get_iosample(remote).get_dio(line, val);
+}
+
+RadioStatus XBee802::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)
+{
+    return get_iosample(remote).get_adc(line, val);
+}
+
+RadioStatus XBee802::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3] = { 'M', '0', '\0' };
+
+    if (line != PWM0 && line != PWM1) {
+        return Failure;
+    }
+    if (line == PWM1) {
+        iocmd[1] = '1';
+    }
+
+    uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100);
+
+    cmdresp = set_param(remote, iocmd, pwm_val);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+IOSample802 XBee802::get_iosample(const RemoteXBee& remote)
+{
+    uint8_t io_sample[MAX_IO_SAMPLE_802_LEN];
+    uint16_t len = sizeof io_sample;
+
+    RadioStatus resp = _get_iosample(remote, io_sample, &len);
+    if (resp != Success) {
+        digi_log(LogLevelError, "XBee802::get_iosample failed to get an IOSample\r\n");
+        len = 0;
+    }
+    return IOSample802(io_sample, len);
+}
+
+static uint8_t get_dio_mask(XBee802::IoLine line)
+{
+    switch (line) {
+        case XBee802::DIO4_AD4:
+            return (1 << 0);
+        case XBee802::DIO3_AD3:
+            return (1 << 1);
+        case XBee802::DIO2_AD2:
+            return (1 << 2);
+        case XBee802::DIO1_AD1:
+            return (1 << 3);
+        case XBee802::DIO0_AD0:
+            return (1 << 4);
+        case XBee802::DIO6:
+            return (1 << 5);
+        case XBee802::DI8:
+            return (1 << 6);
+        default:
+            return 0;
+    }
+}
+
+RadioStatus XBee802::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+    uint8_t pr;
+
+    cmdresp = get_param(remote, "PR", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    pr = var32;
+
+    const uint8_t dio_mask = get_dio_mask(line);
+    if (dio_mask == 0) {
+        digi_log(LogLevelError, "XBee802::set_pin_pull_up: invalid pin %d\r\n", line);
+        return Failure;
+    }
+
+    if (enable) {
+        pr |= dio_mask;
+    } else {
+        pr &= ~dio_mask;
+    }
+
+    cmdresp = set_param(remote, "PR", pr);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+static uint8_t get_dio_ic_mask(XBee802::IoLine line)
+{
+    if (line < XBee802::DI8) {
+        return (1 << line);
+    }
+    return 0;
+}
+
+RadioStatus XBee802::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable)
+{
+    if (line > DIO7) {
+        digi_log(LogLevelError, "XBee802::enable_dio_change_detection: pin not supported (%d)\r\n", line);
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+    uint8_t ic;
+
+    cmdresp = get_param(remote, "IC", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    ic = var32;
+
+    const uint8_t dio_mask = get_dio_ic_mask(line);
+    if (dio_mask == 0) {
+        digi_log(LogLevelError, "XBeeZB::enable_dio_change_detection: invalid pin %d\r\n", line);
+        return Failure;
+    }
+
+    if (enable) {
+        ic |= dio_mask;
+    } else {
+        ic &= ~dio_mask;
+    }
+
+    cmdresp = set_param(remote, "IC", ic);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+#ifdef GET_PWM_AVAILABLE
+RadioStatus XBee802::get_pwm(const RemoteXBee& remote, IoLine line, float * const duty_cycle)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3] = { 'M', '0', '\0' };
+
+    if (line != PWM0 && line != PWM1) {
+        return Failure;
+    }
+
+    if (line == PWM1) {
+        iocmd[1] = '1';
+    }
+
+    uint16_t pwm_val;
+
+    cmdresp = get_param(remote, iocmd, &pwm_val);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    *duty_cycle = (float)(pwm_val * 100 / DR_PWM_MAX_VAL);
+
+    return Success;
+}
+#endif
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBee802/XBee802.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBee802/XBee802.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,405 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_802_H_)
+#define __XBEE_802_H_
+
+#include "FrameHandlers/FH_AtCmdResp.h"
+#include "FrameHandlers/FH_RxPacket802.h"
+#include "FrameHandlers/FH_IoDataSample802.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/** Class for XBee ZigBee modules, derived from XBee */
+class XBee802 : public XBee
+{
+    public:
+
+        /**
+         * IoLine for XBee802 Modules
+         */
+        enum IoLine {
+            DIO0_AD0 = 0, /**< DIO0_AD0 pin */
+            DIO1_AD1 = 1, /**< DIO1_AD1 pin */
+            DIO2_AD2 = 2, /**< DIO2_AD2 pin */
+            DIO3_AD3 = 3, /**< DIO3_AD3 pin */
+            DIO4_AD4 = 4, /**< DIO4_AD4 pin */
+            DIO5_AD5 = 5, /**< DIO5_AD5 pin */
+            DIO6     = 6, /**< DIO6 pin */
+            DIO7     = 7, /**< DIO7 pin */
+            DI8      = 8, /**< DI8 pin */
+            PWM0,         /**< PWM0 pin */
+            PWM1           /**< PWM1 pin */
+        };
+
+        enum AssocStatus {
+            ErrorReading        = -1,       /**< Error occurred when reading parameter. */
+            Joined              = 0x00,     /**< Successful Completion - Coordinator successfully started or End Device association complete. */
+            ActiveScanTimeOut   = 0x01,     /**< Active Scan Timeout. */
+            NoPANs              = 0x02,     /**< Active Scan found no PANs. */
+            JoinNotAllowed      = 0x03,     /**< Active Scan found PAN, but the Coordinator's Allow Association bit is not set. */
+            BeaconsFailed       = 0x04,     /**< Active Scan found PAN, but Coordinator and End Device are not configured to support beacons. */
+            BadPAN              = 0x05,     /**< Active Scan found PAN, but Coordinator ID (PAN ID) value does not match the ID of the End Device. */
+            BadChannel          = 0x06,     /**< Active Scan found PAN, but Coordinator CH (Channel) value does not match the CH of the End Device */
+            EnergyScanTimeout   = 0x07,     /**< Energy Scan timed out. */
+            CoordStartFailed    = 0x08,     /**< Coordinator start request failed. */
+            CoordBadParameters  = 0x09,     /**< Coordinator could not start due to Invalid Parameter. */
+            CoordRealignment    = 0x0A,     /**< Coordinator Realignment is in progress. */
+            AssocReqNotSent     = 0x0B,     /**< Association Request not sent. */
+            AssocReqTimeout     = 0x0C,     /**< Association Request timed out - no reply was received. */
+            AssocReqInvalidPara = 0x0D,     /**< Association Request had an Invalid Parameter. */
+            AssocReqChannelFail = 0x0E,     /**< Association Request Channel Access Failure - Request was not transmitted - CCA failure. */
+            RemCoordNoACK       = 0x0F,     /**< Remote Coordinator did not send an ACK after Association Request was sent. */
+            RemCoordLateACK     = 0x10,     /**< Remote Coordinator did not reply to the Association Request, but an ACK was received after sending the request. */
+            Associating         = 0xFF      /**< RF Module is attempting to associate. */
+        };
+
+        /** Class constructor
+         * @param tx the TX pin of the UART that will interface the XBee module
+         * @param rx the RX pin of the UART that will interface the XBee module
+         * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+         * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+         * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+         */
+        XBee802(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+        /** Class destructor */
+        virtual ~XBee802();
+
+        /** init -  initializes object
+         * This function must be called just after creating the object so it initializes internal data.
+         * @returns
+         *         Success if the module has been properly initialized and is ready to process data.
+         *         Failure otherwise.
+         */
+        RadioStatus init();
+
+        /** set_panid - sets the 16 bit PAN ID.
+         *
+         *  @param panid the PAN ID value that will be set on the radio
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_panid(uint16_t panid);
+
+        /** get_panid - gets the configured 16 bit PAN ID
+         *
+         *  @param panid pointer where the read PAN ID value will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_panid(uint16_t * const panid);
+
+        /** set_channel - sets the network channel number
+         *
+         *  @param channel the channel in which the radio operates. Range is 0x0B - 0x1A for XBee and 0x0C - 0x17 for XBee-PRO.
+         *  The Center Frequency = 2.405 + (CH - 11) * 5 MHz
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_channel(uint8_t channel);
+
+        /** get_panid - gets the network channel number
+         *
+         *  @param channel pointer where the channel value will be stored.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_channel(uint8_t * const channel);
+
+        /** get_network_address - gets the 16bit network address of the device
+         *
+         *  @param addr pointer where the device 16bit network address will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_network_address(uint16_t * const addr);
+
+        /** set_network_address - sets the 16 bit network address of the device
+         *
+         *  @param addr the device 16bit network address (0x0 - 0xFFFF)
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_network_address(uint16_t addr);
+
+        /** register_node_discovery_cb - registers the callback function that will be called
+         * when the responses to the node discovery command arrive
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_node_discovery_cb(node_discovery_802_cb_t function);
+
+        /** unregister_node_discovery_cb - removes the node discovery callback */
+        void unregister_node_discovery_cb();
+
+        /** register_receive_cb - registers the callback function that will be called
+         * when a rx packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_receive_cb(receive_802_cb_t function);
+
+        /** unregister_receive_cb - removes the rx packet callback */
+        void unregister_receive_cb();
+
+        /** register_io_sample_cb - registers the callback function that will be called
+         * when a IO Sample Data packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_io_sample_cb(io_data_cb_802_t function);
+
+        /** unregister_io_sample_cb - removes the IO Sample Data reception callback */
+        void unregister_io_sample_cb();
+
+        /*********************** send_data member methods ************************/
+        /** send_data - sends data to a remote device
+         *
+         *  @param remote remote device
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** get_assoc_status - returns current network association status. This wraps AI parameter, for more information refer to moudle's Reference Manual.
+         *
+         *  @returns an AssocStatus with current network association status.
+         */
+        AssocStatus get_assoc_status(void);
+
+        /** get_remote_node_by_id - searches for a device in the network with the specified Node Identifier.
+         *
+         *  @param node_id node id of the device we are looking for
+         *  @returns a RemoteXBee802 with the 16-bit and 64-bit address of the remote device whose node id matches with the parameter.
+         *  If node is not found, the returned object will have invalid addresses (RemoteXBee802::is_valid() will return false).
+         */
+        RemoteXBee802 get_remote_node_by_id(const char * const node_id);
+
+        /* Allow using XBee::set_param() methods for local radio from this class */
+        using XBee::set_param;
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value (4 bytes) to be set.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data);
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param the parameter value byte array (len bytes) to be set.
+         *  @param len number of bytes of the parameter value.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+        /* Allow using XBee::get_param() methods for local radio from this class */
+        using XBee::get_param;
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (4 bytes) will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data);
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param value will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len);
+
+        /************************* IO member methods **************************/
+        /** set_pin_config - configures a radio IO line
+         *
+         *  @param remote remote device
+         *  @param line IO line being configured
+         *  @param mode configuration mode for the selected line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode);
+
+        /** get_pin_config - gets the configuration of a radio IO line
+         *
+         *  @param remote remote device
+         *  @param line IO line being read to get its configuration
+         *  @param mode pointer where the configuration will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode);
+
+        /** set_dio - sets to low/high a DIO line
+         *
+         *  @param remote remote device
+         *  @param line DIO line being set
+         *  @param val value that will be set in the DIO line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_dio(const RemoteXBee& remote, IoLine line, DioVal val);
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param remote remote device
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val);
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param remote remote device
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from the ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val);
+
+        /** get_iosample - retrieves an @ref IOSample802 from a remote node. This object can be used to get the remote node's ADC and DIO values.
+         *
+         *  @param remote remote device
+         *  @returns IOSample802 object with the remote node's DIO and ADC values.
+         */
+        IOSample802 get_iosample(const RemoteXBee& remote);
+
+        /** set_pwm - sets the duty cycle of a PWM line
+         *
+         *  @param remote remote device
+         *  @param line PWM line being set
+         *  @param duty_cycle duty cycle that will be set in the PWM line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle);
+
+        /** set_pin_pull_up - enables or disables the internal pull-up resistor of a line
+         *
+         *  @param remote remote device
+         *  @param line line being configured for pull-up
+         *  @param enable whether to enable the internal pull-up resistor.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable);
+
+        /** enable_dio_change_detection - enables or disables the notification when a change is detected in a digital input line.
+         * In other words, it will force an IO Sample transmission when the DIO state changes. Only for DIO0 to DIO7.
+         *
+         *  @param remote remote device
+         *  @param line line being configured for pull-up
+         *  @param enable whether to enable the internal pull-up resistor.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable);
+
+/* TODO: With current firmware ATM0 fails: Returns just OK and sets pwm to 0 */
+#ifdef GET_PWM_AVAILABLE
+        /** get_pwm - gets the duty cycle of a PWM line
+         *
+         *  @param remote remote device
+         *  @param line PWM line being read
+         *  @param duty_cycle pointer where the value of the duty cycle read from
+         *                    the PWM line will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_pwm(const RemoteXBee& remote, IoLine line, float * const duty_cycle);
+#endif
+
+    protected:
+
+        /** Frame handler used for the node discovery. Registered when a callback function
+         * is registered */
+        FH_NodeDiscovery802  *_nd_handler;
+
+         /** Frame handler used for the rx 64 bit packets. Automatically registered when a callback
+         *  function is registered */
+        FH_RxPacket64b802  *_rx_64b_handler;
+
+         /** Frame handler used for the rx 16 bit packets. Automatically registered when a callback
+         *  function is registered */
+        FH_RxPacket16b802  *_rx_16b_handler;
+
+        /** Frame handler used for the 64 bit IO Data Samples packets. Automatically registered when a callback
+        *  function is registered */
+        FH_IoDataSampe64b802  *_io_data_64b_handler;
+
+        /** Frame handler used for the 16 bit IO Data Samples packets. Automatically registered when a callback
+        *  function is registered */
+        FH_IoDataSampe16b802  *_io_data_16b_handler;
+
+        /** Method called directly by the library when a modem status frame is received to
+         * update the internal status variables */
+        virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+        /* Allow using XBee::send_data() methods from this class */
+        using XBee::send_data;
+
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms);
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout);
+
+    private:
+
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __XBEE_802_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBeeDM/XBeeDM.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBeeDM/XBeeDM.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,557 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeDM.h"
+#include "IO/IOSampleDM.h"
+#include "Frames/DigiMeshFrames.h"
+
+using namespace XBeeLib;
+
+#define BROADCAST_RADIUS_USE_NH 0x00
+
+/* Class constructor */
+XBeeDM::XBeeDM(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+         XBee(tx, rx, reset, rts, cts, baud), _nd_handler(NULL), _rx_pkt_handler(NULL), _io_data_handler(NULL)
+{
+}
+
+RadioStatus XBeeDM::init()
+{
+    RadioStatus retval = XBee::init();
+
+    const RadioProtocol radioProtocol = get_radio_protocol();
+    if (radioProtocol != DigiMesh) {
+        digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", DigiMesh, radioProtocol);
+        retval = Failure;
+    }
+    assert(radioProtocol == DigiMesh);
+
+    return retval;
+}
+
+/* Class destructor */
+XBeeDM::~XBeeDM()
+{
+    unregister_node_discovery_cb();
+    unregister_receive_cb();
+    unregister_io_sample_cb();
+}
+
+RadioStatus XBeeDM::set_channel(uint8_t  channel)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    /* Pro and Non-Pro modules have different channels available. The at 
+       command will return an error if the selected channel is not available */
+    cmdresp = set_param("CH", channel);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBeeDM::get_channel(uint8_t * const  channel)
+{
+    if (channel == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("CH", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *channel = var32;
+    return Success;
+}
+
+RadioStatus XBeeDM::set_network_id(uint16_t network_id)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("ID", network_id);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBeeDM::get_network_id(uint16_t * const network_id)
+{
+    if (network_id == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("ID", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *network_id = var32;
+    return Success;
+}
+
+RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("N?", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *timeout_ms = (uint16_t)var32;
+
+    return Success;
+}
+
+RadioStatus XBeeDM::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
+{
+    const RadioStatus status = get_node_discovery_timeout(timeout_ms);
+
+    *wait_for_complete_timeout = false;
+
+    return status;
+}
+
+void XBeeDM::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+    /* Update the radio status variables */
+    if (modem_status == AtCmdFrame::HwReset) {
+        _hw_reset_cnt++;
+    } else if (modem_status == AtCmdFrame::WdReset) {
+        _wd_reset_cnt++;
+    }
+
+    _modem_status = modem_status;
+
+    digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
+}
+
+TxStatus XBeeDM::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr)
+{
+    if (!remote.is_valid_addr64b()) {
+        return TxStatusInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    TxFrameDM frame = TxFrameDM(remote64, remote16, BROADCAST_RADIUS_USE_NH,
+                                _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+TxStatus XBeeDM::send_data(const RemoteXBee& remote, uint8_t source_ep,
+                                uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
+                                const uint8_t *const data, uint16_t len, bool syncr)
+{
+    if (!remote.is_valid_addr64b()) {
+        return TxStatusInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    TxFrameDM frame = TxFrameDM(remote64, remote16, source_ep, dest_ep,
+                                cluster_id, profile_id, BROADCAST_RADIUS_USE_NH,
+                                _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+TxStatus XBeeDM::send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr)
+{
+    const uint64_t remaddr = ADDR64_COORDINATOR;
+
+    TxFrameDM frame = TxFrameDM(remaddr, ADDR16_UNKNOWN, BROADCAST_RADIUS_USE_NH, _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+RemoteXBeeDM XBeeDM::get_remote_node_by_id(const char * const node_id)
+{
+    uint64_t addr64;
+    uint16_t addr16;
+    _get_remote_node_by_id(node_id, &addr64, &addr16);
+    return RemoteXBeeDM(addr64);
+}
+
+void XBeeDM::register_node_discovery_cb(node_discovery_dm_cb_t function)
+{
+    if (_nd_handler == NULL) {
+        _nd_handler = new FH_NodeDiscoveryDM();
+        register_frame_handler(_nd_handler);
+    }
+    _nd_handler->register_node_discovery_cb(function);
+}
+
+void XBeeDM::unregister_node_discovery_cb()
+{
+    if (_nd_handler != NULL) {
+        _nd_handler->unregister_node_discovery_cb();
+        unregister_frame_handler(_nd_handler);
+        delete _nd_handler;
+        _nd_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+void XBeeDM::register_receive_cb(receive_dm_cb_t function)
+{
+    if (_rx_pkt_handler == NULL) {
+        _rx_pkt_handler = new FH_RxPacketDM();
+        register_frame_handler(_rx_pkt_handler);
+    }
+    _rx_pkt_handler->register_receive_cb(function);
+}
+
+void XBeeDM::unregister_receive_cb()
+{
+    if (_rx_pkt_handler != NULL) {
+        _rx_pkt_handler->unregister_receive_cb();
+        unregister_frame_handler(_rx_pkt_handler);
+        delete _rx_pkt_handler;
+        _rx_pkt_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+void XBeeDM::register_io_sample_cb(io_data_cb_dm_t function)
+{
+    if (_io_data_handler == NULL) {
+        _io_data_handler = new FH_IoDataSampeDM();
+        register_frame_handler(_io_data_handler);
+    }
+    _io_data_handler->register_io_data_cb(function);
+}
+
+void XBeeDM::unregister_io_sample_cb()
+{
+    if (_io_data_handler != NULL) {
+        _io_data_handler->unregister_io_data_cb();
+        unregister_frame_handler(_io_data_handler);
+        delete _io_data_handler;
+        _io_data_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data)
+{
+    if (!remote.is_valid_addr64b()) {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse;
+
+    AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
+    atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, uint32_t data)
+{
+    if (!remote.is_valid_addr64b()) {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data);
+    return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+}
+
+AtCmdFrame::AtCmdResp XBeeDM::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len)
+{
+    if (!remote.is_valid_addr64b()) {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data, len);
+    return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+}
+
+AtCmdFrame::AtCmdResp XBeeDM::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len)
+{
+
+    if (!remote.is_valid_addr64b()) {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
+    return send_at_cmd(&cmd_frame, data, len, RadioRemote, false);
+}
+
+static void get_dio_cmd(XBeeDM::IoLine line, char * const iocmd)
+{
+    if (line >= XBeeDM::DIO10_PWM0) {
+        iocmd[0] = 'P';
+        iocmd[1] = '0' + line - XBeeDM::DIO10_PWM0;
+    } else {
+        iocmd[0] = 'D';
+        iocmd[1] = '0' + line;
+    }
+    iocmd[2] = '\0';
+}
+
+RadioStatus XBeeDM::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3];
+
+    get_dio_cmd(line, iocmd);
+
+    cmdresp = set_param(remote, iocmd, (uint8_t)mode);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBeeDM::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3];
+
+    get_dio_cmd(line, iocmd);
+
+    uint32_t var32;
+    cmdresp = get_param(remote, iocmd, &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *mode = (IoMode)var32;
+
+    return Success;
+}
+
+RadioStatus XBeeDM::set_dio(const RemoteXBee& remote, IoLine line, DioVal val)
+{
+    return set_pin_config(remote, line, val == Low ? DigitalOutLow : DigitalOutHigh);
+}
+
+RadioStatus XBeeDM::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)
+{
+    return get_iosample(remote).get_dio(line, val);
+}
+
+RadioStatus XBeeDM::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)
+{
+    return get_iosample(remote).get_adc(line, val);
+}
+
+RadioStatus XBeeDM::set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3] = { 'M', '0', '\0' };
+
+    if (line != DIO10_PWM0 && line != DIO11_PWM1) {
+        return Failure;
+    }
+    if (line == DIO11_PWM1) {
+        iocmd[1] = '1';
+    }
+
+    uint16_t pwm_val = (uint16_t)(duty_cycle * DR_PWM_MAX_VAL / 100);
+
+    cmdresp = set_param(remote, iocmd, pwm_val);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+IOSampleDM XBeeDM::get_iosample(const RemoteXBee& remote)
+{
+    uint8_t io_sample[MAX_IO_SAMPLE_DM_LEN];
+    uint16_t len = sizeof io_sample;
+
+    RadioStatus resp = _get_iosample(remote, io_sample, &len);
+    if (resp != Success) {
+        digi_log(LogLevelError, "XBeeDM::get_iosample failed to get an IOSample\r\n");
+        len = 0;
+    }
+
+    return IOSampleDM(io_sample, len);
+}
+
+static uint16_t get_dio_pr_mask(XBeeDM::IoLine line)
+{
+    switch (line) {
+        case XBeeDM::DIO4:
+            return (1 << 0);
+        case XBeeDM::DIO3_AD3:
+            return (1 << 1);
+        case XBeeDM::DIO2_AD2:
+            return (1 << 2);
+        case XBeeDM::DIO1_AD1:
+            return (1 << 3);
+        case XBeeDM::DIO0_AD0:
+            return (1 << 4);
+        case XBeeDM::DIO6:
+            return (1 << 5);
+        case XBeeDM::DIO8:
+            return (1 << 6);
+        case XBeeDM::DIO5:
+            return (1 << 8);
+        case XBeeDM::DIO9:
+            return (1 << 9);
+        case XBeeDM::DIO12:
+            return (1 << 10);
+        case XBeeDM::DIO10_PWM0:
+            return (1 << 11);
+        case XBeeDM::DIO11_PWM1:
+            return (1 << 12);
+        case XBeeDM::DIO7:
+            return (1 << 13);
+        default:
+            return 0;
+    }
+}
+
+RadioStatus XBeeDM::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+    uint16_t pr;
+
+    cmdresp = get_param(remote, "PR", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    pr = var32;
+
+    const uint16_t dio_mask = get_dio_pr_mask(line);
+    if (dio_mask == 0) {
+        digi_log(LogLevelError, "XBeeDM::set_pin_pull_up: invalid pin %d\r\n", line);
+        return Failure;
+    }
+
+    if (enable) {
+        pr |= dio_mask;
+    } else {
+        pr &= ~dio_mask;
+    }
+
+    cmdresp = set_param(remote, "PR", pr);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    return Success;
+}
+
+static uint16_t get_dio_ic_mask(XBeeDM::IoLine line)
+{
+    if (line <= XBeeDM::DIO12) {
+        return (1 << line);
+    }
+    return 0;
+}
+
+RadioStatus XBeeDM::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable)
+{
+    if (line > DIO12) {
+        digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: pin not supported (%d)\r\n", line);
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+    uint16_t ic;
+
+    cmdresp = get_param(remote, "IC", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    ic = var32;
+
+    const uint16_t dio_mask = get_dio_ic_mask(line);
+    if (dio_mask == 0) {
+        digi_log(LogLevelError, "XBeeDM::enable_dio_change_detection: invalid pin %d\r\n", line);
+        return Failure;
+    }
+
+    if (enable) {
+        ic |= dio_mask;
+    } else {
+        ic &= ~dio_mask;
+    }
+
+    cmdresp = set_param(remote, "IC", ic);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBeeDM::config_poll_destination(const RemoteXBee& destination)
+{
+    uint32_t dh;
+    uint32_t dl;
+
+    if (destination.is_valid_addr64b()) {
+        const uint64_t dest64 = destination.get_addr64();
+        dh = (uint32_t)((dest64 >> 32) & 0xFFFFFFFF);
+        dl = (uint32_t)((dest64 & 0xFFFFFFFF));
+    } else {
+        digi_log(LogLevelError, "config_poll_destination: Invalid destination");
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("DH", dh);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    cmdresp = set_param("DL", dl);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "config_poll_destination: error %d:\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBeeDM/XBeeDM.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBeeDM/XBeeDM.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,378 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_DM_H_)
+#define __XBEE_DM_H_
+
+#include "XBee/XBee.h"
+#include "FrameHandlers/FH_AtCmdResp.h"
+#include "FrameHandlers/FH_RxPacketDM.h"
+#include "FrameHandlers/FH_IoDataSampleDM.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/** Class for XBee ZigBee modules, derived from XBee */
+class XBeeDM : public XBee
+{
+    public:
+
+        /**
+         * IoLine for XBeeDM Modules
+         */
+        enum IoLine {
+            DIO0_AD0   = 0,  /**< DIO0_AD0 pin */
+            DIO1_AD1   = 1,  /**< DIO1_AD1 pin */
+            DIO2_AD2   = 2,  /**< DIO2_AD2 pin */
+            DIO3_AD3   = 3,  /**< DIO3_AD3 pin */
+            DIO4       = 4,  /**< DIO4 pin */
+            DIO5       = 5,  /**< DIO5 pin */
+            DIO6       = 6,  /**< DIO6 pin */
+            DIO7       = 7,  /**< DIO7 pin */
+            DIO8       = 8,  /**< DIO8 pin */
+            DIO9       = 9,  /**< DIO9 pin */
+            DIO10_PWM0 = 10, /**< DIO10_PWM0 pin */
+            DIO11_PWM1 = 11, /**< DIO11_PWM1 pin */
+            DIO12      = 12  /**< DIO12 pin */
+        };
+
+        /** Class constructor
+         * @param tx the TX pin of the UART that will interface the XBee module
+         * @param rx the RX pin of the UART that will interface the XBee module
+         * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+         * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+         * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+         */
+        XBeeDM(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+        /** Class destructor */
+        virtual ~XBeeDM();
+
+        /** init-  initializes object
+         * This function must be called just after creating the object so it initializes internal data.
+         * @returns
+         *         Success if the module has been properly initialized and is ready to process data.
+         *         Failure otherwise.
+         */
+        RadioStatus init();
+
+        /** set_channel - sets the channel number
+         *
+         *  @param channel the channel in which the radio operates. Range is 0x0B - 0x1A for XBee and 0x0C - 0x17 for XBee-PRO.
+         *  The Center Frequency = 2.405 + (CH - 11) * 5 MHz
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_channel(uint8_t channel);
+
+        /** get_channel - gets the channel number
+         *
+         *  @param channel pointer where the channel value will be stored.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_channel(uint8_t * const channel);
+
+        /** set_network_id - sets the Network ID.
+         *
+         *  @param network_id the Network ID value that will be set on the radio
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+         RadioStatus set_network_id(uint16_t network_id);
+
+        /** get_network_id - gets the Network ID, as it was set by @ref set_network_id().
+         *
+         *  @param network_id pointer where the Network ID will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_network_id(uint16_t * const network_id);
+
+        /** register_node_discovery_cb - registers the callback function that will be called
+         * when the responses to the node discovery command arrive
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_node_discovery_cb(node_discovery_dm_cb_t function);
+
+        /** unregister_node_discovery_cb - removes the node discovery callback */
+        void unregister_node_discovery_cb();
+
+        /** register_receive_cb - registers the callback function that will be called
+         * when a data packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_receive_cb(receive_dm_cb_t function);
+
+        /** unregister_receive_cb - removes the rx packet callback */
+        void unregister_receive_cb();
+
+        /** register_io_sample_cb - registers the callback function that will be called
+         * when a IO Sample Data packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_io_sample_cb(io_data_cb_dm_t function);
+
+        /** unregister_io_sample_cb - removes the IO Sample Data reception callback */
+        void unregister_io_sample_cb();
+
+        /*********************** send_data member methods ************************/
+        /** send_data - sends data to a remote device
+         *
+         *  @param remote remote device
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** send_data - sends data to a remote device. This method uses
+         *                   the explicit addressing frame, allowing to use source and
+         *                   destination end points and cluster and profile IDs
+         *
+         *  @param remote remote device
+         *  @param source_ep source end point
+         *  @param dest_ep destination end point
+         *  @param cluster_id cluster ID
+         *  @param profile_id profile ID
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data(const RemoteXBee& remote, uint8_t source_ep,
+                                uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
+                                const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** send_data_to_coordinator - sends data to the ZigBee coordinator
+         *
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** get_remote_node_by_id - searches for a device in the network with the specified Node Identifier.
+         *
+         *  @param node_id node id of the device we are looking for
+         *  @returns a RemoteXBeeDM with the 16-bit and 64-bit address of the remote device whose node id matches with the parameter.
+         *  If node is not found, the returned object will have invalid addresses (RemoteXBeeDM::is_valid() will return false).
+         */
+        RemoteXBeeDM get_remote_node_by_id(const char * const node_id);
+
+        /* Allow using XBee::set_param() methods for local radio from this class */
+        using XBee::set_param;
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value (4 bytes) to be set.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data);
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value byte array (len bytes) to be set.
+         *  @param len number of bytes of the parameter value.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+        /* Allow using XBee::get_param() methods for local radio from this class */
+        using XBee::get_param;
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (4 bytes) will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data);
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param value will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len);
+
+        /************************* IO member methods **************************/
+        /** set_pin_config - configures a radio IO line
+         *
+         *  @param remote remote device
+         *  @param line IO line being configured
+         *  @param mode configuration mode for the selected line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode);
+
+        /** get_pin_config - gets the configuration of a radio IO line
+         *
+         *  @param remote remote device
+         *  @param line IO line being read to get its configuration
+         *  @param mode pointer where the configuration will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode);
+
+        /** set_dio - sets to low/high a DIO line
+         *
+         *  @param remote remote device
+         *  @param line DIO line being set
+         *  @param val value that will be set in the DIO line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_dio(const RemoteXBee& remote, IoLine line, DioVal val);
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param remote remote device
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val);
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param remote remote device
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from hte ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val);
+
+        /** get_iosample - retrieves an @ref IOSampleDM from a remote node. This object can be used to get the remote node's ADC and DIO values.
+         *
+         *  @param remote remote device
+         *  @returns IOSampleDM object with the remote node's DIO and ADC values.
+         */
+        IOSampleDM get_iosample(const RemoteXBee& remote);
+
+        /** set_pwm - sets the duty cycle of a PWM line
+         *
+         *  @param remote remote device
+         *  @param line PWM line being set
+         *  @param duty_cycle duty cycle that will be set in the PWM line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pwm(const RemoteXBee& remote, IoLine line, float duty_cycle);
+
+        /** set_pin_pull_up - enables or disables the internal pull-up resistor of a line
+         *
+         *  @param remote remote device
+         *  @param line line being configured for pull-up
+         *  @param enable whether to enable the internal pull-up resistor.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable);
+
+        /** enable_dio_change_detection - enables or disables the notification when a change is detected in a digital input line.
+         * In other words, it will force an IO Sample transmission when the DIO state changes. Only for DIO0 to DIO11.
+         *
+         *  @param remote remote device
+         *  @param line line being configured for pull-up
+         *  @param enable whether to enable the internal pull-up resistor.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable);
+
+        /** config_poll_destination - configures to which node poll messages will be sent once module awakes if configured as
+         *                            an Indirect Msg Poller (CE==0x4).
+         * Consult the module's reference manual for more information.
+         *
+         *  @param destination remote device where the poll messages will be sent
+         *  @returns the result of the data transfer
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus config_poll_destination(const RemoteXBee& destination);
+
+    protected:
+
+        /** Frame handler used for the node discovery. Registered when a callback function
+         * is registered */
+        FH_NodeDiscoveryDM  *_nd_handler;
+
+        /** Frame handler used for the rx packets. Automatically registered when a callback
+         *  function is registered */
+        FH_RxPacketDM  *_rx_pkt_handler;
+
+        /** Frame handler used for the IO Data Sample packets. Automatically registered when a callback
+         *  function is registered */
+        FH_IoDataSampeDM  *_io_data_handler;
+
+        /** Method called directly by the library when a modem status frame is received to
+         * update the internal status variables */
+        virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+        /* Allow using XBee::send_data() methods from this class */
+        using XBee::send_data;
+
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms);
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout);
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __XBEE_DM_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBeeLib.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBeeLib.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+/** @file
+ */
+
+#ifndef __XBEE_H_
+#define __XBEE_H_
+
+#define XB_LIBRARY_VERSION          0x01010200U
+#define XB_MAJOR_VERSION            ((XB_LIBRARY_VERSION >> 24) & 0xFFU)
+#define XB_MINOR_VERSION            ((XB_LIBRARY_VERSION >> 16) & 0xFFU)
+#define XB_PATCH_LEVEL              ((XB_LIBRARY_VERSION >> 8) & 0xFFU)
+#define XB_BUILD_ID                 (XB_LIBRARY_VERSION & 0xFFU)
+
+/**/
+#define XB_LIB_BANNER               "\r\n\r\n" "mbed Digi International Inc., XBeeLib v%d.%d.%d" "\r\n", \
+                                        XB_MAJOR_VERSION, XB_MINOR_VERSION, XB_PATCH_LEVEL
+
+#define ENABLE_LOGGING
+#define ENABLE_ASSERTIONS
+#define FRAME_BUFFER_SIZE           4
+#define MAX_FRAME_PAYLOAD_LEN       256
+
+#define SYNC_OPS_TIMEOUT_MS         2000
+
+#include "XBeeZB/XBeeZB.h"
+#include "IO/IOSampleZB.h"
+#include "XBee802/XBee802.h"
+#include "IO/IOSample802.h"
+#include "XBeeDM/XBeeDM.h"
+#include "IO/IOSampleDM.h"
+#include "XBee/Addresses.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+#endif /* __XBEE_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBeeZB/XBeeZB.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBeeZB/XBeeZB.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,650 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#include "XBeeZB.h"
+#include "IO/IOSampleZB.h"
+#include "Frames/ZigbeeFrames.h"
+
+using namespace XBeeLib;
+
+#define BROADCAST_RADIUS_USE_NH 0x00
+
+/* Class constructor */
+XBeeZB::XBeeZB(PinName tx, PinName rx, PinName reset, PinName rts, PinName cts, int baud) :
+         XBee(tx, rx, reset, rts, cts, baud), _nd_handler(NULL), _rx_pkt_handler(NULL), _io_data_handler(NULL)
+{
+}
+
+RadioStatus XBeeZB::init()
+{
+    RadioStatus retval = XBee::init();
+    uint16_t addr16;
+    RadioStatus error = get_network_address(&addr16);
+    if (error == Success) {
+        digi_log(LogLevelInfo, "ADDR16: %04x\r\n", addr16);
+    } else {
+        digi_log(LogLevelInfo, "ADDR16: UNKNOWN\r\n");
+    }
+
+    const RadioProtocol radioProtocol = get_radio_protocol();
+    if (radioProtocol != ZigBee) {
+        digi_log(LogLevelError, "Radio protocol does not match, needed a %d got a %d\r\n", ZigBee, radioProtocol);
+        retval = Failure;
+    }
+    assert(radioProtocol == ZigBee);
+
+    return retval;
+}
+
+/* Class destructor */
+XBeeZB::~XBeeZB()
+{
+    unregister_node_discovery_cb();
+    unregister_receive_cb();
+    unregister_io_sample_cb();
+}
+
+RadioStatus XBeeZB::set_channel_mask(uint16_t  chmask)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("SC", chmask);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBeeZB::get_channel_mask(uint16_t * const  chmask)
+{
+    if (chmask == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("SC", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *chmask = var32;
+    return Success;
+}
+
+RadioStatus XBeeZB::set_panid(uint64_t  panid)
+{
+    uint8_t panid_u8[8];
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    rmemcpy(panid_u8, (const uint8_t *) &panid, sizeof panid_u8);
+
+    cmdresp = set_param("ID", panid_u8, sizeof panid_u8);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBeeZB::get_operating_panid(uint64_t * const  opanid)
+{
+    if (opanid == NULL) {
+        return Failure;
+    }
+    uint8_t opanid_u8[8];
+    uint16_t len = sizeof opanid_u8;
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = get_param("OP", opanid_u8, &len);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    if (len != sizeof opanid_u8) {
+        digi_log(LogLevelError, "XBeeZB::get_operating_panid: Read %d bytes instead of %d for OP", len, sizeof opanid_u8);
+        return Failure;
+    }
+    rmemcpy((uint8_t *)opanid, opanid_u8, len);
+    return Success;
+}
+
+RadioStatus XBeeZB::get_configured_panid(uint64_t * const  panid)
+{
+    if (panid == NULL) {
+        return Failure;
+    }
+    uint8_t panid_u8[8];
+    uint16_t len = sizeof panid_u8;
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = get_param("ID", panid_u8, &len);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    if (len != sizeof panid_u8) {
+        digi_log(LogLevelError, "XBeeZB::get_configured_panid: Read %d bytes instead of %d for ID", len, sizeof panid_u8);
+        return Failure;
+    }
+    rmemcpy((uint8_t *)panid, panid_u8, len);
+    return Success;
+}
+
+RadioStatus XBeeZB::set_panid(const RemoteXBee& remote, uint64_t  panid)
+{
+    uint8_t panid_u8[8];
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    rmemcpy(panid_u8, (const uint8_t *) &panid, sizeof panid_u8);
+
+    cmdresp = set_param(remote, "ID", panid_u8, sizeof panid_u8);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    return Success;
+}
+
+RadioStatus XBeeZB::get_operating_panid(const RemoteXBee& remote, uint64_t * const  opanid)
+{
+    if (opanid == NULL) {
+        return Failure;
+    }
+    uint8_t opanid_u8[8];
+    uint16_t len = sizeof opanid_u8;
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = get_param(remote, "OP", opanid_u8, &len);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    if (len != sizeof opanid_u8) {
+        digi_log(LogLevelError, "XBeeZB::get_operating_panid: Read %d bytes instead of %d for OP", len, sizeof opanid_u8);
+        return Failure;
+    }
+    rmemcpy((uint8_t *)opanid, opanid_u8, len);
+    return Success;
+}
+
+RadioStatus XBeeZB::get_configured_panid(const RemoteXBee& remote, uint64_t * const  panid)
+{
+    if (panid == NULL) {
+        return Failure;
+    }
+    uint8_t panid_u8[8];
+    uint16_t len = sizeof panid_u8;
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = get_param(remote, "ID", panid_u8, &len);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    if (len != sizeof panid_u8) {
+        digi_log(LogLevelError, "XBeeZB::get_configured_panid: Read %d bytes instead of %d for ID", len, sizeof panid_u8);
+        return Failure;
+    }
+    rmemcpy((uint8_t *)panid, panid_u8, len);
+    return Success;
+}
+
+RadioStatus XBeeZB::get_network_address(uint16_t * const  addr16)
+{
+    if (addr16 == NULL) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    uint32_t var32;
+    cmdresp = get_param("MY", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *addr16 = var32;
+    return Success;
+}
+
+RadioStatus XBeeZB::get_node_discovery_timeout(uint16_t * const timeout_ms)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+
+    cmdresp = get_param("NT", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *timeout_ms = (uint16_t)var32;
+
+    /* No N? command available for this protocol. Add a fix 1s guard time */
+    *timeout_ms += 1000;
+
+    return Success;
+}
+
+RadioStatus XBeeZB::get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout)
+{
+    const RadioStatus status = get_node_discovery_timeout(timeout_ms);
+
+    *wait_for_complete_timeout = false;
+
+    return status;
+}
+
+RadioStatus XBeeZB::check_for_coordinator_at_start(bool enable)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("JV", (uint8_t)enable);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+RadioStatus XBeeZB::set_network_security_key(const uint8_t * const key, const uint16_t length)
+{
+    if (key == NULL || length == 0 || length > 16) {
+        return Failure;
+    }
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("NK", key, length);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+RadioStatus XBeeZB::set_encryption_options(const uint8_t options)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+
+    cmdresp = set_param("EO", options);
+    return cmdresp == AtCmdFrame::AtCmdRespOk ? Success : Failure;
+}
+
+void XBeeZB::radio_status_update(AtCmdFrame::ModemStatus modem_status)
+{
+    /* Update the radio status variables */
+    if (modem_status == AtCmdFrame::HwReset) {
+        _hw_reset_cnt++;
+    } else if (modem_status == AtCmdFrame::WdReset) {
+        _wd_reset_cnt++;
+    }
+
+    _modem_status = modem_status;
+
+    digi_log(LogLevelDebug, "\r\nUpdating radio status: %02x\r\n", modem_status);
+}
+
+TxStatus XBeeZB::send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr)
+{
+    if (!remote.is_valid_addr64b()) {
+        return TxStatusInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    TxFrameZB frame = TxFrameZB(remote64, remote16, BROADCAST_RADIUS_USE_NH,
+                                _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+TxStatus XBeeZB::send_data(const RemoteXBee& remote, uint8_t source_ep,
+                                uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
+                                const uint8_t *const data, uint16_t len, bool syncr)
+{
+    if (!remote.is_valid_addr64b()) {
+        return TxStatusInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    TxFrameZB frame = TxFrameZB(remote64, remote16, source_ep, dest_ep,
+                                cluster_id, profile_id, BROADCAST_RADIUS_USE_NH,
+                                _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+TxStatus XBeeZB::send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr)
+{
+    const uint64_t remaddr = ADDR64_COORDINATOR;
+
+    TxFrameZB frame = TxFrameZB(remaddr, ADDR16_UNKNOWN, BROADCAST_RADIUS_USE_NH, _tx_options, data, len);
+    if (syncr) {
+        return send_data(&frame);
+    } else {
+        frame.set_data(0, 0); /* Set frame id to 0 so there is no answer */
+        send_api_frame(&frame);
+        return TxStatusSuccess;
+    }
+}
+
+RemoteXBeeZB XBeeZB::get_remote_node_by_id(const char * const node_id)
+{
+    uint64_t addr64;
+    uint16_t addr16;
+    _get_remote_node_by_id(node_id, &addr64, &addr16);
+    return RemoteXBeeZB(addr64, addr16);
+}
+
+XBeeZB::AssocStatus XBeeZB::get_assoc_status(void)
+{
+    return (AssocStatus)get_AI();
+}
+
+bool XBeeZB::is_joined()
+{
+    return get_assoc_status() == Joined ? true : false;
+}
+
+void XBeeZB::register_node_discovery_cb(node_discovery_zb_cb_t function)
+{
+    if (_nd_handler == NULL) {
+        _nd_handler = new FH_NodeDiscoveryZB();
+        register_frame_handler(_nd_handler);
+    }
+    _nd_handler->register_node_discovery_cb(function);
+}
+
+void XBeeZB::unregister_node_discovery_cb()
+{
+    if (_nd_handler != NULL) {
+        _nd_handler->unregister_node_discovery_cb();
+        unregister_frame_handler(_nd_handler);
+        delete _nd_handler;
+        _nd_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+void XBeeZB::register_receive_cb(receive_zb_cb_t function)
+{
+    if (_rx_pkt_handler == NULL) {
+        _rx_pkt_handler = new FH_RxPacketZB();
+        register_frame_handler(_rx_pkt_handler);
+    }
+    _rx_pkt_handler->register_receive_cb(function);
+}
+
+void XBeeZB::unregister_receive_cb()
+{
+    if (_rx_pkt_handler != NULL) {
+        _rx_pkt_handler->unregister_receive_cb();
+        unregister_frame_handler(_rx_pkt_handler);
+        delete _rx_pkt_handler;
+        _rx_pkt_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+void XBeeZB::register_io_sample_cb(io_data_cb_zb_t function)
+{
+    if (_io_data_handler == NULL) {
+        _io_data_handler = new FH_IoDataSampeZB();
+        register_frame_handler(_io_data_handler);
+    }
+    _io_data_handler->register_io_data_cb(function);
+}
+
+void XBeeZB::unregister_io_sample_cb()
+{
+    if (_io_data_handler != NULL) {
+        _io_data_handler->unregister_io_data_cb();
+        unregister_frame_handler(_io_data_handler);
+        delete _io_data_handler;
+        _io_data_handler = NULL; /* as delete does not set to NULL */
+    }
+}
+
+AtCmdFrame::AtCmdResp XBeeZB::get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data)
+{
+    if (!remote.is_valid_addr64b()) {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+    uint16_t len = sizeof *data;
+    AtCmdFrame::AtCmdResp atCmdResponse;
+
+    AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
+    atCmdResponse = send_at_cmd(&cmd_frame, (uint8_t *)data, &len, RadioRemote);
+
+    if (atCmdResponse == AtCmdFrame::AtCmdRespOk && len > sizeof *data) {
+        atCmdResponse = AtCmdFrame::AtCmdRespLenMismatch;
+    }
+
+    return atCmdResponse;
+}
+
+AtCmdFrame::AtCmdResp XBeeZB::set_param(const RemoteXBee& remote, const char * const param, uint32_t data)
+{
+    if (!remote.is_valid_addr64b()) {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data);
+    return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+}
+
+AtCmdFrame::AtCmdResp XBeeZB::set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data, uint16_t len)
+{
+    if (!remote.is_valid_addr64b()) {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param, data, len);
+    return send_at_cmd(&cmd_frame, NULL, NULL, RadioRemote);
+}
+
+AtCmdFrame::AtCmdResp XBeeZB::get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len)
+{
+
+    if (!remote.is_valid_addr64b()) {
+        return AtCmdFrame::AtCmdRespInvalidAddr;
+    }
+
+    const uint64_t remote64 = remote.get_addr64();
+    const uint16_t remote16 = remote.get_addr16();
+
+    AtCmdFrame cmd_frame = AtCmdFrame(remote64, remote16, param);
+    return send_at_cmd(&cmd_frame, data, len, RadioRemote, false);
+}
+
+static void get_dio_cmd(XBeeZB::IoLine line, char * const iocmd)
+{
+    if (line >= XBeeZB::DIO10) {
+        iocmd[0] = 'P';
+        iocmd[1] = '0' + line - XBeeZB::DIO10;
+    } else {
+        iocmd[0] = 'D';
+        iocmd[1] = '0' + line;
+    }
+    iocmd[2] = '\0';
+}
+
+RadioStatus XBeeZB::set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3];
+
+    get_dio_cmd(line, iocmd);
+
+    cmdresp = set_param(remote, iocmd, (uint8_t)mode);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        digi_log(LogLevelError, "set_pin_config: set_param returned %d\r\n", cmdresp);
+        return Failure;
+    }
+
+    return Success;
+}
+
+RadioStatus XBeeZB::get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    char iocmd[3];
+
+    get_dio_cmd(line, iocmd);
+
+    uint32_t var32;
+    cmdresp = get_param(remote, iocmd, &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    *mode = (IoMode)var32;
+
+    return Success;
+}
+
+RadioStatus XBeeZB::set_dio(const RemoteXBee& remote, IoLine line, DioVal val)
+{
+    return set_pin_config(remote, line, val == Low ? DigitalOutLow : DigitalOutHigh);
+}
+
+RadioStatus XBeeZB::get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val)
+{
+    return get_iosample(remote).get_dio(line, val);
+}
+
+RadioStatus XBeeZB::get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val)
+{
+    return get_iosample(remote).get_adc(line, val);
+}
+
+IOSampleZB XBeeZB::get_iosample(const RemoteXBee& remote)
+{
+    uint8_t io_sample[MAX_IO_SAMPLE_ZB_LEN];
+    uint16_t len = sizeof io_sample;
+
+    RadioStatus resp = _get_iosample(remote, io_sample, &len);
+    if (resp != Success) {
+        digi_log(LogLevelError, "XBeeZB::get_iosample failed to get an IOSample\r\n");
+        len = 0;
+    }
+
+    return IOSampleZB(io_sample, len);
+}
+
+static uint16_t get_dio_pr_mask(XBeeZB::IoLine line)
+{
+    switch (line) {
+        case XBeeZB::DIO4:
+            return (1 << 0);
+        case XBeeZB::DIO3_AD3:
+            return (1 << 1);
+        case XBeeZB::DIO2_AD2:
+            return (1 << 2);
+        case XBeeZB::DIO1_AD1:
+            return (1 << 3);
+        case XBeeZB::DIO0_AD0:
+            return (1 << 4);
+        case XBeeZB::DIO6:
+            return (1 << 5);
+        case XBeeZB::DIO5:
+            return (1 << 8);
+        case XBeeZB::DIO12:
+            return (1 << 10);
+        case XBeeZB::DIO10:
+            return (1 << 11);
+        case XBeeZB::DIO11:
+            return (1 << 12);
+        case XBeeZB::DIO7:
+            return (1 << 13);
+        default:
+            return 0;
+    }
+}
+
+RadioStatus XBeeZB::set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable)
+{
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+    uint16_t pr;
+
+    cmdresp = get_param(remote, "PR", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    pr = var32;
+
+    const uint16_t dio_mask = get_dio_pr_mask(line);
+    if (dio_mask == 0) {
+        digi_log(LogLevelError, "XBeeZB::set_pin_pull_up: invalid pin %d\r\n", line);
+        return Failure;
+    }
+
+    if (enable) {
+        pr |= dio_mask;
+    } else {
+        pr &= ~dio_mask;
+    }
+
+    cmdresp = set_param(remote, "PR", pr);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    return Success;
+}
+
+static uint16_t get_dio_ic_mask(XBeeZB::IoLine line)
+{
+    if (line < XBeeZB::DIO12) {
+        return (1 << line);
+    }
+    return 0;
+}
+
+RadioStatus XBeeZB::enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable)
+{
+    if (line > DIO11) {
+        digi_log(LogLevelError, "XBeeZB::enable_dio_change_detection: pin not supported (%d)\r\n", line);
+        return Failure;
+    }
+
+    AtCmdFrame::AtCmdResp cmdresp;
+    uint32_t var32;
+    uint16_t ic;
+
+    cmdresp = get_param(remote, "IC", &var32);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+    ic = var32;
+
+    const uint16_t dio_mask = get_dio_ic_mask(line);
+    if (dio_mask == 0) {
+        digi_log(LogLevelError, "XBeeZB::enable_dio_change_detection: invalid pin %d\r\n", line);
+        return Failure;
+    }
+
+    if (enable) {
+        ic |= dio_mask;
+    } else {
+        ic &= ~dio_mask;
+    }
+
+    cmdresp = set_param(remote, "IC", ic);
+    if (cmdresp != AtCmdFrame::AtCmdRespOk) {
+        return Failure;
+    }
+
+    return Success;
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XBeeLib/XBeeZB/XBeeZB.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XBeeLib/XBeeZB/XBeeZB.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,474 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#if !defined(__XBEE_ZB_H_)
+#define __XBEE_ZB_H_
+
+#include "XBee/XBee.h"
+#include "FrameHandlers/FH_AtCmdResp.h"
+#include "FrameHandlers/FH_RxPacketZB.h"
+#include "FrameHandlers/FH_IoDataSampleZB.h"
+#include "RemoteXBee/RemoteXBee.h"
+
+namespace XBeeLib {
+
+/** Class for XBee ZigBee modules, derived from XBee */
+class XBeeZB : public XBee
+{
+    public:
+
+        /**
+         * IoLine for XBeeZB Modules
+         */
+        enum IoLine {
+            DIO0_AD0 = 0,  /**< DIO0_AD0 pin */
+            DIO1_AD1 = 1,  /**< DIO1_AD1 pin */
+            DIO2_AD2 = 2,  /**< DIO2_AD2 pin */
+            DIO3_AD3 = 3,  /**< DIO3_AD3 pin */
+            DIO4     = 4,  /**< DIO4 pin */
+            DIO5     = 5,  /**< DIO5 pin */
+            DIO6     = 6,  /**< DIO6 pin */
+            DIO7     = 7,  /**< DIO7 pin */
+            DIO10    = 10, /**< DIO10 pin */
+            DIO11    = 11, /**< DIO11 pin */
+            DIO12    = 12, /**< DIO12 pin */
+            SUPPLY_VOLTAGE = 7, /**< SUPPLY_VOLTAGE is not a real pin */
+        };
+
+        enum AssocStatus {
+            ErrorReading    = -1,       /**< Error occurred when reading parameter. */
+            Joined          = 0x00,     /**< Successfully formed or joined a network. (Coordinators form a network, routers and end devices join a network.) */
+            NoPANs          = 0x21,     /**< Scan found no PANs */
+            NoValidPAN      = 0x22,     /**< Scan found no valid PANs based on current SC and ID settings */
+            JoinNotAllowed  = 0x23,     /**< Valid Coordinator or Routers found, but they are not allowing joining (NJ expired). */
+            NoBeacons       = 0x24,     /**< No joinable beacons were found. */
+            Unexpected      = 0x25,     /**< Unexpected state, node should not be attempting to join at this time. */
+            JoinFailed      = 0x27,     /**< Node Joining attempt failed (typically due to incompatible security settings). */
+            CoordStartFail  = 0x2A,     /**< Coordinator start attempt failed */
+            CheckingCoord   = 0x2B,     /**< Checking for an existing coordinator. */
+            LeaveFail       = 0x2C,     /**< Attempt to leave the network failed. */
+            JoinNoResponse  = 0xAB,     /**< Attempted to join a device that did not respond. */
+            SecKeyUnsec     = 0xAC,     /**< Secure join error - network security key received unsecured. */
+            SecKeyNotRec    = 0xAD,     /**< Secure join error - network security key not received. */
+            SecBadKey       = 0xAF,     /**< Secure join error - joining device does not have the right preconfigured link key. */
+            Scanning        = 0xFF      /**< Scanning for a ZigBee network (routers and end devices). */
+        };
+
+        /** Class constructor
+         * @param tx the TX pin of the UART that will interface the XBee module
+         * @param rx the RX pin of the UART that will interface the XBee module
+         * @param reset the pin to which the XBee's reset line is attached to, use NC if not available
+         * @param rts the RTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param cts the CTS pin for the UART that will interface the XBee module, use NC if not available
+         * @param baud the baudrate for the UART that will interface the XBee module. Note that the module has to be already configured
+         * to this baud rate (ATBD parameter). By default it is configured to 9600 bps
+         */
+        XBeeZB(PinName tx, PinName rx, PinName reset = NC, PinName rts = NC, PinName cts = NC, int baud = 9600);
+
+        /** Class destructor */
+        virtual ~XBeeZB();
+
+        /** init-  initializes object
+         * This function must be called just after creating the object so it initializes internal data.
+         * @returns
+         *         Success if the module has been properly initialized and is ready to process data.
+         *         Failure otherwise.
+         */
+        RadioStatus init();
+
+        /** set_panid - sets the 64bit extended PAN ID.
+         *
+         *  @note on ZigBee devices, if set to 0, the coordinator will select a random PAN ID
+         *           and the routers will join any extended PAN ID
+         *  @param panid the PAN ID value that will be set on the radio
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_panid(uint64_t panid);
+
+        /** get_configured_panid - gets the configured PAN ID, as it was set by @ref set_panid().
+         *
+         *  @note on ZigBee devices, if set to 0, the coordinator will select a random PAN ID
+         *           and the routers will join any extended PAN ID
+         *  @param panid pointer where the configured PAN ID will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_configured_panid(uint64_t * const panid);
+
+        /** get_operating_panid - gets the operating 64bit extended PAN ID the module is running on. This is useful to determine the PAN ID when the ID parameter (@ref set_panid) is set to 0x00.
+         *
+         *  @param panid pointer where the operating PAN ID will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_operating_panid(uint64_t * const panid);
+
+        /** set_panid - sets the 64bit extended PAN ID.
+         *
+         *  @note on ZigBee devices, if set to 0, the coordinator will select a random PAN ID
+         *           and the routers will join any extended PAN ID
+         *  @param remote remote device
+         *  @param panid the PAN ID value that will be set on the radio
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_panid(const RemoteXBee& remote, uint64_t panid);
+
+        /** get_configured_panid - gets the configured PAN ID in a remote node, as it was set by @ref set_panid()
+         *
+         *  @note on ZigBee devices, if set to 0, the coordinator will select a random PAN ID
+         *           and the routers will join any extended PAN ID
+         *
+         *  @param remote remote device
+         *  @param panid pointer where the configured PAN ID will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_configured_panid(const RemoteXBee& remote, uint64_t * const panid);
+
+        /** get_operating_panid - gets the operating 64bit extended PAN ID in which a remote node is running on. This is useful to determine the PAN ID when the ID parameter (@ref set_panid) is set to 0x00.
+         *
+         *  @param remote remote device
+         *  @param panid pointer where the operating PAN ID will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_operating_panid(const RemoteXBee& remote, uint64_t * const panid);
+
+        /** set_channel_mask - sets the channel mask in which the module will scan for the PAN ID (if it is a router or end-device) or start the network (if it is a coordinator).
+         * It should be set to the minimum available set of channels of all nodes in the network. Refer to "SC" parameter in the product manual for more information.
+         *
+         *  @param chmask bit field list of channels to scan (router/end-devices) or to choose when starting a network (coordinator). Bit 0 is for channel 0x0B and bit 15 for channel 0x1A.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_channel_mask(uint16_t const chmask);
+
+        /** get_channel_mask - gets the channel mask in which the module will scan for the PAN ID (if it is a router or end-device) or start the network (if it is a coordinator).
+         *
+         *  @param chmask pointer to where the configured channel mask will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_channel_mask(uint16_t * const chmask);
+
+        /** get_network_address - gets the 16bit network address of the device
+         *
+         *  @param addr pointer where the device 16bit network address will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_network_address(uint16_t * const addr);
+
+        /** check_for_coordinator_at_start - (Routers only) If enabled, a router will verify the coordinator is on its operating channel when joining or coming up from a power cycle.
+         * If a coordinator is not detected, the router will leave its current channel and attempt to join a new PAN. If JV=0, the router will continue operating on its current channel even if a coordinator is not detected.
+         *
+         *  @param enable whether to enable this feature or not
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus check_for_coordinator_at_start(bool enable);
+
+        /** set_network_security_key - (Coordinator only) Set the 128-bit AES network encryption key. If set to 0 (default), the module will select a random network key.
+         *  It is not recommended to set the key programmatically, because it could be read through the raw serial port bits.
+         *  @param key pointer to the 128-bit AES key
+         *  @param length size of the buffer pointed by 'key'
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_network_security_key(const uint8_t * const key, const uint16_t length);
+
+#define XBEE_ZB_ENC_OPT_SEND_KEY_ON_JOIN    0x01
+#define XBEE_ZB_ENC_OPT_USE_TRUST_CENTER    0x02
+        /** set_encryption_options - Configure options for encryption. Unused option bits should be set to 0. Options include:
+         *  - XBEE_ZB_ENC_OPT_SEND_KEY_ON_JOIN - Send the security key unsecured over-the-air during joins
+         *  - XBEE_ZB_ENC_OPT_USE_TRUST_CENTER - Use trust center (coordinator only)
+         *  @param options bit mask with the encryption options
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_encryption_options(const uint8_t options);
+
+        /** register_node_discovery_cb - registers the callback function that will be called
+         * when the responses to the node discovery command arrive
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_node_discovery_cb(node_discovery_zb_cb_t function);
+
+        /** unregister_node_discovery_cb - removes the node discovery callback */
+        void unregister_node_discovery_cb();
+
+        /** register_receive_cb - registers the callback function that will be called
+         * when a data packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_receive_cb(receive_zb_cb_t function);
+
+        /** unregister_receive_cb - removes the rx packet callback */
+        void unregister_receive_cb();
+
+        /** register_io_sample_cb - registers the callback function that will be called
+         * when a IO Sample Data packet is received
+         *
+         *  @param function function pointer with the callback function
+         */
+        void register_io_sample_cb(io_data_cb_zb_t function);
+
+        /** unregister_io_sample_cb - removes the IO Sample Data reception callback */
+        void unregister_io_sample_cb();
+
+        /*********************** send_data member methods ************************/
+        /** send_data - sends data to a remote device
+         *
+         *  @param remote remote device
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        virtual TxStatus send_data(const RemoteXBee& remote, const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** send_data - sends data to a remote device. This method uses
+         *                   the explicit addressing frame, allowing to use source and
+         *                   destination end points and cluster and profile IDs
+         *
+         *  @param remote remote device
+         *  @param source_ep source end point
+         *  @param dest_ep destination end point
+         *  @param cluster_id cluster ID
+         *  @param profile_id profile ID
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data(const RemoteXBee& remote, uint8_t source_ep,
+                                uint8_t dest_ep, uint16_t cluster_id, uint16_t profile_id,
+                                const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** send_data_to_coordinator - sends data to the ZigBee coordinator
+         *
+         *  @param data pointer to the data that will be sent
+         *  @param len number of bytes that will be transmitted
+         *  @param syncr if true, method waits for the packet answer with the result of the operation
+         *  @returns the result of the data transfer
+         *     TxStatusSuccess if the operation was successful,
+         *     the error code otherwise
+         */
+        TxStatus send_data_to_coordinator(const uint8_t *const data, uint16_t len, bool syncr = true);
+
+        /** get_assoc_status - returns current network association status. This wraps AI parameter, for more information refer to moudle's Reference Manual.
+         *
+         *  @returns an AssocStatus with current network association status.
+         */
+        AssocStatus get_assoc_status(void);
+
+        /** is_joined - checks if the device is joined to ZigBee network
+         *  @returns true if joined, false otherwise
+         */
+        bool is_joined();
+
+        /** get_remote_node_by_id - searches for a device in the network with the specified Node Identifier.
+         *
+         *  @param node_id node id of the device we are looking for
+         *  @returns a RemoteXBeeZB with the 16-bit and 64-bit address of the remote device whose node id matches with the parameter.
+         *  If node is not found, the returned object will have invalid addresses (RemoteXBeeZB::is_valid() will return false).
+         */
+        RemoteXBeeZB get_remote_node_by_id(const char * const node_id);
+
+        /* Allow using XBee::set_param() methods for local radio from this class */
+        using XBee::set_param;
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value (4 bytes) to be set.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, uint32_t data);
+
+        /** set_param - sets a parameter in a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be set.
+         *  @param data the parameter value byte array (len bytes) to be set.
+         *  @param len number of bytes of the parameter value.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp set_param(const RemoteXBee& remote, const char * const param, const uint8_t * data = NULL, uint16_t len = 0);
+
+        /* Allow using XBee::get_param() methods for local radio from this class */
+        using XBee::get_param;
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (4 bytes) will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint32_t * const data);
+
+        /** get_param - gets a parameter from a remote radio by sending an AT command and waiting for the response.
+         *
+         *  @param remote remote device
+         *  @param param parameter to be get.
+         *  @param data pointer where the param value (n bytes) will be stored.
+         *  @param len pointer where the number of bytes of the param value will be stored.
+         *  @returns the command response status.
+         */
+        virtual AtCmdFrame::AtCmdResp get_param(const RemoteXBee& remote, const char * const param, uint8_t * const data, uint16_t * const len);
+
+        /************************* IO member methods **************************/
+        /** set_pin_config - configures a radio IO line
+         *
+         *  @param remote remote device
+         *  @param line IO line being configured
+         *  @param mode configuration mode for the selected line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pin_config(const RemoteXBee& remote, IoLine line, IoMode mode);
+
+        /** get_pin_config - gets the configuration of a radio IO line
+         *
+         *  @param remote remote device
+         *  @param line IO line being read to get its configuration
+         *  @param mode pointer where the configuration will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_pin_config(const RemoteXBee& remote, IoLine line, IoMode * const mode);
+
+        /** set_dio - sets to low/high a DIO line
+         *
+         *  @param remote remote device
+         *  @param line DIO line being set
+         *  @param val value that will be set in the DIO line
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_dio(const RemoteXBee& remote, IoLine line, DioVal val);
+
+        /** get_dio - read the value of a DIO configured as digital input
+         *
+         *  @param remote remote device
+         *  @param line DIO line being read
+         *  @param val pointer where the DIO value read will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_dio(const RemoteXBee& remote, IoLine line, DioVal * const val);
+
+        /** get_adc - read the value of the espcified ADC line
+         *
+         *  @param remote remote device
+         *  @param line ADC line being read
+         *  @param val pointer where the value read from hte ADC will be stored
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus get_adc(const RemoteXBee& remote, IoLine line, uint16_t * const val);
+
+        /** get_iosample - retrieves an @ref IOSampleZB from a remote node. This object can be used to get the remote node's ADC and DIO values.
+         *
+         *  @param remote remote device
+         *  @returns IOSampleZB object with the remote node's DIO and ADC values.
+         */
+        IOSampleZB get_iosample(const RemoteXBee& remote);
+
+        /** set_pin_pull_up - enables or disables the internal pull-up resistor of a line
+         *
+         *  @param remote remote device
+         *  @param line line being configured for pull-up
+         *  @param enable whether to enable the internal pull-up resistor.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus set_pin_pull_up(const RemoteXBee& remote, IoLine line, bool enable);
+
+        /** enable_dio_change_detection - enables or disables the notification when a change is detected in a digital input line.
+         * In other words, it will force an IO Sample transmission when the DIO state changes. Only for DIO0 to DIO11.
+         *
+         *  @param remote remote device
+         *  @param line line being configured for pull-up
+         *  @param enable whether to enable the internal pull-up resistor.
+         *  @returns
+         *     Success if the operation was successful,
+         *     Failure otherwise
+         */
+        RadioStatus enable_dio_change_detection(const RemoteXBee& remote, IoLine line, bool enable);
+
+    protected:
+
+        /** Frame handler used for the node discovery. Registered when a callback function
+         * is registered */
+        FH_NodeDiscoveryZB  *_nd_handler;
+
+        /** Frame handler used for the rx packets. Automatically registered when a callback
+         *  function is registered */
+        FH_RxPacketZB  *_rx_pkt_handler;
+
+        /** Frame handler used for the IO Data Sample packets. Automatically registered when a callback
+         *  function is registered */
+        FH_IoDataSampeZB  *_io_data_handler;
+
+        /** Method called directly by the library when a modem status frame is received to
+         * update the internal status variables */
+        virtual void radio_status_update(AtCmdFrame::ModemStatus modem_status);
+
+        /* Allow using XBee::send_data() methods from this class */
+        using XBee::send_data;
+
+        /** get_node_discovery_timeout - gets the node discovery timeout
+          *
+          *  @param timeout_ms pointer where the node discovery timeout value will be stored
+          *  @param wait_for_complete_timeout pointer where the function will store if the operator
+          *                                   has to wait for the complete nd timeout after issuing 
+          *                                   a directed nd request
+          *  @returns
+          *     Success if the operation was successful,
+          *     Failure otherwise
+          */
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms);
+        virtual RadioStatus get_node_discovery_timeout(uint16_t * const timeout_ms, bool * const wait_for_complete_timeout);
+};
+
+}   /* namespace XBeeLib */
+
+#endif /* __XBEE_ZB_H_ */
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XbeeMonitor.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XbeeMonitor.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,144 @@
+#include "XbeeMonitor.h"
+#include "XBeeLib.h"
+#include "Utils.h"
+#include "MQTTSManager.h"
+#include "config.h"
+#include "mbed.h"
+
+using namespace XBeeLib;
+
+#if defined(TARGET_NUCLEO_L476RG)
+XBee802 xbee(D8, D2, NC, NC, NC, 115200); // local xbee
+#else
+XBee802 xbee(PTC15, PTC14, NC, NC, NC, 115200); // local xbee
+#endif
+
+extern float lastTemperature;
+
+static MemoryPool<RadioControlData, 4> mpool;
+static Queue<RadioControlData, 4> mqueue;
+
+void postRadioControl(RadioControlData &data)
+{
+    // push data to pool
+    RadioControlData *message = mpool.alloc();
+    // Simple copy
+    *message = data;
+    mqueue.put(message);    
+}
+
+// Callback functions
+static void io_data_cb(const RemoteXBee802 & remote, const IOSample802 & data)
+{
+    RadioStatus radioStatus;
+    const uint64_t remote_addr64 = remote.get_addr64();
+    
+    printf("\r\n============== Radio Callback ===================\r\n");
+    printf("\r\nRemote Radio Address :[%08x:%08x] %llu\r\n",
+          UINT64_HI32(remote_addr64),
+          UINT64_LO32(remote_addr64),
+          remote_addr64);
+
+    SensorData sdata;    
+   
+    // Get data from the digital input pin (DIO2) Sprinkler
+    DioVal dio2;
+    radioStatus = data.get_dio(XBee802::DIO2_AD2, &dio2);
+    if (radioStatus != Success) {
+        printf("Getting data from digital pin DIO2 FAILED\r\n");
+    } 
+
+
+    // Get data from the humidity pin
+    uint16_t humidity;
+    radioStatus = data.get_adc( XBee802::DIO3_AD3, &humidity);
+    if (radioStatus != Success) {
+        printf("Getting data from analog pin AD3 FAILED\r\n" );
+    } 
+    
+    // Get data from the temperature pin
+    uint16_t temperature;
+    radioStatus = data.get_adc( XBee802::DIO0_AD0, &temperature);
+    if (radioStatus != Success) {
+        printf("Temperature : (AD0 Not connected) FAILED\r\n");
+    } 
+    
+    // Get data from the luminace pin
+    uint16_t luminance;
+    radioStatus = data.get_adc( XBee802::DIO1_AD1, &luminance);
+    if (radioStatus != Success) {
+        printf("Getting data from analog pin AD1 FAILED\r\n");
+    }    
+    
+    sdata.deviceaddr  = remote_addr64;
+    sdata.temperature = lastTemperature;//temperature;
+    sdata.humidity = 1023 - humidity;
+    sdata.luminance = luminance;
+    // Assign the value to the sensor data
+    sdata.sprinkler = dio2;
+    
+    sdata.debug();        
+    postMQTTUpdate(sdata);
+    printf("\r\n=================================================\r\n");    
+}
+
+uint64_t getXbeeId()
+{
+    return xbee.get_addr64();   
+}
+
+int initXbeeMonitor()
+{
+  
+    /* Register the callback function */
+    xbee.register_io_sample_cb(&io_data_cb);
+    
+    /* Initialize the xbee device */
+    RadioStatus radioStatus = xbee.init();
+    if (radioStatus != Success)
+    {
+        printf("Radio initialization failed!\r\n");
+        return -1;
+    }
+    printf("XBee radios initialized ...\r\n");
+    
+    return 0;
+}
+
+int sendControlData(RadioControlData * data)
+{
+    RadioStatus radioStatus;
+    const RemoteXBee802 remoteDevice = RemoteXBee802(data->radioID);
+    if (data->sprinkler_pin == 0) // Turn on 
+    {
+        radioStatus = xbee.set_dio(remoteDevice, XBee802::DIO2_AD2, Low);
+    }else
+    {
+        radioStatus = xbee.set_dio(remoteDevice, XBee802::DIO2_AD2, High);
+    }
+    
+    return (radioStatus == Success);
+}
+
+void runXbeeMonitor()
+{
+    // Continually listen for arriving frames
+    while(true)
+    {
+        osEvent evt = mqueue.get(100);
+        if (evt.status == osEventMessage) 
+        {
+            // Unpack the message
+            RadioControlData * message = (RadioControlData *)evt.value.p;
+
+            // Send the packet, do not queue the call
+            sendControlData(message);
+            
+            // Free the message from mempool  after using
+            mpool.free(message);
+        }
+        
+        xbee.process_rx_frames();
+        // Thread::wait(100);
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b XbeeMonitor/XbeeMonitor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XbeeMonitor/XbeeMonitor.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,17 @@
+#ifndef _XBEE_MONITOR_H_
+#define _XBEE_MONITOR_H_
+
+#include <stdint.h>
+
+typedef struct 
+{
+    uint64_t radioID;
+    int sprinkler_pin;    
+} RadioControlData, *pRadioControlData;
+
+int initXbeeMonitor();
+uint64_t getXbeeId();
+void runXbeeMonitor();
+void postRadioControl(RadioControlData &);
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,70 @@
+/**
+ * Copyright (c) 2015 Digi International Inc.,
+ * All rights not expressly granted are reserved.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
+ * =======================================================================
+ */
+
+#ifndef __CONFIG_H_
+#define __CONFIG_H_
+
+/** Library configuration options */
+#define ENABLE_LOGGING
+#define ENABLE_ASSERTIONS
+#define FRAME_BUFFER_SIZE           4
+#define MAX_FRAME_PAYLOAD_LEN       256
+
+#define SYNC_OPS_TIMEOUT_MS         2000
+
+//#define DEBUG 1
+
+#ifdef DEBUG
+#define DBG(fmt, args...)    printf(fmt, ## args)
+#else
+#define DBG(fmt, args...)    /* Don't do anything in release builds */
+#endif
+
+//#define RADIO_TX                NC /* TODO: specify your setup's Serial TX pin connected to the XBee module DIN pin */
+//#define RADIO_RX                NC /* TODO: specify your setup's Serial RX pin connected to the XBee module DOUT pin */
+//#define RADIO_RTS               NC /* TODO: specify your setup's Serial RTS# pin connected to the XBee module RTS# pin */
+//#define RADIO_CTS               NC /* TODO: specify your setup's Serial CTS# pin connected to the XBee module CTS# pin */
+//#define RADIO_RESET             NC /* TODO: specify your setup's GPIO (output) connected to the XBee module's reset pin */
+//#define RADIO_SLEEP_REQ         NC /* TODO: specify your setup's GPIO (output) connected to the XBee module's SLEEP_RQ pin */
+//#define RADIO_ON_SLEEP          NC /* TODO: specify your setup's GPIO (input) connected to the XBee module's ON_SLEEP pin */
+//#define DEBUG_TX                NC /* TODO: specify your setup's Serial TX for debugging */
+//#define DEBUG_RX                NC /* TODO: specify your setup's Serial RX for debugging (optional) */
+#define RADIO_TX    D1
+#define RADIO_RX    D0
+#define RADIO_RESET D2
+#define DEBUG_TX    USBTX
+#define DEBUG_RX    USBRX
+
+#if !defined(RADIO_TX)
+    #error "Please define RADIO_TX pin"
+#endif
+
+#if !defined(RADIO_RX)
+    #error "Please define RADIO_RX pin"
+#endif
+
+#if !defined(RADIO_RESET)
+    #define RADIO_RESET             NC
+    #warning "RADIO_RESET not defined, defaulted to 'NC'"
+#endif
+
+#if defined(ENABLE_LOGGING)
+    #if !defined(DEBUG_TX)
+        #error "Please define DEBUG_TX"
+    #endif
+    #if !defined(DEBUG_RX)
+        #define DEBUG_RX                NC
+        #warning "DEBUG_RX not defined, defaulted to 'NC'"
+    #endif
+#endif
+
+#endif /* __CONFIG_H_ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/easy-connect/#5b9cb8cea4a11b0ab974c991b527c9b79fceae75
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/COMMIT_EDITMSG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/COMMIT_EDITMSG	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+Fix config download
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/FETCH_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/FETCH_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+5b9cb8cea4a11b0ab974c991b527c9b79fceae75		branch 'master' of https://github.com/ARMmbed/easy-connect
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/ORIG_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/ORIG_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+5b9cb8cea4a11b0ab974c991b527c9b79fceae75
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/config
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/config	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/easy-connect/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/description
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/description	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/hooks/applypatch-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/hooks/applypatch-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/hooks/commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/hooks/commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/hooks/post-update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/hooks/post-update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/hooks/pre-applypatch.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/hooks/pre-applypatch.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/hooks/pre-commit.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/hooks/pre-commit.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/hooks/pre-rebase.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/hooks/pre-rebase.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/hooks/prepare-commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/hooks/prepare-commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/hooks/update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/hooks/update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/index
Binary file easy-connect/.git/index has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/info/exclude
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/info/exclude	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,29 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
+atmel-rf-driver
+esp8266-driver
+mcr20a-rf-driver
+stm-spirit1-rf-driver
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/logs/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/logs/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+0000000000000000000000000000000000000000 5b9cb8cea4a11b0ab974c991b527c9b79fceae75 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036513 +0000	clone: from https://github.com/ARMmbed/easy-connect/
+5b9cb8cea4a11b0ab974c991b527c9b79fceae75 5b9cb8cea4a11b0ab974c991b527c9b79fceae75 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036513 +0000	checkout: moving from master to 5b9cb8cea4a11b0ab974c991b527c9b79fceae75
+5b9cb8cea4a11b0ab974c991b527c9b79fceae75 5b9cb8cea4a11b0ab974c991b527c9b79fceae75 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036513 +0000	checkout: moving from 5b9cb8cea4a11b0ab974c991b527c9b79fceae75 to master
+5b9cb8cea4a11b0ab974c991b527c9b79fceae75 d5ab2018616c4823c472bd3b71698eb00437383d www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491662352 +0000	commit: Fix config download
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/logs/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/logs/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+0000000000000000000000000000000000000000 5b9cb8cea4a11b0ab974c991b527c9b79fceae75 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036513 +0000	clone: from https://github.com/ARMmbed/easy-connect/
+5b9cb8cea4a11b0ab974c991b527c9b79fceae75 d5ab2018616c4823c472bd3b71698eb00437383d www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491662352 +0000	commit: Fix config download
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/logs/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/logs/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 5b9cb8cea4a11b0ab974c991b527c9b79fceae75 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036513 +0000	clone: from https://github.com/ARMmbed/easy-connect/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/08/9aa4faf066ddefa6bc0d01299ed49bd71084d1
Binary file easy-connect/.git/objects/08/9aa4faf066ddefa6bc0d01299ed49bd71084d1 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/0c/5ae545f0b266388e47de8bd706c786d485c072
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/0c/5ae545f0b266388e47de8bd706c786d485c072	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+x}MKÅ0E]÷W¸”Ö™&mxÈs¥AܹÌǤ¯Ð65M„÷ï-¨nï¹çÂuqY¦¢Ç›œ˜Arš\è¥'R†u/H¢ºÅN*GÄ^z1ˆj3‰×Á:‡Æ	ÁZJ¶ŠÛ‰65¡³­í)üö	‘m¯BÏGYö¨ôt%¼w†EkÑQ°•)ù¼Ç‘÷¼šÕ3œ®qÜ̊t.;§½Ycâm¾6ã”/Å6..@R¡j©îP VGz<̜àiÊÏÅÂéG;ÿ«U/œF†­Ì3$þ(¼g¸%).ðøö²Xö÷eó&smòÂsBíÓôÉ©ž'[Ußþ°æ`_ÙÜtó
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/0c/77697463c204aa53467a8b7c6286c31b973792
Binary file easy-connect/.git/objects/0c/77697463c204aa53467a8b7c6286c31b973792 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/0d/c426db510ec4f4c73bc14a75a9de181dae6868
Binary file easy-connect/.git/objects/0d/c426db510ec4f4c73bc14a75a9de181dae6868 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/0e/924fc9504c5fc4425adf30f7ad85a9fe0bf4fd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/0e/924fc9504c5fc4425adf30f7ad85a9fe0bf4fd	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xŽKj1D½Ö)zobômÀo²ñ*|€n}<c¬‘+9´È	LQ‹zPEÅVëÒA;µë[ÎÀÁX²(e2
+±”8±7.D“œõK/í°"ñ¤-¯Ðp"‡LN…TŠ*œ'¬GmãS"Ô’ Ÿ>·
.´Â¥­7n­ÂñNëý?œo•–Ç!¶ze½vèL°—ZJ1èxÙó»}q}exRsNðùý5iď´-¿cñ±°øo‡OÀ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/10/0eb67f6eeb7460798f95f873ddcae32a8351fb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/10/0eb67f6eeb7460798f95f873ddcae32a8351fb	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x¥Î1nÃ0@ÑÎ:÷"iÑRE‘P…µâ@ sþ¸COÐõ
¿ì½¯óßl¨‚*‰J\‰¢h
+ž“O3.‘V®þêÝC†Þ
Z.¥x¯‰Ys¤¦ùŠg„17ÊҖ<ç@ÍÉaßû€›j?à&?²{ø°_˜ì¾dô©ìýˆ#†À3{xGèN=WMÿqÇ£Š)ˆuÝ.£]êXŸ:¦mÍîSÙ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/15/3045d3887fcebc76e82914138658e28909cc27
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/15/3045d3887fcebc76e82914138658e28909cc27	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+xÎ½j1àÔzŠíF?¶´‚BúT.\ï­VŽÀw:tBòô¾@žÀÅßÀÀpŸç¦àcxÒ!ŠçÛR|”´ƒR̓ÿK¦9eD³ÒE!£+.‘­$È9U;	†	m¬"h)¤c2ô¥Ÿ}À¥ßꕖ+¼‹þÂË÷?ÓηMÜçWpGLx
+6{x¶ÎZ³·ûK•G÷æÜæõÖêœ×6š:ø *eȶÁ¶
+·Ú˜´õÅÜ	ÏUõ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/15/a293e5d2fffb7c16297ca58e726ad492b7bf34
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/15/a293e5d2fffb7c16297ca58e726ad492b7bf34	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xŽKn!D³æ½·5¢Èkïs€šqÆ20ÂØçŸÀ«R=©>©•²
PÁ|Œž3h”:HrÁ¨)kdҎŒµl½ñž#éˆdŒ;õ\XòZ/¬¼Em”sÈ•\ÖmƒN’›8zŒ¿ÖáLέ^–Ö
+|_©^_æt)´Ý¾R+? M@çä\„D1é|9ò»yñ»3£A¾ïa‚B÷Ùw%ß>ûú@•˜¡¤®€ûöÌ]ü'¾Y×
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/19/f6f960eb5519fcdb734d9a2e80410f647d04b5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/19/f6f960eb5519fcdb734d9a2e80410f647d04b5	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xuÍjÃ0„{öS,ôXÒJÖÏÊJzj	äÒ7XIkÇÁ²\E†öíë–ôØËÀ7Ì0LÈ)”¶wµ0C”Îø`:átˆI3iÔ((Fì”WBÛ›…
+Ï‚ã¶ÓÚY‡BIÅ:êH„Ix´¬	;ꕳyl•Ñ­5J	dBǽo£óìƒìmÇ6‹uCk=çGšá˜çÁçœ`¡ùrƒÃhœCNÏ ·}£]«„¢ÙÜíUå¯c}[=ìç\x™¾ÃXÏ«ÿ§Öœ¸Ë:MPøcåk…{)¡/ÛøËû)yŽO?²Ó¸½oš_È×RZ&¾ù[y¢Ê™息ߌnm
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/1b/01547f94c5552694a1930da954b2b7e8da1b0e
Binary file easy-connect/.git/objects/1b/01547f94c5552694a1930da954b2b7e8da1b0e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/1b/44cc5b9087fa700d29a7f1db48931b6300c35e
Binary file easy-connect/.git/objects/1b/44cc5b9087fa700d29a7f1db48931b6300c35e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/1d/8ffaa66c2d016d8c178199016ebe139856747e
Binary file easy-connect/.git/objects/1d/8ffaa66c2d016d8c178199016ebe139856747e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/22/0970a75eb458de640e38c7e828b2ba8df91609
Binary file easy-connect/.git/objects/22/0970a75eb458de640e38c7e828b2ba8df91609 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/24/d353af5e8cdcaccc11029ab3e8434a197429fa
Binary file easy-connect/.git/objects/24/d353af5e8cdcaccc11029ab3e8434a197429fa has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/25/b70564bc258cd7587f910879cb94645229170e
Binary file easy-connect/.git/objects/25/b70564bc258cd7587f910879cb94645229170e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/2f/55ecfeb118a73bf8bb60ab39e41056ea7c6d0f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/2f/55ecfeb118a73bf8bb60ab39e41056ea7c6d0f	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x½jÄ0„Sû)Ô]8ô·–!„ô©S»«]Ûp¶ƒO‡!OŽÔ)g˜o†áuž§f‚sOm1
+}í!Šev<°/Ž“MbÅ©ÄN©Ä¤Ýn²4Ó'L*¥jñ¹0¥=Rt–r…XüË+AŽž„Q´†Þ*¤âz„œЪVŽ j;¼·qÝÌçzÕ—Á¼Kû6/ûCžéo·væu~5.朓Í³uÖv‡{¼jò¾Dç­/¾ûmC.<šÓŒ·£ëd¦¥­æwy¿ìt¦6Þ©ûÏÜd~
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/30/1381a684281af9da36a455d57477d9a390a445
Binary file easy-connect/.git/objects/30/1381a684281af9da36a455d57477d9a390a445 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/32/57c0301a578f652c3b0657cbdcf0250cdc5e9c
Binary file easy-connect/.git/objects/32/57c0301a578f652c3b0657cbdcf0250cdc5e9c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/34/54ed73977760f2225f2b0b270ef1dbaf4803d7
Binary file easy-connect/.git/objects/34/54ed73977760f2225f2b0b270ef1dbaf4803d7 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/37/93db5dfd5198501ebc68ecc7f0504a349f94a5
Binary file easy-connect/.git/objects/37/93db5dfd5198501ebc68ecc7f0504a349f94a5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/39/5e3cd97d052c82c51bd63616ea0c4085f45b8b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/39/5e3cd97d052c82c51bd63616ea0c4085f45b8b	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,6 @@
+xuÍNÃ0„9ç)VâˆZìø/‘*Ô\8çâµw[‹¤1ŽCOO)âÈe¤o43҄iS¥ÕU-DÀÆFk4‰¤Q­	m/ƒŽIEƒdìµã&ûBÇ
+–ÑtºE
+ž8*+ظ^Zo:‡Ææ´aù–¡À„RvÞ)äÑ
+ª'-…±ä]°Qpã—z˜
+<QÎ<û7?L°™h]/´õe\‡i¼©»^K-ûnD+Dsvϧ*¸OõaAاByøÜîS=,øO­y¤²'ÈË0@¡÷…æ
+×Ò—i¤úuº½èߡ¦yÉÑW‚×¹Ž«9§’ª\^Œ>¨¬‡„¯ßlp+
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/3a/1c91cf64d117ae96314093920547c11ed4d383
Binary file easy-connect/.git/objects/3a/1c91cf64d117ae96314093920547c11ed4d383 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/3a/5abc3fe130697448aca19177aa3f16f7004c62
Binary file easy-connect/.git/objects/3a/5abc3fe130697448aca19177aa3f16f7004c62 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/3b/a9f999525e8f002c7cf5287ecae64a0aeec4e1
Binary file easy-connect/.git/objects/3b/a9f999525e8f002c7cf5287ecae64a0aeec4e1 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/3e/fe7f33ae0768cec61cd9d6548100ffb4410a72
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/3e/fe7f33ae0768cec61cd9d6548100ffb4410a72	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xKj1D³Ö)zoZÿBð6C®Ð’z>öHÆrÎï	øÙ¼‚U©•2wP.¼õ>£Š6h+³£@˜=+3x̚"&Ù¨P¬´q퐳2–MDë˜DÉÁ³ŽQ« q—3yÊIУOmƒ3U8·:ÆÖ
+|^©^_pÍË{jå¤ñ28tA¢ØÛ}eçÿúâB7†ïŸ_süK÷V¸Os¡O´®pŸÚcɐ9-û3ñÄXVÞ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/42/4ae3367662881a6b866594e66388dfbe52d0bb
Binary file easy-connect/.git/objects/42/4ae3367662881a6b866594e66388dfbe52d0bb has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/43/f40bcc5c52a70f4103a1bacd35f7174fdac8f7
Binary file easy-connect/.git/objects/43/f40bcc5c52a70f4103a1bacd35f7174fdac8f7 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/45/cfc786f2e75ef5309c2854805d6d2ce80099a8
Binary file easy-connect/.git/objects/45/cfc786f2e75ef5309c2854805d6d2ce80099a8 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/49/1a3bac7f0f38ea74c31da2aa2526caee85b279
Binary file easy-connect/.git/objects/49/1a3bac7f0f38ea74c31da2aa2526caee85b279 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/4a/b5b17c065d256e2debf9d2e3b637e87d70026e
Binary file easy-connect/.git/objects/4a/b5b17c065d256e2debf9d2e3b637e87d70026e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/4f/9a5e30a4f3874754a919746b617c053e8b4d92
Binary file easy-connect/.git/objects/4f/9a5e30a4f3874754a919746b617c053e8b4d92 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/4f/c50217275c7fba4d8fd73bce2c8b3ea0b361a3
Binary file easy-connect/.git/objects/4f/c50217275c7fba4d8fd73bce2c8b3ea0b361a3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/53/8e08c93dcc43b769d6a726f9072ace0aeb8bd4
Binary file easy-connect/.git/objects/53/8e08c93dcc43b769d6a726f9072ace0aeb8bd4 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/53/8fa834d808c87aafad8d80127152d3239a31dc
Binary file easy-connect/.git/objects/53/8fa834d808c87aafad8d80127152d3239a31dc has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/57/4b1793787ca4916a0c612b5ddef4e15489288a
Binary file easy-connect/.git/objects/57/4b1793787ca4916a0c612b5ddef4e15489288a has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/57/cea69ad98a66e7ef1417aea9335b2f00d71116
Binary file easy-connect/.git/objects/57/cea69ad98a66e7ef1417aea9335b2f00d71116 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/59/3b4d82760aae5f2917c5ffbcb402dff05271e5
Binary file easy-connect/.git/objects/59/3b4d82760aae5f2917c5ffbcb402dff05271e5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/5a/733bd2750342660d9021bfc9b3583ca8c62668
Binary file easy-connect/.git/objects/5a/733bd2750342660d9021bfc9b3583ca8c62668 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/5b/9cb8cea4a11b0ab974c991b527c9b79fceae75
Binary file easy-connect/.git/objects/5b/9cb8cea4a11b0ab974c991b527c9b79fceae75 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/5d/3d0e811967c9c6f33a710aa076e8b8b77defcf
Binary file easy-connect/.git/objects/5d/3d0e811967c9c6f33a710aa076e8b8b77defcf has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/5e/4887274fd6836189c01b70e285f277611f5f3d
Binary file easy-connect/.git/objects/5e/4887274fd6836189c01b70e285f277611f5f3d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/61/9c1c17362546bdf3353a800c11f233a7b72667
Binary file easy-connect/.git/objects/61/9c1c17362546bdf3353a800c11f233a7b72667 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/63/bda56ba519dff1fbe82947624c4c4bada62a9d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/63/bda56ba519dff1fbe82947624c4c4bada62a9d	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xŽ;n1Sëì
\RŸ®]û”ÄuÖ°VÆZÉù­"'HùxƒÉ­ÖµY÷ÑwU¨£ ”Ä$V‘
+/„Î/J婸à-™§ìºup˜S¡à-y%"MiÉ1±›9˜ýÀ³‘ŸþÝv¸È—¶ÝRk>ï²ÝÿÆùVe}œr«_0Ù@;öHˆfÐQÙõ¿sm ¯ç<JŽe_‡¨ÊkøÌ+”M5
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/67/2acbfe9df9289ca9fb342ab410b8d5493c5b3a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/67/2acbfe9df9289ca9fb342ab410b8d5493c5b3a	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xŽAjÃ0E»Ö)f_#YcÉІ’%¡iéґǣ$PYÁV(ôôÕ¢'èêó><xœSº0­{(‹ˆëccñ±ÕâÓPŒ†œ¡‘më-r§na‘¹@§'n	#…ÑKˆˆ#MãIˆ;™„8NV…{¹ä>óW<‡ù;)?ðôý‡›±âËZ6œÓ´õÞ;cÑÀ#jDUßZY俾úXRà%Ãéxèßúw=Ô^÷Çþù°è±ÆÝ®3¤<­ê£TÙ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/67/d50bbba064b284ec7710e217f0f689c4ed1d78
Binary file easy-connect/.git/objects/67/d50bbba064b284ec7710e217f0f689c4ed1d78 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/67/db7cbdf804b235c8d3dc51ad5663de67de16ac
Binary file easy-connect/.git/objects/67/db7cbdf804b235c8d3dc51ad5663de67de16ac has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/68/ee82789079b8a48165e7e6e5066b5d1005eed3
Binary file easy-connect/.git/objects/68/ee82789079b8a48165e7e6e5066b5d1005eed3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/6e/09ffca24c3167f6f723c486d8f1081812cc556
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/6e/09ffca24c3167f6f723c486d8f1081812cc556	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xŽ»j1Së+no0ÒjW0&†ðv™ú>$[&Z™Eùÿlá/pwf`àp«µtlüèkJÀÉ1…À£x6&	¤5kæ3¡wۘċSO\Óҁ)Z›ÉDÔè­E7Š#odð&“#Á“…ýÞV˜q¹-7j­ÂáË㟷ŠåwÏ­ÁŒa°&ŒÚÁN­Õf·—=½Û«“\¿Îø)ßø^žê–ÒM„
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/6f/b5842becaefd360f57916a587b5a0ffdc45ff0
Binary file easy-connect/.git/objects/6f/b5842becaefd360f57916a587b5a0ffdc45ff0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/70/e399a0adb32a4e02d3f2056fe7d9ae31d57642
Binary file easy-connect/.git/objects/70/e399a0adb32a4e02d3f2056fe7d9ae31d57642 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/72/3542653307ea78efb2d8b91fc1f69e6d567574
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/72/3542653307ea78efb2d8b91fc1f69e6d567574	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xUANÃ0EY糧*N<Žm	¡¢JŠªîXNìiã&¶«Ôp"nÂÅ¥–ÿIÿiæ»c(ÐhuS&fðµQSVt^{B&Ô¨y¯­ì¤@ÕZ'}u¢‰Sg¸±ˆ¦5ZÈZ2zôDÚknI[ÚKÓVôQú<Á†Rbx
á<„ñû`9üZÑ—.Ǩg§B#,­¨…¨f:_Zøâ€MN‡.çx¯auˆÆýF©k¿Úq̟gž˜?׳àe{÷ö¸^@Hó¥gØ=Áöù½úáÉWš
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/73/2661d17a0fae8c97f0be83b806fee80a3747ea
Binary file easy-connect/.git/objects/73/2661d17a0fae8c97f0be83b806fee80a3747ea has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/7a/3ee2bd184ca8dc4d8c49a4522b41a7b89f8d66
Binary file easy-connect/.git/objects/7a/3ee2bd184ca8dc4d8c49a4522b41a7b89f8d66 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/81/9375ab99e86e6efad0037fb9cff4e6af7223a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/81/9375ab99e86e6efad0037fb9cff4e6af7223a8	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xÁ1ƒ0P枢skHbËtëX¸A‚
+¡çç½´lé©¡šJÙÏÑo.ӕÞã¶Òwè×#œ»:‘—óÕâ%fÇÁ,¢P?sn5À±GŽAºØ<nbŸ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/83/d2cd6dc0dd26e72cda79e89b289b29a66c7988
Binary file easy-connect/.git/objects/83/d2cd6dc0dd26e72cda79e89b289b29a66c7988 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/84/1ff5b5ec24ff027d27a6310cedfb6155556544
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/84/1ff5b5ec24ff027d27a6310cedfb6155556544	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+x•Ž»jÃ@E]ïWLo0;šÙ˜`»O¥€ëÙݑ-ˆ,#¯	äë£B?êr.8ež¦±AG~×Uș9sÞb¬(©°vJ"­jE§„æ)‹>HBJž‰×a&[*¥Šºäì(ÖàJ4òn÷yëü=Üäqƒ‹¶_8þlxÈ+ž^íPæéc@Gœì-ZkÖw­lú/ßù7ߜk…þëú縌
ÍÕÛJ%
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/86/e02b59351d6a9a0d7e24bf4f70d3ab0f4c5b20
Binary file easy-connect/.git/objects/86/e02b59351d6a9a0d7e24bf4f70d3ab0f4c5b20 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/89/60c27a28435820cca76958a2d83008022b0a3d
Binary file easy-connect/.git/objects/89/60c27a28435820cca76958a2d83008022b0a3d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/89/a75a6da3be993d2e5aa3c7d0319cd6fab45824
Binary file easy-connect/.git/objects/89/a75a6da3be993d2e5aa3c7d0319cd6fab45824 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/91/1f2ef98edaac9b09407b5c318591a923d1a784
Binary file easy-connect/.git/objects/91/1f2ef98edaac9b09407b5c318591a923d1a784 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/91/dc650f5ab8eaf00b5aca3385e5c9ede505cfd4
Binary file easy-connect/.git/objects/91/dc650f5ab8eaf00b5aca3385e5c9ede505cfd4 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/93/1a0a5600917e7417b35ac2e4f25943fb930b98
Binary file easy-connect/.git/objects/93/1a0a5600917e7417b35ac2e4f25943fb930b98 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/93/8f7f2f726027ab3fda9c83e6934898816a0579
Binary file easy-connect/.git/objects/93/8f7f2f726027ab3fda9c83e6934898816a0579 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/9d/233c35352ff61aa11ad4c818e901e0306934e0
Binary file easy-connect/.git/objects/9d/233c35352ff61aa11ad4c818e901e0306934e0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/9f/567936d77b8c2bbd7ea5098c468d8f3358d310
Binary file easy-connect/.git/objects/9f/567936d77b8c2bbd7ea5098c468d8f3358d310 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/a0/45def3617364e04e5654c512d863108ee699f0
Binary file easy-connect/.git/objects/a0/45def3617364e04e5654c512d863108ee699f0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/a2/483c9ba7dcaefc56b311488e530f376dfcc521
Binary file easy-connect/.git/objects/a2/483c9ba7dcaefc56b311488e530f376dfcc521 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/a8/31423401dcec34451fc60dd3cb52d4b6bc210e
Binary file easy-connect/.git/objects/a8/31423401dcec34451fc60dd3cb52d4b6bc210e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/a9/13964341394430cd3997c6f2950f93ba1d75c8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/a9/13964341394430cd3997c6f2950f93ba1d75c8	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xuŽËjÃ0E»öW̾PFòè!¤6ÐMÿ@²Æ¶B$!/ú÷õ¢ÛîÎ=páL5çÔAŽú¥7fAoR6²&äÑN†­´Aoãì„F7<}ãÒA¸YÏN#¥vžb0#Eç%[$³&‘‚üÖ×ÚàæÜjYB­w_îã´dŸoSÍGdµ";’„WˆÃn÷ÊÎ
®©l¥6~>~NKêëþ¹
Ÿ%§Z è+Ã÷åýüuù•J†
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/ab/96de702ba89e0ca322756726404ea6f96558e4
Binary file easy-connect/.git/objects/ab/96de702ba89e0ca322756726404ea6f96558e4 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/ae/123517e7c3743ef983ad88f9da3d7808930da2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/ae/123517e7c3743ef983ad88f9da3d7808930da2	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,7 @@
+x­VaoÚH½ÏþSP¯NÕ8„k¹”('lÔà ›4•ÚjåØk¼ãE»&UTå¿ß¬½8&@Jt±@ï¼7ofž¹Nù5´:ÿh²8‹h„ŒzŸ†}Ò¿p]§?!g„M°ŒnŒM–…é"¢Ð˜]ÓÈJ†áSÁ‚ø"Ÿ/róÒ?|}øå}Ý;6ªlÎäÌñ\gú:¬"WÃÁ8þø¨Ýé¨`»ŠŒÿŒœ_\{.qm€¿V#“3Ïéám¼Þ#‹atêت–éÇÑ®.¼ÏdèNoÐë;pru´Z5˜åTÄAH‹Ê0¥i5«~’ØÎéå'ãñ9 rnn> dÙñ¶F
+”±ISI_
+¬È—E,FÑhº›lËöÕ%Ë*2š¯hæ<¾	4O
+þ»á¬¶|¥ß5h7ȸ̃ðfûœ«Iqíê&̨|6x9UÏCž$‚Ñ\lZ“
+Á4\!Ï2æì–åwÈ-OxaÂ%Í,§4‚(‚7ø\̦jû“‹›}¶JiÝ邾œÃ_P;H‚ùÜúWòLI)¨•9Ö,‚Qg\P`þœ9ãٞÕ@Bº÷Ú”äÆÁL&?HAP)ˆÊ6½e!…~Iž‹iÔ¶ùŽ÷ÅñH϶=Ç÷¡ò`Þ=8æÌÒåra^òY÷Cçè½b ¦ùE!%b~kwZwãVÔêâ¯Ãî‡v·Ûný¨@˲ÝRÕªYo…¿#š¬yÍy
+)ŸœL©„ˆä»¿e5ëçuŸHÕ'<Ò:.Æ[Ë®¹C¥ë	ìâFì¶+v¥àñ˜Y§·¤¥b¥[s°±Ùøæ`aºm?àR²l
+WlÀÀÔ®µßÅ÷¬~ N«ëÉ:•Jƒ³¡2YV=Á}‘FY+-q9[¬Ñ÷‡ö6s÷|mÜÖ,7‰ý'"<Ãc*/SÿO=—~·“yRéðd5¥cãº|©}º#4Ä:U•ò=WÇwë¹rޝŠUªÞՖšk#„ûTŸó§z¶kEhl8Äz™Aïf¼HÓ»Çú”c}Ê´´”<·/â®$Бë,K‘×ëèUÁáÝcë¨-jIJáš/Dîåùy¹Çeè)P_‰¾”Þ²9Q†®´¶YûÿLiNôè\f
_¥×‘zg~[øp\½_^K]å2σ
­‰ýÛ¼øv}H½¥ƒÅi¹ÖŠ=6îÕß!5†€o¦MŒÿbw£
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/ae/9cc8adaa8fbb00061c04cd3c24055043c0489b
Binary file easy-connect/.git/objects/ae/9cc8adaa8fbb00061c04cd3c24055043c0489b has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/b8/9589db944f6c58d39808147f6749c0a96a0cc2
Binary file easy-connect/.git/objects/b8/9589db944f6c58d39808147f6749c0a96a0cc2 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/b9/34a4600d3166ffc8b7359c3d5478b07040701a
Binary file easy-connect/.git/objects/b9/34a4600d3166ffc8b7359c3d5478b07040701a has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/bb/44bf51b776018d2ae3ea4e2e3aa380eed15e31
Binary file easy-connect/.git/objects/bb/44bf51b776018d2ae3ea4e2e3aa380eed15e31 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/c2/b63f8793187dfd8e4264149540e21fccb12b9a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/c2/b63f8793187dfd8e4264149540e21fccb12b9a	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xŽ1!E­9Åô&f€YXclµ²²Ÿ…Aݘ
z~·ð–ÿ½¼äÇVÊ£ƒ±´é‹x#§É&A“l68¸,>«ÓàõâEj+«ÈÖ² wc”ètL!¹F˜óD¤‘½Qüî÷¶À™+œ[½M­ØÏ\çß8Þ
+?ž»ØÊ4yŽä`‹Q­t}Ùåß^.W‚Ú:œ.R_‘tIÈ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/c8/e294486870313e4d4daa7d7a0b76e4a79af386
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/c8/e294486870313e4d4daa7d7a0b76e4a79af386	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xŽÁj1E»ÎW¼}A’˜¼$ ¥¶*(´ÎÂåð2ó´ŠIdˆÿßY”.ºìòž{.ܾ¤t© }xª#3¨(•5îLo­Õ©0—k¢ŽŽý@“ÃâN#ç
+줎ä˞æZ;‹N£‘†	O­õl=êWaGv%Ÿc)	WÊןðzNt¹Íú’^@•öž¥’RLtzYù¿{qàL‰áãm½êÞ÷Ÿ›nÙ4ݺm¼FìšeÛ÷‡ÔòÇ8n7ÛßZ|{ÙY™
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/c9/352112681d09e7af0fc996552c7e7d1656edca
Binary file easy-connect/.git/objects/c9/352112681d09e7af0fc996552c7e7d1656edca has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/cb/933fb19cda0a733a64d6b71d271fb6bdaf9e6d
Binary file easy-connect/.git/objects/cb/933fb19cda0a733a64d6b71d271fb6bdaf9e6d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/ce/6cb88c4d7c1a85d8b00c0ccf9fba76ccf5d7d6
Binary file easy-connect/.git/objects/ce/6cb88c4d7c1a85d8b00c0ccf9fba76ccf5d7d6 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/ce/95fc4ab9f28413df4d1fa2e30c13d62c468d54
Binary file easy-connect/.git/objects/ce/95fc4ab9f28413df4d1fa2e30c13d62c468d54 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/ce/a47621759ff67ffa4b191809c364943f9db1f3
Binary file easy-connect/.git/objects/ce/a47621759ff67ffa4b191809c364943f9db1f3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/d1/85bc59084cd7da4ea47470add793b304569c3d
Binary file easy-connect/.git/objects/d1/85bc59084cd7da4ea47470add793b304569c3d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/d2/6ab233dacac50f47ece4493b16311d45e1bb58
Binary file easy-connect/.git/objects/d2/6ab233dacac50f47ece4493b16311d45e1bb58 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/d3/503403331d10000e1d061fe189c17f215d4e89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/d3/503403331d10000e1d061fe189c17f215d4e89	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,5 @@
+xA
+Â0D]ç·‚üŸ&M"ºu)^ M~µbI£ç·¨—ó†afBNi¨Ð YÔÂ½nc«c¤©ƒtF¦†c¨ïœ2½¸ûÂc¶s·ÈR;cf)É*EºoÙFO†l0^³ðzÉ~„CÏ]Î	6W?^¿bwN~¸­CN[ å°%IRÂ
+%¢˜é¼²ò¿yqä'—
+Ë}Œê±3X
+qº”·;Á§æçOkñä_î
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/d3/ab1936ef685518aeb35cf67e31465cffb25021
Binary file easy-connect/.git/objects/d3/ab1936ef685518aeb35cf67e31465cffb25021 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/d5/964336e2d7f627d0706902ad22acbf00bdcc50
Binary file easy-connect/.git/objects/d5/964336e2d7f627d0706902ad22acbf00bdcc50 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/d5/ab2018616c4823c472bd3b71698eb00437383d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/d5/ab2018616c4823c472bd3b71698eb00437383d	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+x}NINÄ0äìWô%Š=ÞZBhNü£ÝîAN3ß¸R—*©×u]:gzÑEÌ	­=»˜/§¨m˜}°È¡§‰Ù¨šl\BN‘…,i&J,#êäL`Lçӓà}ô×Úà¾s-O¿|]“䱶Û3h‹Ú{sq§Šžuipǐ©Ÿ­?uÍr—RwiÃûüEÛpæ÷¥HKe*ã?Ëêeù®Û¼Ü ×c+•²úöšR¥
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/dd/245e4b056ea2e4001e97e3bb329307e2da7adc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/dd/245e4b056ea2e4001e97e3bb329307e2da7adc	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xŽKj1³Ö)zo0jýB˜ìU ‹,C«Õ3¶‰¤0È÷÷r‚ìª
+<îµ^—žÆ*´‘å)S,L2³Ù"º”Ä[=ÛÊÌì
ªZ¥
Ѕ	%{ÔÂnvmft=ME0a!	)$E÷qé+œ©Á¹·%÷^áùFíö'¯K¥ë÷ž{}t§ GØi£µÚêörÈ÷êp¡¶|žŽ'Þ>ޓ	áë×Õ25N\
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/e2/c6d1de117c2917df101208c066337e50fde2e5
Binary file easy-connect/.git/objects/e2/c6d1de117c2917df101208c066337e50fde2e5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/e3/8c0cbab2fadf0f00c34eef2b4e593cdfa0f9f6
Binary file easy-connect/.git/objects/e3/8c0cbab2fadf0f00c34eef2b4e593cdfa0f9f6 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/e5/119192cfc8c687fec99ab9c9c9fe8dca954524
Binary file easy-connect/.git/objects/e5/119192cfc8c687fec99ab9c9c9fe8dca954524 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/e6/1ba698f31f71693451e91f68bb2035706695b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/objects/e6/1ba698f31f71693451e91f68bb2035706695b7	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xŽKnÃ0»Ö)¸/RècS6PA—¹)R©ƒH2¥ç¯9A—3À<¼ÔJÙx´o£«ÂD<³‹Éâ,~Fõ¢œWñCÔ%J´Ö£šºÖ‰×2»5	YŠ!N‚øè2#åUQ=ÇOëp¡
+—V¯ÜZÏÕÛÎ×BÛý#µònZpš1ÆÞ­³Ööx9ô¿½ù~–h½Ÿz>Iß~-ªú؏øRæc·T¦
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/e7/925a2477ce8f61e73235ff25725b55046840c9
Binary file easy-connect/.git/objects/e7/925a2477ce8f61e73235ff25725b55046840c9 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/e8/b993a80e25977e8b2184415f6e8da1718c7a5e
Binary file easy-connect/.git/objects/e8/b993a80e25977e8b2184415f6e8da1718c7a5e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/ef/6c33a08523753da6a63b2818aba5b7d7d46ca1
Binary file easy-connect/.git/objects/ef/6c33a08523753da6a63b2818aba5b7d7d46ca1 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/f5/6d654e0cc15325c291c707e0e13edbc1fb947f
Binary file easy-connect/.git/objects/f5/6d654e0cc15325c291c707e0e13edbc1fb947f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/f7/7df055e7907a3d9d3c4d77a578c0980d6b1466
Binary file easy-connect/.git/objects/f7/7df055e7907a3d9d3c4d77a578c0980d6b1466 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/fb/cc0ac33e944eb71feb80a1c40bf1baf5b2b61f
Binary file easy-connect/.git/objects/fb/cc0ac33e944eb71feb80a1c40bf1baf5b2b61f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/fb/eec5274508773d0f37c6893e794accf39e32f1
Binary file easy-connect/.git/objects/fb/eec5274508773d0f37c6893e794accf39e32f1 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/objects/fc/c6be1d2b7c64f0c2232d7559cd5e49bcb45171
Binary file easy-connect/.git/objects/fc/c6be1d2b7c64f0c2232d7559cd5e49bcb45171 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/packed-refs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/packed-refs	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,7 @@
+# pack-refs with: peeled 
+0e924fc9504c5fc4425adf30f7ad85a9fe0bf4fd refs/remotes/origin/esp8266-latest
+5b9cb8cea4a11b0ab974c991b527c9b79fceae75 refs/remotes/origin/master
+723542653307ea78efb2d8b91fc1f69e6d567574 refs/remotes/origin/mbed-client
+e61ba698f31f71693451e91f68bb2035706695b7 refs/remotes/origin/mbedos5.3.4
+0c77697463c204aa53467a8b7c6286c31b973792 refs/remotes/origin/odin
+d3503403331d10000e1d061fe189c17f215d4e89 refs/remotes/origin/revert-mts
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+d5ab2018616c4823c472bd3b71698eb00437383d
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.git/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.git/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.gitignore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.gitignore	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,8 @@
+atmel-rf-driver/*
+atmel-rf-driver
+esp8266-driver/*
+esp8266-driver
+mcr20a-rf-driver/*
+mcr20a-rf-driver
+stm-spirit1-rf-driver
+stm-spirit1-rf-driver/*
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.meta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.meta	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
diff -r 000000000000 -r a1734fe1ec4b easy-connect/.msub
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/.msub	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+atmel-rf-driver = https://github.com/ARMmbed/atmel-rf-driver/#110:57f22763f4d3649d4ac0b1df1f568f4cc45e491a
+esp8266-driver = https://github.com/ARMmbed/esp8266-driver/#13:4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb
+mcr20a-rf-driver = https://github.com/ARMmbed/mcr20a-rf-driver/#16:d8810e105d7d35315aa708ec51d821156cad45e9
+stm-spirit1-rf-driver = https://github.com/ARMmbed/stm-spirit1-rf-driver/#56:bbde15ee85d0c3b83864099c2659ad701a0325e7
diff -r 000000000000 -r a1734fe1ec4b easy-connect/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,102 @@
+# Easy Connect - Easily add all supported connectivity methods to your mbed OS project
+
+Often you want to give users of your application the choice to switch between connectivity methods. The `NetworkInterface` API makes this easy, but you'll still need a mechanism for the user to chooce the method, throw in some `#define`'s, etc. Easy Connect handles all this for you. Just declare the desired connectivity method in your `mbed_app.json` file, and call `easy_connect()` from your application.
+
+## Specifying connectivity method
+
+Add the following to your ``mbed_app.json`` file:
+
+```json
+{
+    "config": {
+        "network-interface":{
+            "help": "options are ETHERNET,WIFI_ESP8266,WIFI_ODIN,MESH_LOWPAN_ND,MESH_THREAD",
+            "value": "ETHERNET"
+        }
+    },
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["NANOSTACK", "LOWPAN_ROUTER", "COMMON_PAL"],
+            "mbed-mesh-api.6lowpan-nd-channel-page": 0,
+            "mbed-mesh-api.6lowpan-nd-channel": 12
+        }
+    }
+}
+```
+
+If you choose `WIFI_ESP8266` or `WIFI_ODIN`, you'll also need to add the WiFi SSID and password:
+
+```json
+    "config": {
+        "network-interface":{
+            "help": "options are ETHERNET,WIFI_ESP8266,WIFI_ODIN,MESH_LOWPAN_ND,MESH_THREAD",
+            "value": "WIFI_ESP8266"
+        },
+        "esp8266-tx": {
+            "help": "Pin used as TX (connects to ESP8266 RX)",
+            "value": "PTD3"
+        },
+        "esp8266-rx": {
+            "help": "Pin used as RX (connects to ESP8266 TX)",
+            "value": "PTD2"
+        },
+        "esp8266-debug": {
+            "value": true
+        },
+        "wifi-ssid": {
+            "value": "\"SSID\""
+        },
+        "wifi-password": {
+            "value": "\"Password\""
+        }
+    }
+```
+
+If you use `MESH_LOWPAN_ND` or `MESH_THREAD` you will need to specify your radio module:
+
+```json
+    "config": {
+        "network-interface":{
+            "help": "options are ETHERNET,WIFI_ESP8266,WIFI_ODIN,MESH_LOWPAN_ND,MESH_THREAD",
+            "value": "MESH_LOWPAN_ND"
+        },
+        "mesh_radio_type": {
+        	"help": "options are ATMEL, MCR20, SPIRIT1",
+        	"value": "ATMEL"
+        }
+    }
+```
+
+## Using Easy Connect from your application
+
+Easy Connect has just one function which will either return a `NetworkInterface`-pointer or `NULL`:
+
+```cpp
+#include "easy-connect.h"
+
+int main(int, char**) {
+    NetworkInterface* network = easy_connect(true); /* has 1 argument, enable_logging (pass in true to log to serial port) */
+    if (!network) {
+        printf("Connecting to the network failed... See serial output.\r\n");
+        return 1;
+    }
+
+    // Rest of your program
+}
+```
+## CR/LF in serial output
+
+If you want to avoid using `\r\n` in your printouts and just use normal C-style `\n` instead, please specify these to your `mbed_app.json`
+
+```json
+       "target_overrides": {
+        "*": {
+            "platform.stdio-baud-rate": 115200,
+            "platform.stdio-convert-newlines": true
+        }
+    }
+```
+
+## Extra defines
+
+If you'd like to use Easy Connect with mbed Client then you're in luck. Easy Connect automatically defines the `MBED_SERVER_ADDRESS` macro depending on your connectivity method (either IPv4 or IPv6 address). Use this address to connect to the right instance of mbed Device Connector.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/atmel-rf-driver/#57f22763f4d3649d4ac0b1df1f568f4cc45e491a
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/FETCH_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/FETCH_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+57f22763f4d3649d4ac0b1df1f568f4cc45e491a		branch 'master' of https://github.com/ARMmbed/atmel-rf-driver
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/ORIG_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/ORIG_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+57f22763f4d3649d4ac0b1df1f568f4cc45e491a
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/config
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/config	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/atmel-rf-driver/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/description
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/description	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/hooks/applypatch-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/hooks/applypatch-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/hooks/commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/hooks/commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/hooks/post-update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/hooks/post-update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/hooks/pre-applypatch.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/hooks/pre-applypatch.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/hooks/pre-commit.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/hooks/pre-commit.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/hooks/pre-rebase.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/hooks/pre-rebase.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/hooks/prepare-commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/hooks/prepare-commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/hooks/update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/hooks/update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/index
Binary file easy-connect/atmel-rf-driver/.git/index has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/info/exclude
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/info/exclude	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,25 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/logs/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/logs/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 57f22763f4d3649d4ac0b1df1f568f4cc45e491a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036520 +0000	clone: from https://github.com/ARMmbed/atmel-rf-driver/
+57f22763f4d3649d4ac0b1df1f568f4cc45e491a 57f22763f4d3649d4ac0b1df1f568f4cc45e491a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036520 +0000	checkout: moving from master to 57f22763f4d3649d4ac0b1df1f568f4cc45e491a
+57f22763f4d3649d4ac0b1df1f568f4cc45e491a 57f22763f4d3649d4ac0b1df1f568f4cc45e491a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036520 +0000	checkout: moving from 57f22763f4d3649d4ac0b1df1f568f4cc45e491a to master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/logs/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/logs/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 57f22763f4d3649d4ac0b1df1f568f4cc45e491a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036520 +0000	clone: from https://github.com/ARMmbed/atmel-rf-driver/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/logs/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/logs/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 57f22763f4d3649d4ac0b1df1f568f4cc45e491a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036520 +0000	clone: from https://github.com/ARMmbed/atmel-rf-driver/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/objects/pack/pack-cb9e3e95d81b3cf553d3174ae4ccbca538c03c13.idx
Binary file easy-connect/atmel-rf-driver/.git/objects/pack/pack-cb9e3e95d81b3cf553d3174ae4ccbca538c03c13.idx has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/objects/pack/pack-cb9e3e95d81b3cf553d3174ae4ccbca538c03c13.pack
Binary file easy-connect/atmel-rf-driver/.git/objects/pack/pack-cb9e3e95d81b3cf553d3174ae4ccbca538c03c13.pack has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/packed-refs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/packed-refs	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,84 @@
+# pack-refs with: peeled 
+a2d72a667b7ed3ac4e70ae743fd3c02a6e02afda refs/remotes/origin/alpha2-release
+d11d8a2564ef5f946c99f8003533caea13599d7b refs/remotes/origin/alpha3-release
+6a5156bea2dc8981a7efd86bcdf341dc398307e3 refs/remotes/origin/dep_update
+dc0c089e6782d66f3ef379736f3062afae708ef2 refs/remotes/origin/eui_chip_check
+1bf67eedce0f85a16376876670d525144d887892 refs/remotes/origin/eui_mac_chip_check
+b4357d79d7421a7e2bb629c7e22eff8f109054e7 refs/remotes/origin/feature_cmsis5
+f29a7aaefdba350fee57572a7d56bba66a87464e refs/remotes/origin/fhss_dev
+06296efdcc38e2719895af98e1f5ec911a1f00f8 refs/remotes/origin/mac_class_update
+a41e721bbb81e4e15b812909cd36005a000b03f9 refs/remotes/origin/maint_merge
+57f22763f4d3649d4ac0b1df1f568f4cc45e491a refs/remotes/origin/master
+b73c78b4f8ccbfa3295fd419173ce576ff9ddcf6 refs/remotes/origin/morpheus_dependency
+248d04582db6ba2db423cf8eb4e3535d5ef4cb72 refs/remotes/origin/ns_minar_take2
+a36e17a728732268b404fc727940257830e208ac refs/remotes/origin/retries
+a729202ba68a7537e4bdbea5f6d91d1522280ccd refs/remotes/origin/spi_timing_fix
+a82eda14afc4bd57c0574d0d58443d4aa4dddf31 refs/remotes/origin/thread_start_cond
+37e636728520d0d6d4e6caafff5e36962e5ceec0 refs/remotes/origin/update_mbed_dep
+0f7255a79b69c09469f4b3377513a39a9e6b25f5 refs/remotes/origin/v1.0-maint
+a7ff1a1ea2b3060139a345a09b72bdbf244cf4dc refs/remotes/origin/v2.1-maint
+453e4e2324d1d634dad87b1e107a1bc762c8ff2f refs/tags/beta-release
+a16a4ed6f6e8d5f2d009f25b6ab7c38affb5019c refs/tags/mbed-os-5.1.0-rc3
+a16a4ed6f6e8d5f2d009f25b6ab7c38affb5019c refs/tags/mbed-os-5.1.0-rc4
+a2d72a667b7ed3ac4e70ae743fd3c02a6e02afda refs/tags/mbedOS-alpha2
+4d2d328030c538a15cde01baa6c6e8f15ba7e0f4 refs/tags/mbedos-16.01-release
+4d2d328030c538a15cde01baa6c6e8f15ba7e0f4 refs/tags/mbedos-16.03-release
+4a7b2df89566412ab1f78c34acd66e114c210965 refs/tags/mbedos-2016q1-oob1
+4a7b2df89566412ab1f78c34acd66e114c210965 refs/tags/mbedos-2016q1-oob2
+4d2d328030c538a15cde01baa6c6e8f15ba7e0f4 refs/tags/mbedos-2016q1-oob3
+dcd91e50e2cef8a8944ec4acc30a9186fd250838 refs/tags/mbedos-release-15-11
+083d0d49ede86c2bf6417bf0a951ff37e497480c refs/tags/mbedos-techcon-oob2
+cf743c8ed7a61cd9217d010415b872629afa92ca refs/tags/v0.0.10
+d11d8a2564ef5f946c99f8003533caea13599d7b refs/tags/v0.0.11
+3b4d57bc558e26d357280c56908a2e0a211541dc refs/tags/v0.0.12
+7ee6cb249980d2b9f4e18744273ddd4da446e43b refs/tags/v0.0.13
+0ab8f39aebb09c3d57b1b612f562c5f2ea8e8217 refs/tags/v0.0.14
+^607843bac2c6677f69805fa45b169a9f4a89147c
+5ddc1deddcabe511d9e92d82ba2943d4ab272901 refs/tags/v0.0.15
+^f2fa5831d8d80deaeff177fffb628c06f5e3f4ce
+1b68214c528ef2fa41827292d0a8b919f530d4e6 refs/tags/v0.0.16
+^60256bb25d369570403ca27e752a6847b35b1424
+761c9ed3ee0e01563a1fa4783c03f3d4b40eb87b refs/tags/v0.0.18
+^f245f7ae3556436d017827d097904d85f8d7061c
+83e3d05272235be8e2fbd671ecd0489f05974dd0 refs/tags/v0.0.19
+^7d53d340711421f2ceffa43bbc036530c1cab6d3
+4b57c221f603ec186f2939d25c17481954468ca4 refs/tags/v0.0.20
+^ec465a0701cf62542dea77b6a4933adcb3275028
+66cb6974dd688bb99be556ff87305a99cf6ff584 refs/tags/v0.0.21
+^453e4e2324d1d634dad87b1e107a1bc762c8ff2f
+a8ed93388a3952da5c2a15d1bda443f092afb746 refs/tags/v0.0.22
+^a293db7a32e00d4e96e2c0af3692c047d2126037
+05edb4fd8c8503181aa07c2cad5ab262d748cb27 refs/tags/v0.0.23
+^d57710cdad5df1e55af0a1be179b98a6e59c4ebd
+844097fe55cfcc3658bed3452469137badca2798 refs/tags/v0.0.24
+^6269d5ea5e313b33f011ece34318ecac79d6a626
+876b12b8b4f2bbe9399345259b68259d33d59909 refs/tags/v0.0.25
+^4614966ca81530bc1fb376062af078c120f24241
+1874e9cf58468a41e25450dcffeb0e0ca08d9ca6 refs/tags/v0.0.8
+cc0a6379a081f4fddc1dc98e96f1bc7c4573115c refs/tags/v0.0.9
+9b2561ff19aa36d2176cae99d05e883ddabcb70a refs/tags/v1.0.0
+^083d0d49ede86c2bf6417bf0a951ff37e497480c
+303705bca8f05d221c1f2a44290d46147af52b6f refs/tags/v1.0.1
+^dcd91e50e2cef8a8944ec4acc30a9186fd250838
+755358c39f9484546ef1330932e63d430550c825 refs/tags/v1.0.2
+^efe496dcf42e2eed98f6d70c33f8d6bd7cfd430e
+eeb91783261991c06f0541a547ccea44afea7370 refs/tags/v1.0.3
+^0f7255a79b69c09469f4b3377513a39a9e6b25f5
+b17a8d9177c6985379176ffa41cb836632644162 refs/tags/v2.0.0
+^a7a63cfea3492f9693f1904cda264b99037fe475
+8a6fb2273f4b1cbd9b6b6cb7d4aa58774f06a0be refs/tags/v2.0.1
+^232e2508475626865679b5b4e43e21f19e2d2b88
+91c188f0c616ce47b5d1d832bed97aeb5cc02384 refs/tags/v2.0.2
+^4a7b2df89566412ab1f78c34acd66e114c210965
+ca1cad744508e1abc981b4dbd359401385b4da75 refs/tags/v2.0.3
+^41441226a87109a7405e4c8ba048311484a4b1c4
+d382c3d7e1a3656176bbf1d05180928cded5217d refs/tags/v2.1.0
+^4d2d328030c538a15cde01baa6c6e8f15ba7e0f4
+17393a1acefd268c75c0376aaa24c3ae6617f2f3 refs/tags/v2.1.1
+^a7ff1a1ea2b3060139a345a09b72bdbf244cf4dc
+c81741ac293409229df9c2343398016205797eae refs/tags/v3.0.0
+^50889f6c316d0b80520c781841f053b3a8aa8cd3
+b13508e3cd625d723a153d10626bdd3b342382f7 refs/tags/v3.0.1
+^3de9de8fa23b2a699cef382dd49e7f9a1dec6e5d
+80b2af683c02ca10f40917dcf60dc0e5973504d8 refs/tags/v3.0.2
+^160ce634ac16723c18bb2be61f1ed21c776252c9
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+57f22763f4d3649d4ac0b1df1f568f4cc45e491a
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.git/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.git/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.gitignore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.gitignore	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,6 @@
+*~
+*.swo
+*.swp
+build
+yotta_modules
+yotta_targets
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/.meta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/.meta	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/LICENSE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/LICENSE	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,7 @@
+# Example RF driver for Atmel 802.15.4 transceivers #
+
+Support for:
+ * AT86RF233
+ * AT86RF212B
+
+This driver is used with 6LoWPAN stack.
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/apache-2.0.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/apache-2.0.txt	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NANOSTACK_RF_PHY_ATMEL_H_
+#define NANOSTACK_RF_PHY_ATMEL_H_
+
+#include "NanostackRfPhy.h"
+#include "at24mac.h"
+#include "PinNames.h"
+
+// Arduino pin defaults for convenience
+#if !defined(ATMEL_SPI_MOSI)
+#define ATMEL_SPI_MOSI   D11
+#endif
+#if !defined(ATMEL_SPI_MISO)
+#define ATMEL_SPI_MISO   D12
+#endif
+#if !defined(ATMEL_SPI_SCLK)
+#define ATMEL_SPI_SCLK   D13
+#endif
+#if !defined(ATMEL_SPI_CS)
+#define ATMEL_SPI_CS     D10
+#endif
+#if !defined(ATMEL_SPI_RST)
+#define ATMEL_SPI_RST    D5
+#endif
+#if !defined(ATMEL_SPI_SLP)
+#define ATMEL_SPI_SLP    D7
+#endif
+#if !defined(ATMEL_SPI_IRQ)
+#define ATMEL_SPI_IRQ    D9
+#endif
+#if !defined(ATMEL_I2C_SDA)
+#define ATMEL_I2C_SDA    D14
+#endif
+#if !defined(ATMEL_I2C_SCL)
+#define ATMEL_I2C_SCL    D15
+#endif
+
+class RFBits;
+
+class NanostackRfPhyAtmel : public NanostackRfPhy {
+public:
+    NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso,
+            PinName spi_sclk, PinName spi_cs,  PinName spi_rst, PinName spi_slp, PinName spi_irq,
+            PinName i2c_sda, PinName i2c_scl);
+    ~NanostackRfPhyAtmel();
+    int8_t rf_register();
+    void rf_unregister();
+    void get_mac_address(uint8_t *mac);
+    void set_mac_address(uint8_t *mac);
+
+private:
+    AT24Mac _mac;
+    uint8_t _mac_addr[8];
+    RFBits *_rf;
+    bool _mac_set;
+
+    const PinName _spi_mosi;
+    const PinName _spi_miso;
+    const PinName _spi_sclk;
+    const PinName _spi_cs;
+    const PinName _spi_rst;
+    const PinName _spi_slp;
+    const PinName _spi_irq;
+};
+
+#endif /* NANOSTACK_RF_PHY_ATMEL_H_ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/module.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/module.json	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,17 @@
+{
+  "name": "atmel-rf-driver",
+  "version": "3.0.2",
+  "description": "RF driver for Atmel AT86RF233",
+  "keywords": [
+    "rf",
+    "driver"
+  ],
+  "author": "Seppo Takalo <seppo.takalo@arm.com>",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "nanostack-libservice": "^3.0.0",
+    "sal-stack-nanostack": "^5.0.0",
+    "mbed-drivers": "^1.0.0"
+  },
+  "targetDependencies": {}
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/source/AT86RFReg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/source/AT86RFReg.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AT86RFREG_H_
+#define AT86RFREG_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*AT86RF212 PHY Modes*/
+#define BPSK_20                     0x00
+#define BPSK_40                     0x04
+#define BPSK_40_ALT                 0x14
+#define OQPSK_SIN_RC_100            0x08
+#define OQPSK_SIN_RC_200            0x09
+#define OQPSK_RC_100                0x18
+#define OQPSK_RC_200                0x19
+#define OQPSK_SIN_250               0x0c
+#define OQPSK_SIN_500               0x0d
+#define OQPSK_SIN_500_ALT           0x0f
+#define OQPSK_RC_250                0x1c
+#define OQPSK_RC_500                0x1d
+#define OQPSK_RC_500_ALT            0x1f
+#define OQPSK_SIN_RC_400_SCR_ON     0x2A
+#define OQPSK_SIN_RC_400_SCR_OFF    0x0A
+#define OQPSK_RC_400_SCR_ON         0x3A
+#define OQPSK_RC_400_SCR_OFF        0x1A
+#define OQPSK_SIN_1000_SCR_ON       0x2E
+#define OQPSK_SIN_1000_SCR_OFF      0x0E
+#define OQPSK_RC_1000_SCR_ON        0x3E
+#define OQPSK_RC_1000_SCR_OFF       0x1E
+
+/*Supported transceivers*/
+#define PART_AT86RF231              0x03
+#define PART_AT86RF212              0x07
+#define PART_AT86RF233              0x0B
+#define VERSION_AT86RF212           0x01
+#define VERSION_AT86RF212B          0x03
+
+/*RF Configuration Registers*/
+#define TRX_STATUS                  0x01
+#define TRX_STATE                   0x02
+#define TRX_CTRL_0                  0x03
+#define TRX_CTRL_1                  0x04
+#define PHY_TX_PWR                  0x05
+#define PHY_RSSI                    0x06
+#define PHY_ED_LEVEL                0x07
+#define PHY_CC_CCA                  0x08
+#define RX_CTRL                     0x0A
+#define SFD_VALUE                   0x0B
+#define TRX_CTRL_2                  0x0C
+#define ANT_DIV                     0x0D
+#define IRQ_MASK                    0x0E
+#define IRQ_STATUS                  0x0F
+#define VREG_CTRL                   0x10
+#define BATMON                      0x11
+#define XOSC_CTRL                   0x12
+#define CC_CTRL_0                   0x13
+#define CC_CTRL_1                   0x14
+#define RX_SYN                      0x15
+#define TRX_RPC                     0x16
+#define RF_CTRL_0                   0x16
+#define XAH_CTRL_1                  0x17
+#define FTN_CTRL                    0x18
+#define PLL_CF                      0x1A
+#define PLL_DCU                     0x1B
+#define PART_NUM                    0x1C
+#define VERSION_NUM                 0x1D
+#define MAN_ID_0                    0x1E
+#define MAN_ID_1                    0x1F
+#define SHORT_ADDR_0                0x20
+#define SHORT_ADDR_1                0x21
+#define PAN_ID_0                    0x22
+#define PAN_ID_1                    0x23
+#define IEEE_ADDR_0                 0x24
+#define IEEE_ADDR_1                 0x25
+#define IEEE_ADDR_2                 0x26
+#define IEEE_ADDR_3                 0x27
+#define IEEE_ADDR_4                 0x28
+#define IEEE_ADDR_5                 0x29
+#define IEEE_ADDR_6                 0x2A
+#define IEEE_ADDR_7                 0x2B
+#define XAH_CTRL_0                  0x2C
+#define CSMA_SEED_0                 0x2D
+#define CSMA_SEED_1                 0x2E
+#define CSMA_BE                     0x2F
+
+/* CSMA_SEED_1*/
+#define AACK_FVN_MODE1              7
+#define AACK_FVN_MODE0              6
+#define AACK_SET_PD                 5
+#define AACK_DIS_ACK                4
+#define AACK_I_AM_COORD             3
+#define CSMA_SEED_12                2
+#define CSMA_SEED_11                1
+#define CSMA_SEED_10                0
+
+/*TRX_STATUS bits*/
+#define CCA_STATUS                  0x40
+#define CCA_DONE                    0x80
+
+/*PHY_CC_CCA bits*/
+#define CCA_REQUEST                 0x80
+#define CCA_MODE_1                  0x20
+#define CCA_MODE_3                  0x60
+
+/*IRQ_MASK bits*/
+#define RX_START                    0x04
+#define TRX_END                     0x08
+#define CCA_ED_DONE                 0x10
+#define AMI                         0x20
+#define TRX_UR                      0x40
+
+/*ANT_DIV bits*/
+#define ANT_DIV_EN                  0x08
+#define ANT_EXT_SW_EN               0x04
+#define ANT_CTRL_DEFAULT            0x03
+
+/*TRX_CTRL_1 bits*/
+#define PA_EXT_EN                   0x80
+
+/*FTN_CTRL bits*/
+#define FTN_START                   0x80
+
+/*PHY_RSSI bits*/
+#define CRC_VALID                   0x80
+
+/*RX_SYN bits*/
+#define RX_PDT_DIS                  0x80
+
+/*TRX_RPC bits */
+#define RX_RPC_CTRL                 0xC0
+#define RX_RPC_EN                   0x20
+#define PDT_RPC_EN                  0x10
+#define PLL_RPC_EN                  0x08
+#define XAH_TX_RPC_EN               0x04
+#define IPAN_RPC_EN                 0x02
+#define TRX_RPC_RSVD_1              0x01
+
+/*XAH_CTRL_1 bits*/
+#define AACK_PROM_MODE              0x02
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AT86RFREG_H_ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2479 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+#include "platform/arm_hal_interrupt.h"
+#include "nanostack/platform/arm_hal_phy.h"
+#include "ns_types.h"
+#include "NanostackRfPhyAtmel.h"
+#include "randLIB.h"
+#include "AT86RFReg.h"
+#include "nanostack/platform/arm_hal_phy.h"
+#include "toolchain.h"
+
+/*Worst case sensitivity*/
+#define RF_DEFAULT_SENSITIVITY -88
+/*Run calibration every 5 minutes*/
+#define RF_CALIBRATION_INTERVAL 6000000
+/*Wait ACK for 2.5ms*/
+#define RF_ACK_WAIT_DEFAULT_TIMEOUT 50
+/*Base CCA backoff (50us units) - substitutes for Inter-Frame Spacing*/
+#define RF_CCA_BASE_BACKOFF 13 /* 650us */
+/*CCA random backoff (50us units)*/
+#define RF_CCA_RANDOM_BACKOFF 51 /* 2550us */
+
+#define RF_MTU 127
+
+#define RF_PHY_MODE OQPSK_SIN_250
+
+/*Radio RX and TX state definitions*/
+#define RFF_ON 0x01
+#define RFF_RX 0x02
+#define RFF_TX 0x04
+#define RFF_CCA 0x08
+#define RFF_PROT 0x10
+
+typedef enum
+{
+    RF_MODE_NORMAL = 0,
+    RF_MODE_SNIFFER = 1,
+    RF_MODE_ED = 2
+}rf_mode_t;
+
+/*Atmel RF Part Type*/
+typedef enum
+{
+    ATMEL_UNKNOW_DEV = 0,
+    ATMEL_AT86RF212,
+    ATMEL_AT86RF231, // No longer supported (doesn't give ED+status on frame read)
+    ATMEL_AT86RF233
+}rf_trx_part_e;
+
+/*Atmel RF states*/
+typedef enum
+{
+    NOP = 0x00,
+    BUSY_RX = 0x01,
+    RF_TX_START = 0x02,
+    FORCE_TRX_OFF = 0x03,
+    FORCE_PLL_ON = 0x04,
+    RX_ON = 0x06,
+    TRX_OFF = 0x08,
+    PLL_ON = 0x09,
+    BUSY_RX_AACK = 0x11,
+    SLEEP = 0x0F,
+    RX_AACK_ON = 0x16,
+    TX_ARET_ON = 0x19
+}rf_trx_states_t;
+
+static const uint8_t *rf_tx_data; // Points to Nanostack's buffer
+static uint8_t rf_tx_length;
+/*ACK wait duration changes depending on data rate*/
+static uint16_t rf_ack_wait_duration = RF_ACK_WAIT_DEFAULT_TIMEOUT;
+
+static int8_t rf_sensitivity = RF_DEFAULT_SENSITIVITY;
+static rf_mode_t rf_mode = RF_MODE_NORMAL;
+static uint8_t radio_tx_power = 0x00;   // Default to +4dBm
+static uint8_t rf_phy_channel = 12;
+static uint8_t rf_tuned = 1;
+static uint8_t rf_use_antenna_diversity = 0;
+static int16_t expected_ack_sequence = -1;
+static uint8_t rf_rx_mode = 0;
+static uint8_t rf_flags = 0;
+static int8_t rf_radio_driver_id = -1;
+static phy_device_driver_s device_driver;
+static uint8_t mac_tx_handle = 0;
+
+/* Channel configurations for 2.4 and sub-GHz */
+static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK};
+static const phy_rf_channel_configuration_s phy_subghz = {868300000U, 2000000U, 250000U, 11U, M_OQPSK};
+
+static const phy_device_channel_page_s phy_channel_pages[] = {
+        { CHANNEL_PAGE_0, &phy_24ghz},
+        { CHANNEL_PAGE_2, &phy_subghz},
+        { CHANNEL_PAGE_0, NULL}
+};
+
+/**
+ *  RF output power write
+ *
+ * \brief TX power has to be set before network start.
+ *
+ * \param power
+ *              AT86RF233
+ *              0 = 4 dBm
+ *              1 = 3.7 dBm
+ *              2 = 3.4 dBm
+ *              3 = 3 dBm
+ *              4 = 2.5 dBm
+ *              5 = 2 dBm
+ *              6 = 1 dBm
+ *              7 = 0 dBm
+ *              8 = -1 dBm
+ *              9 = -2 dBm
+ *              10 = -3 dBm
+ *              11 = -4 dBm
+ *              12 = -6 dBm
+ *              13 = -8 dBm
+ *              14 = -12 dBm
+ *              15 = -17 dBm
+ *
+ *              AT86RF212B
+ *              See datasheet for TX power settings
+ *
+ * \return 0, Supported Value
+ * \return -1, Not Supported Value
+ */
+static int8_t rf_tx_power_set(uint8_t power);
+static rf_trx_part_e rf_radio_type_read(void);
+static void rf_ack_wait_timer_start(uint16_t slots);
+static void rf_ack_wait_timer_stop(void);
+static void rf_handle_cca_ed_done(void);
+static void rf_handle_tx_end(void);
+static void rf_handle_rx_end(void);
+static void rf_on(void);
+static void rf_receive(void);
+static void rf_poll_trx_state_change(rf_trx_states_t trx_state);
+static void rf_init(void);
+static int8_t rf_device_register(const uint8_t *mac_addr);
+static void rf_device_unregister(void);
+static void rf_enable_static_frame_buffer_protection(void);
+static void rf_disable_static_frame_buffer_protection(void);
+static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol );
+static void rf_cca_abort(void);
+static void rf_calibration_cb(void);
+static void rf_init_phy_mode(void);
+static void rf_ack_wait_timer_interrupt(void);
+static void rf_calibration_timer_interrupt(void);
+static void rf_calibration_timer_start(uint32_t slots);
+static void rf_cca_timer_interrupt(void);
+static void rf_cca_timer_start(uint32_t slots);
+static uint8_t rf_scale_lqi(int8_t rssi);
+
+static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
+static int8_t rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr);
+static int8_t rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr);
+
+static void rf_if_cca_timer_start(uint32_t slots);
+static void rf_if_enable_promiscuous_mode(void);
+static void rf_if_lock(void);
+static void rf_if_unlock(void);
+static uint8_t rf_if_read_rnd(void);
+static void rf_if_calibration_timer_start(uint32_t slots);
+static void rf_if_interrupt_handler(void);
+static void rf_if_ack_wait_timer_start(uint16_t slots);
+static void rf_if_ack_wait_timer_stop(void);
+static void rf_if_ack_pending_ctrl(uint8_t state);
+static void rf_if_calibration(void);
+static uint8_t rf_if_read_register(uint8_t addr);
+static void rf_if_set_bit(uint8_t addr, uint8_t bit, uint8_t bit_mask);
+static void rf_if_clear_bit(uint8_t addr, uint8_t bit);
+static void rf_if_write_register(uint8_t addr, uint8_t data);
+static void rf_if_reset_radio(void);
+static void rf_if_enable_ant_div(void);
+static void rf_if_disable_ant_div(void);
+static void rf_if_enable_slptr(void);
+static void rf_if_disable_slptr(void);
+static void rf_if_write_antenna_diversity_settings(void);
+static void rf_if_write_set_tx_power_register(uint8_t value);
+static void rf_if_write_rf_settings(void);
+static uint8_t rf_if_check_cca(void);
+static uint8_t rf_if_read_trx_state(void);
+static uint16_t rf_if_read_packet(uint8_t data[RF_MTU], uint8_t *lqi_out, uint8_t *ed_out, bool *crc_good);
+static void rf_if_write_short_addr_registers(uint8_t *short_address);
+static uint8_t rf_if_last_acked_pending(void);
+static void rf_if_write_pan_id_registers(uint8_t *pan_id);
+static void rf_if_write_ieee_addr_registers(uint8_t *address);
+static void rf_if_write_frame_buffer(const uint8_t *ptr, uint8_t length);
+static void rf_if_change_trx_state(rf_trx_states_t trx_state);
+static void rf_if_enable_tx_end_interrupt(void);
+static void rf_if_enable_rx_end_interrupt(void);
+static void rf_if_enable_cca_ed_done_interrupt(void);
+static void rf_if_start_cca_process(void);
+static int8_t rf_if_scale_rssi(uint8_t ed_level);
+static void rf_if_set_channel_register(uint8_t channel);
+static void rf_if_enable_promiscuous_mode(void);
+static void rf_if_disable_promiscuous_mode(void);
+static uint8_t rf_if_read_part_num(void);
+static void rf_if_enable_irq(void);
+static void rf_if_disable_irq(void);
+
+#ifdef MBED_CONF_RTOS_PRESENT
+#include "mbed.h"
+#include "rtos.h"
+
+static void rf_if_irq_task_process_irq();
+
+#define SIG_RADIO       1
+#define SIG_TIMER_ACK   2
+#define SIG_TIMER_CAL   4
+#define SIG_TIMER_CCA   8
+
+#define SIG_TIMERS (SIG_TIMER_ACK|SIG_TIMER_CAL|SIG_TIMER_CCA)
+#define SIG_ALL (SIG_RADIO|SIG_TIMERS)
+#endif
+
+// HW pins to RF chip
+#define SPI_SPEED 7500000
+
+class UnlockedSPI : public SPI {
+public:
+    UnlockedSPI(PinName mosi, PinName miso, PinName sclk) :
+        SPI(mosi, miso, sclk) { }
+    virtual void lock() { }
+    virtual void unlock() { }
+};
+
+class RFBits {
+public:
+    RFBits(PinName spi_mosi, PinName spi_miso,
+           PinName spi_sclk, PinName spi_cs,
+           PinName spi_rst, PinName spi_slp, PinName spi_irq);
+    UnlockedSPI spi;
+    DigitalOut CS;
+    DigitalOut RST;
+    DigitalOut SLP_TR;
+    InterruptIn IRQ;
+    Timeout ack_timer;
+    Timeout cal_timer;
+    Timeout cca_timer;
+#ifdef MBED_CONF_RTOS_PRESENT
+    Thread irq_thread;
+    Mutex mutex;
+    void rf_if_irq_task();
+#endif
+};
+
+RFBits::RFBits(PinName spi_mosi, PinName spi_miso,
+               PinName spi_sclk, PinName spi_cs,
+               PinName spi_rst, PinName spi_slp, PinName spi_irq)
+    :   spi(spi_mosi, spi_miso, spi_sclk),
+        CS(spi_cs),
+        RST(spi_rst),
+        SLP_TR(spi_slp),
+        IRQ(spi_irq)
+#ifdef MBED_CONF_RTOS_PRESENT
+,irq_thread(osPriorityRealtime, 1024)
+#endif
+{
+#ifdef MBED_CONF_RTOS_PRESENT
+    irq_thread.start(mbed::callback(this, &RFBits::rf_if_irq_task));
+#endif
+}
+
+static RFBits *rf;
+static uint8_t rf_part_num = 0;
+/*TODO: RSSI Base value setting*/
+static int8_t rf_rssi_base_val = -91;
+
+static uint8_t rf_if_spi_exchange(uint8_t out);
+
+static void rf_if_lock(void)
+{
+    platform_enter_critical();
+}
+
+static void rf_if_unlock(void)
+{
+    platform_exit_critical();
+}
+
+#ifdef MBED_CONF_RTOS_PRESENT
+static void rf_if_cca_timer_signal(void)
+{
+    rf->irq_thread.signal_set(SIG_TIMER_CCA);
+}
+
+static void rf_if_cal_timer_signal(void)
+{
+    rf->irq_thread.signal_set(SIG_TIMER_CAL);
+}
+
+static void rf_if_ack_timer_signal(void)
+{
+    rf->irq_thread.signal_set(SIG_TIMER_ACK);
+}
+#endif
+
+
+/* Delay functions for RF Chip SPI access */
+#ifdef __CC_ARM
+__asm static void delay_loop(uint32_t count)
+{
+1
+  SUBS a1, a1, #1
+  BCS  %BT1
+  BX   lr
+}
+#elif defined (__ICCARM__)
+static void delay_loop(uint32_t count)
+{
+  __asm volatile(
+    "loop: \n"
+    " SUBS %0, %0, #1 \n"
+    " BCS.n  loop\n"
+    : "+r" (count)
+    :
+    : "cc"
+  );
+}
+#else // GCC
+static void delay_loop(uint32_t count)
+{
+  __asm__ volatile (
+    "%=:\n\t"
+#if defined(__thumb__) && !defined(__thumb2__)
+    "SUB  %0, #1\n\t"
+#else
+    "SUBS %0, %0, #1\n\t"
+#endif
+    "BCS  %=b\n\t"
+    : "+l" (count)
+    :
+    : "cc"
+  );
+}
+#endif
+
+static void delay_ns(uint32_t ns)
+{
+  uint32_t cycles_per_us = SystemCoreClock / 1000000;
+  // Cortex-M0 takes 4 cycles per loop (SUB=1, BCS=3)
+  // Cortex-M3 and M4 takes 3 cycles per loop (SUB=1, BCS=2)
+  // Cortex-M7 - who knows?
+  // Cortex M3-M7 have "CYCCNT" - would be better than a software loop, but M0 doesn't
+  // Assume 3 cycles per loop for now - will be 33% slow on M0. No biggie,
+  // as original version of code was 300% slow on M4.
+  // [Note that this very calculation, plus call overhead, will take multiple
+  // cycles. Could well be 100ns on its own... So round down here, startup is
+  // worth at least one loop iteration.]
+  uint32_t count = (cycles_per_us * ns) / 3000;
+
+  delay_loop(count);
+}
+
+// t1 = 180ns, SEL falling edge to MISO active [SPI setup assumed slow enough to not need manual delay]
+#define CS_SELECT()  {rf->CS = 0; /* delay_ns(180); */}
+ // t9 = 250ns, last clock to SEL rising edge, t8 = 250ns, SPI idle time between consecutive access
+#define CS_RELEASE() {delay_ns(250); rf->CS = 1; delay_ns(250);}
+
+/*
+ * \brief Function sets the TX power variable.
+ *
+ * \param power TX power setting
+ *
+ * \return 0 Success
+ * \return -1 Fail
+ */
+MBED_UNUSED static int8_t rf_tx_power_set(uint8_t power)
+{
+    int8_t ret_val = -1;
+
+    radio_tx_power = power;
+    rf_if_lock();
+    rf_if_write_set_tx_power_register(radio_tx_power);
+    rf_if_unlock();
+    ret_val = 0;
+
+    return ret_val;
+}
+
+/*
+ * \brief Read connected radio part.
+ *
+ * This function only return valid information when rf_init() is called
+ *
+ * \return
+ */
+static rf_trx_part_e rf_radio_type_read(void)
+{
+  rf_trx_part_e ret_val = ATMEL_UNKNOW_DEV;
+
+  switch (rf_part_num)
+  {
+    case PART_AT86RF212:
+      ret_val = ATMEL_AT86RF212;
+      break;
+    case PART_AT86RF233:
+      ret_val = ATMEL_AT86RF233;
+      break;
+    default:
+      break;
+  }
+
+  return ret_val;
+}
+
+
+/*
+ * \brief Function starts the ACK wait timeout.
+ *
+ * \param slots Given slots, resolution 50us
+ *
+ * \return none
+ */
+static void rf_if_ack_wait_timer_start(uint16_t slots)
+{
+#ifdef MBED_CONF_RTOS_PRESENT
+  rf->ack_timer.attach_us(rf_if_ack_timer_signal, slots*50);
+#else
+  rf->ack_timer.attach_us(rf_ack_wait_timer_interrupt, slots*50);
+#endif
+}
+
+/*
+ * \brief Function starts the calibration interval.
+ *
+ * \param slots Given slots, resolution 50us
+ *
+ * \return none
+ */
+static void rf_if_calibration_timer_start(uint32_t slots)
+{
+#ifdef MBED_CONF_RTOS_PRESENT
+  rf->cal_timer.attach_us(rf_if_cal_timer_signal, slots*50);
+#else
+  rf->cal_timer.attach_us(rf_calibration_timer_interrupt, slots*50);
+#endif
+}
+
+/*
+ * \brief Function starts the CCA interval.
+ *
+ * \param slots Given slots, resolution 50us
+ *
+ * \return none
+ */
+static void rf_if_cca_timer_start(uint32_t slots)
+{
+#ifdef MBED_CONF_RTOS_PRESENT
+  rf->cca_timer.attach_us(rf_if_cca_timer_signal, slots*50);
+#else
+  rf->cca_timer.attach_us(rf_cca_timer_interrupt, slots*50);
+#endif
+}
+
+/*
+ * \brief Function stops the CCA interval.
+ *
+ * \return none
+ */
+static void rf_if_cca_timer_stop(void)
+{
+  rf->cca_timer.detach();
+}
+
+/*
+ * \brief Function stops the ACK wait timeout.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_ack_wait_timer_stop(void)
+{
+  rf->ack_timer.detach();
+}
+
+/*
+ * \brief Function sets bit(s) in given RF register.
+ *
+ * \param addr Address of the register to set
+ * \param bit Bit(s) to set
+ * \param bit_mask Masks the field inside the register
+ *
+ * \return none
+ */
+static void rf_if_set_bit(uint8_t addr, uint8_t bit, uint8_t bit_mask)
+{
+  uint8_t reg = rf_if_read_register(addr);
+  reg &= ~bit_mask;
+  reg |= bit;
+  rf_if_write_register(addr, reg);
+}
+
+/*
+ * \brief Function clears bit(s) in given RF register.
+ *
+ * \param addr Address of the register to clear
+ * \param bit Bit(s) to clear
+ *
+ * \return none
+ */
+static void rf_if_clear_bit(uint8_t addr, uint8_t bit)
+{
+  rf_if_set_bit(addr, 0, bit);
+}
+
+/*
+ * \brief Function writes register in RF.
+ *
+ * \param addr Address on the RF
+ * \param data Written data
+ *
+ * \return none
+ */
+static void rf_if_write_register(uint8_t addr, uint8_t data)
+{
+  uint8_t cmd = 0xC0;
+  CS_SELECT();
+  rf_if_spi_exchange(cmd | addr);
+  rf_if_spi_exchange(data);
+  CS_RELEASE();
+}
+
+/*
+ * \brief Function reads RF register.
+ *
+ * \param addr Address on the RF
+ *
+ * \return Read data
+ */
+static uint8_t rf_if_read_register(uint8_t addr)
+{
+  uint8_t cmd = 0x80;
+  uint8_t data;
+  CS_SELECT();
+  rf_if_spi_exchange(cmd | addr);
+  data = rf_if_spi_exchange(0);
+  CS_RELEASE();
+  return data;
+}
+
+/*
+ * \brief Function resets the RF.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_reset_radio(void)
+{
+  rf->spi.frequency(SPI_SPEED);
+  rf->IRQ.rise(0);
+  rf->RST = 1;
+  wait_ms(1);
+  rf->RST = 0;
+  wait_ms(10);
+  CS_RELEASE();
+  rf->SLP_TR = 0;
+  wait_ms(10);
+  rf->RST = 1;
+  wait_ms(10);
+
+  rf->IRQ.rise(&rf_if_interrupt_handler);
+}
+
+/*
+ * \brief Function enables the promiscuous mode.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_enable_promiscuous_mode(void)
+{
+  /*Set AACK_PROM_MODE to enable the promiscuous mode*/
+  rf_if_set_bit(XAH_CTRL_1, AACK_PROM_MODE, AACK_PROM_MODE);
+}
+
+/*
+ * \brief Function enables the promiscuous mode.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_disable_promiscuous_mode(void)
+{
+  /*Set AACK_PROM_MODE to enable the promiscuous mode*/
+  rf_if_clear_bit(XAH_CTRL_1, AACK_PROM_MODE);
+}
+
+/*
+ * \brief Function enables the Antenna diversity usage.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_enable_ant_div(void)
+{
+  /*Set ANT_EXT_SW_EN to enable controlling of antenna diversity*/
+  rf_if_set_bit(ANT_DIV, ANT_EXT_SW_EN, ANT_EXT_SW_EN);
+}
+
+/*
+ * \brief Function disables the Antenna diversity usage.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_disable_ant_div(void)
+{
+  rf_if_clear_bit(ANT_DIV, ANT_EXT_SW_EN);
+}
+
+/*
+ * \brief Function sets the SLP TR pin.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_enable_slptr(void)
+{
+  rf->SLP_TR = 1;
+}
+
+/*
+ * \brief Function clears the SLP TR pin.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_disable_slptr(void)
+{
+  rf->SLP_TR = 0;
+}
+
+/*
+ * \brief Function writes the antenna diversity settings.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_write_antenna_diversity_settings(void)
+{
+  /*Recommended setting of PDT_THRES is 3 when antenna diversity is used*/
+  rf_if_set_bit(RX_CTRL, 0x03, 0x0f);
+  rf_if_write_register(ANT_DIV, ANT_DIV_EN | ANT_EXT_SW_EN | ANT_CTRL_DEFAULT);
+}
+
+/*
+ * \brief Function writes the TX output power register.
+ *
+ * \param value Given register value
+ *
+ * \return none
+ */
+static void rf_if_write_set_tx_power_register(uint8_t value)
+{
+  rf_if_write_register(PHY_TX_PWR, value);
+}
+
+/*
+ * \brief Function returns the RF part number.
+ *
+ * \param none
+ *
+ * \return part number
+ */
+static uint8_t rf_if_read_part_num(void)
+{
+  return rf_if_read_register(PART_NUM);
+}
+
+/*
+ * \brief Function writes the RF settings and initialises SPI interface.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_write_rf_settings(void)
+{
+  /*Reset RF module*/
+  rf_if_reset_radio();
+
+  rf_part_num = rf_if_read_part_num();
+
+  rf_if_write_register(XAH_CTRL_0,0);
+  rf_if_write_register(TRX_CTRL_1, 0x20);
+
+  /*CCA Mode - Carrier sense OR energy above threshold. Channel list is set separately*/
+  rf_if_write_register(PHY_CC_CCA, 0x05);
+
+  /*Read transceiver PART_NUM*/
+  rf_part_num = rf_if_read_register(PART_NUM);
+
+  /*Sub-GHz RF settings*/
+  if(rf_part_num == PART_AT86RF212)
+  {
+    /*GC_TX_OFFS mode-dependent setting - OQPSK*/
+    rf_if_write_register(RF_CTRL_0, 0x32);
+
+    if(rf_if_read_register(VERSION_NUM) == VERSION_AT86RF212B)
+    {
+      /*TX Output Power setting - 0 dBm North American Band*/
+      rf_if_write_register(PHY_TX_PWR, 0x03);
+    }
+    else
+    {
+      /*TX Output Power setting - 0 dBm North American Band*/
+      rf_if_write_register(PHY_TX_PWR, 0x24);
+    }
+
+    /*PHY Mode: IEEE 802.15.4-2006/2011 - OQPSK-SIN-250*/
+    rf_if_write_register(TRX_CTRL_2, RF_PHY_MODE);
+    /*Based on receiver Characteristics. See AT86RF212B Datasheet where RSSI BASE VALUE in range -97 - -100 dBm*/
+    rf_rssi_base_val = -98;
+  }
+  /*2.4GHz RF settings*/
+  else
+  {
+#if 0
+    /* Disable power saving functions for now - can only impact reliability,
+     * and don't have any users demanding it. */
+    /*Set RPC register*/
+    rf_if_write_register(TRX_RPC, RX_RPC_CTRL|RX_RPC_EN|PLL_RPC_EN|XAH_TX_RPC_EN|IPAN_RPC_EN|TRX_RPC_RSVD_1);
+#endif
+    /*PHY Mode: IEEE 802.15.4 - Data Rate 250 kb/s*/
+    rf_if_write_register(TRX_CTRL_2, 0);
+    rf_rssi_base_val = -91;
+  }
+}
+
+/*
+ * \brief Function checks the channel availability
+ *
+ * \param none
+ *
+ * \return 1 Channel clear
+ * \return 0 Channel not clear
+ */
+static uint8_t rf_if_check_cca(void)
+{
+  uint8_t retval = 0;
+  if(rf_if_read_register(TRX_STATUS) & CCA_STATUS)
+  {
+    retval = 1;
+  }
+  return retval;
+}
+
+/*
+ * \brief Function returns the RF state
+ *
+ * \param none
+ *
+ * \return RF state
+ */
+static uint8_t rf_if_read_trx_state(void)
+{
+  return rf_if_read_register(TRX_STATUS) & 0x1F;
+}
+
+/*
+ * \brief Function reads packet buffer.
+ *
+ * \param data_out Output buffer
+ * \param lqi_out LQI output
+ * \param ed_out ED output
+ * \param crc_good CRC good indication
+ *
+ * \return PSDU length [0..RF_MTU]
+ */
+static uint16_t rf_if_read_packet(uint8_t data_out[RF_MTU], uint8_t *lqi_out, uint8_t *ed_out, bool *crc_good)
+{
+  CS_SELECT();
+  rf_if_spi_exchange(0x20);
+  uint8_t len = rf_if_spi_exchange(0) & 0x7F;
+  uint8_t *ptr = data_out;
+  for (uint_fast8_t i = 0; i < len; i++) {
+    *ptr++ = rf_if_spi_exchange(0);
+  }
+
+  *lqi_out = rf_if_spi_exchange(0);
+  *ed_out = rf_if_spi_exchange(0);
+  *crc_good = rf_if_spi_exchange(0) & 0x80;
+  CS_RELEASE();
+
+  return len;
+}
+
+/*
+ * \brief Function writes RF short address registers
+ *
+ * \param short_address Given short address
+ *
+ * \return none
+ */
+static void rf_if_write_short_addr_registers(uint8_t *short_address)
+{
+  rf_if_write_register(SHORT_ADDR_1, *short_address++);
+  rf_if_write_register(SHORT_ADDR_0, *short_address);
+}
+
+/*
+ * \brief Function sets the frame pending in ACK message
+ *
+ * \param state Given frame pending state
+ *
+ * \return none
+ */
+static void rf_if_ack_pending_ctrl(uint8_t state)
+{
+  rf_if_lock();
+  if(state)
+  {
+    rf_if_set_bit(CSMA_SEED_1, (1 << AACK_SET_PD), (1 << AACK_SET_PD));
+  }
+  else
+  {
+    rf_if_clear_bit(CSMA_SEED_1, (1 << AACK_SET_PD));
+  }
+  rf_if_unlock();
+}
+
+/*
+ * \brief Function returns the state of frame pending control
+ *
+ * \param none
+ *
+ * \return Frame pending state
+ */
+static uint8_t rf_if_last_acked_pending(void)
+{
+  uint8_t last_acked_data_pending;
+
+  rf_if_lock();
+  if(rf_if_read_register(CSMA_SEED_1) & 0x20)
+    last_acked_data_pending = 1;
+  else
+    last_acked_data_pending = 0;
+  rf_if_unlock();
+
+  return last_acked_data_pending;
+}
+
+/*
+ * \brief Function calibrates the RF part.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_calibration(void)
+{
+  rf_if_set_bit(FTN_CTRL, FTN_START, FTN_START);
+  /*Wait while calibration is running*/
+  while(rf_if_read_register(FTN_CTRL) & FTN_START);
+}
+
+/*
+ * \brief Function writes RF PAN Id registers
+ *
+ * \param pan_id Given PAN Id
+ *
+ * \return none
+ */
+static void rf_if_write_pan_id_registers(uint8_t *pan_id)
+{
+  rf_if_write_register(PAN_ID_1, *pan_id++);
+  rf_if_write_register(PAN_ID_0, *pan_id);
+}
+
+/*
+ * \brief Function writes RF IEEE Address registers
+ *
+ * \param address Given IEEE Address
+ *
+ * \return none
+ */
+static void rf_if_write_ieee_addr_registers(uint8_t *address)
+{
+  uint8_t i;
+  uint8_t temp = IEEE_ADDR_0;
+
+  for(i=0; i<8; i++)
+    rf_if_write_register(temp++, address[7-i]);
+}
+
+/*
+ * \brief Function writes data in RF frame buffer.
+ *
+ * \param ptr Pointer to data (PSDU, except FCS)
+ * \param length Pointer to length (PSDU length, minus 2 for FCS)
+ *
+ * \return none
+ */
+static void rf_if_write_frame_buffer(const uint8_t *ptr, uint8_t length)
+{
+  uint8_t i;
+  uint8_t cmd = 0x60;
+
+  CS_SELECT();
+  rf_if_spi_exchange(cmd);
+  rf_if_spi_exchange(length + 2);
+  for(i=0; i<length; i++)
+    rf_if_spi_exchange(*ptr++);
+
+  CS_RELEASE();
+}
+
+/*
+ * \brief Function returns 8-bit random value.
+ *
+ * \param none
+ *
+ * \return random value
+ */
+static uint8_t rf_if_read_rnd(void)
+{
+  uint8_t temp;
+  uint8_t tmp_rpc_val = 0;
+  /*RPC must be disabled while reading the random number*/
+  if(rf_part_num == PART_AT86RF233)
+  {
+    tmp_rpc_val = rf_if_read_register(TRX_RPC);
+    rf_if_write_register(TRX_RPC, RX_RPC_CTRL|TRX_RPC_RSVD_1);
+  }
+
+  wait_ms(1);
+  temp = ((rf_if_read_register(PHY_RSSI)>>5) << 6);
+  wait_ms(1);
+  temp |= ((rf_if_read_register(PHY_RSSI)>>5) << 4);
+  wait_ms(1);
+  temp |= ((rf_if_read_register(PHY_RSSI)>>5) << 2);
+  wait_ms(1);
+  temp |= ((rf_if_read_register(PHY_RSSI)>>5));
+  wait_ms(1);
+  if(rf_part_num == PART_AT86RF233)
+    rf_if_write_register(TRX_RPC, tmp_rpc_val);
+  return temp;
+}
+
+/*
+ * \brief Function changes the state of the RF.
+ *
+ * \param trx_state Given RF state
+ *
+ * \return none
+ */
+static void rf_if_change_trx_state(rf_trx_states_t trx_state)
+{
+  // XXX Lock claim apparently not required
+  rf_if_lock();
+  rf_if_write_register(TRX_STATE, trx_state);
+  /*Wait while not in desired state*/
+  rf_poll_trx_state_change(trx_state);
+  rf_if_unlock();
+}
+
+/*
+ * \brief Function enables the TX END interrupt
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_enable_tx_end_interrupt(void)
+{
+  rf_if_set_bit(IRQ_MASK, TRX_END, TRX_END);
+}
+
+/*
+ * \brief Function enables the RX END interrupt
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_enable_rx_end_interrupt(void)
+{
+  rf_if_set_bit(IRQ_MASK, TRX_END, TRX_END);
+}
+
+/*
+ * \brief Function enables the CCA ED interrupt
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_enable_cca_ed_done_interrupt(void)
+{
+  rf_if_set_bit(IRQ_MASK, CCA_ED_DONE, CCA_ED_DONE);
+}
+
+/*
+ * \brief Function starts the CCA process
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_start_cca_process(void)
+{
+  rf_if_set_bit(PHY_CC_CCA, CCA_REQUEST, CCA_REQUEST);
+}
+
+/*
+ * \brief Function scales RSSI
+ *
+ * \param ed_level ED level read from chip
+ *
+ * \return appropriately scaled RSSI dBm
+ */
+static int8_t rf_if_scale_rssi(uint8_t ed_level)
+{
+  if (rf_part_num == PART_AT86RF212) {
+    /* Data sheet says to multiply by 1.03 - this is 1.03125, rounding down */
+    ed_level += ed_level >> 5;
+  }
+  return rf_rssi_base_val + ed_level;
+}
+
+/*
+ * \brief Function sets the RF channel field
+ *
+ * \param Given channel
+ *
+ * \return none
+ */
+static void rf_if_set_channel_register(uint8_t channel)
+{
+  rf_if_set_bit(PHY_CC_CCA, channel, 0x1f);
+}
+
+/*
+ * \brief Function enables RF irq pin interrupts in RF interface.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_enable_irq(void)
+{
+  rf->IRQ.enable_irq();
+}
+
+/*
+ * \brief Function disables RF irq pin interrupts in RF interface.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_disable_irq(void)
+{
+  rf->IRQ.disable_irq();
+}
+
+#ifdef MBED_CONF_RTOS_PRESENT
+static void rf_if_interrupt_handler(void)
+{
+    rf->irq_thread.signal_set(SIG_RADIO);
+}
+
+// Started during construction of rf, so variable
+// rf isn't set at the start. Uses 'this' instead.
+void RFBits::rf_if_irq_task(void)
+{
+    for (;;) {
+        osEvent event = irq_thread.signal_wait(0);
+        if (event.status != osEventSignal) {
+            continue;
+        }
+        rf_if_lock();
+        if (event.value.signals & SIG_RADIO) {
+            rf_if_irq_task_process_irq();
+        }
+        if (event.value.signals & SIG_TIMER_ACK) {
+            rf_ack_wait_timer_interrupt();
+        }
+        if (event.value.signals & SIG_TIMER_CCA) {
+            rf_cca_timer_interrupt();
+        }
+        if (event.value.signals & SIG_TIMER_CAL) {
+            rf_calibration_timer_interrupt();
+        }
+        rf_if_unlock();
+    }
+}
+
+static void rf_if_irq_task_process_irq(void)
+#else
+/*
+ * \brief Function is a RF interrupt vector. End of frame in RX and TX are handled here as well as CCA process interrupt.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_if_interrupt_handler(void)
+#endif
+{
+  uint8_t irq_status;
+
+  /*Read interrupt flag*/
+  irq_status = rf_if_read_register(IRQ_STATUS);
+
+  /*Disable interrupt on RF*/
+  rf_if_clear_bit(IRQ_MASK, irq_status);
+  /*RX start interrupt*/
+  if(irq_status & RX_START)
+  {
+  }
+  /*Address matching interrupt*/
+  if(irq_status & AMI)
+  {
+  }
+  if(irq_status & TRX_UR)
+  {
+  }
+  /*Frame end interrupt (RX and TX)*/
+  if(irq_status & TRX_END)
+  {
+    /*TX done interrupt*/
+    if(rf_if_read_trx_state() == PLL_ON || rf_if_read_trx_state() == TX_ARET_ON)
+    {
+      rf_handle_tx_end();
+    }
+    /*Frame received interrupt*/
+    else
+    {
+      rf_handle_rx_end();
+    }
+  }
+  if(irq_status & CCA_ED_DONE)
+  {
+    rf_handle_cca_ed_done();
+  }
+}
+
+/*
+ * \brief Function writes/read data in SPI interface
+ *
+ * \param out Output data
+ *
+ * \return Input data
+ */
+static uint8_t rf_if_spi_exchange(uint8_t out)
+{
+  uint8_t v;
+  v = rf->spi.write(out);
+  // t9 = t5 = 250ns, delay between LSB of last byte to next MSB or delay between LSB & SEL rising
+  // [SPI setup assumed slow enough to not need manual delay]
+  // delay_ns(250);
+  return v;
+}
+
+/*
+ * \brief Function sets given RF flag on.
+ *
+ * \param x Given RF flag
+ *
+ * \return none
+ */
+static void rf_flags_set(uint8_t x)
+{
+    rf_flags |= x;
+}
+
+/*
+ * \brief Function clears given RF flag on.
+ *
+ * \param x Given RF flag
+ *
+ * \return none
+ */
+static void rf_flags_clear(uint8_t x)
+{
+    rf_flags &= ~x;
+}
+
+/*
+ * \brief Function checks if given RF flag is on.
+ *
+ * \param x Given RF flag
+ *
+ * \return states of the given flags
+ */
+static uint8_t rf_flags_check(uint8_t x)
+{
+    return (rf_flags & x);
+}
+
+/*
+ * \brief Function clears all RF flags.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_flags_reset(void)
+{
+    rf_flags = 0;
+}
+
+/*
+ * \brief Function initialises and registers the RF driver.
+ *
+ * \param none
+ *
+ * \return rf_radio_driver_id Driver ID given by NET library
+ */
+static int8_t rf_device_register(const uint8_t *mac_addr)
+{
+    rf_trx_part_e radio_type;
+
+    rf_init();
+
+    radio_type = rf_radio_type_read();
+    if(radio_type != ATMEL_UNKNOW_DEV)
+    {
+        /*Set pointer to MAC address*/
+        device_driver.PHY_MAC = (uint8_t *)mac_addr;
+        device_driver.driver_description = (char*)"ATMEL_MAC";
+        //Create setup Used Radio chips
+        if(radio_type == ATMEL_AT86RF212)
+        {
+            device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
+        }
+        else
+        {
+            device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
+        }
+        device_driver.phy_channel_pages = phy_channel_pages;
+        /*Maximum size of payload is 127*/
+        device_driver.phy_MTU = 127;
+        /*No header in PHY*/
+        device_driver.phy_header_length = 0;
+        /*No tail in PHY*/
+        device_driver.phy_tail_length = 0;
+        /*Set address write function*/
+        device_driver.address_write = &rf_address_write;
+        /*Set RF extension function*/
+        device_driver.extension = &rf_extension;
+        /*Set RF state control function*/
+        device_driver.state_control = &rf_interface_state_control;
+        /*Set transmit function*/
+        device_driver.tx = &rf_start_cca;
+        /*NULLIFY rx and tx_done callbacks*/
+        device_driver.phy_rx_cb = NULL;
+        device_driver.phy_tx_done_cb = NULL;
+        /*Register device driver*/
+        rf_radio_driver_id = arm_net_phy_register(&device_driver);
+    }
+    return rf_radio_driver_id;
+}
+
+/*
+ * \brief Function unregisters the RF driver.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_device_unregister()
+{
+    if (rf_radio_driver_id >= 0) {
+        arm_net_phy_unregister(rf_radio_driver_id);
+        rf_radio_driver_id = -1;
+    }
+}
+
+/*
+ * \brief Enable frame buffer protection
+ *
+ * If protection is enabled, reception cannot start - the radio will
+ * not go into RX_BUSY or write into the frame buffer if in receive mode.
+ * Setting this won't abort an already-started reception.
+ * We can still write the frame buffer ourselves.
+ */
+static void rf_enable_static_frame_buffer_protection(void)
+{
+  if (!rf_flags_check(RFF_PROT)) {
+    /* This also writes RX_PDT_LEVEL to 0 - maximum RX sensitivity */
+    /* Would need to modify this function if messing with that */
+    rf_if_write_register(RX_SYN, RX_PDT_DIS);
+    rf_flags_set(RFF_PROT);
+  }
+}
+
+/*
+ * \brief Disable frame buffer protection
+ */
+static void rf_disable_static_frame_buffer_protection(void)
+{
+  if (rf_flags_check(RFF_PROT)) {
+    /* This also writes RX_PDT_LEVEL to 0 - maximum RX sensitivity */
+    /* Would need to modify this function if messing with that */
+    rf_if_write_register(RX_SYN, 0);
+    rf_flags_clear(RFF_PROT);
+  }
+}
+
+
+/*
+ * \brief Function is a call back for ACK wait timeout.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_ack_wait_timer_interrupt(void)
+{
+    rf_if_lock();
+    expected_ack_sequence = -1;
+    /*Force PLL state*/
+    rf_if_change_trx_state(FORCE_PLL_ON);
+    rf_poll_trx_state_change(PLL_ON);
+    /*Start receiver in RX_AACK_ON state*/
+    rf_rx_mode = 0;
+    rf_flags_clear(RFF_RX);
+    rf_receive();
+    rf_if_unlock();
+}
+
+/*
+ * \brief Function is a call back for calibration interval timer.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_calibration_timer_interrupt(void)
+{
+    /*Calibrate RF*/
+    rf_calibration_cb();
+    /*Start new calibration timeout*/
+    rf_calibration_timer_start(RF_CALIBRATION_INTERVAL);
+}
+
+/*
+ * \brief Function is a call back for cca interval timer.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_cca_timer_interrupt(void)
+{
+    /*Disable reception - locks against entering BUSY_RX and overwriting frame buffer*/
+    rf_enable_static_frame_buffer_protection();
+
+    if(rf_if_read_trx_state() == BUSY_RX_AACK)
+    {
+        /*Reception already started - re-enable reception and say CCA fail*/
+        rf_disable_static_frame_buffer_protection();
+        if(device_driver.phy_tx_done_cb){
+            device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
+        }
+    }
+    else
+    {
+        /*Load the frame buffer with frame to transmit */
+        rf_if_write_frame_buffer(rf_tx_data, rf_tx_length);
+        /*Make sure we're in RX state to read channel (any way we could not be?)*/
+        rf_receive();
+        rf_flags_set(RFF_CCA);
+        /*Start CCA process*/
+        rf_if_enable_cca_ed_done_interrupt();
+        rf_if_start_cca_process();
+    }
+}
+
+/*
+ * \brief Function starts the ACK wait timeout.
+ *
+ * \param slots Given slots, resolution 50us
+ *
+ * \return none
+ */
+static void rf_ack_wait_timer_start(uint16_t slots)
+{
+    rf_if_ack_wait_timer_start(slots);
+}
+
+/*
+ * \brief Function starts the calibration interval.
+ *
+ * \param slots Given slots, resolution 50us
+ *
+ * \return none
+ */
+static void rf_calibration_timer_start(uint32_t slots)
+{
+    rf_if_calibration_timer_start(slots);
+}
+
+/*
+ * \brief Function starts the CCA backoff.
+ *
+ * \param slots Given slots, resolution 50us
+ *
+ * \return none
+ */
+static void rf_cca_timer_start(uint32_t slots)
+{
+    rf_if_cca_timer_start(slots);
+}
+
+/*
+ * \brief Function stops the CCA backoff.
+ *
+ * \return none
+ */
+static void rf_cca_timer_stop(void)
+{
+    rf_if_cca_timer_stop();
+}
+
+/*
+ * \brief Function stops the ACK wait timeout.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_ack_wait_timer_stop(void)
+{
+    rf_if_ack_wait_timer_stop();
+}
+
+/*
+ * \brief Function writes various RF settings in startup.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_write_settings(void)
+{
+    rf_if_lock();
+    rf_if_write_rf_settings();
+    /*Set output power*/
+    rf_if_write_set_tx_power_register(radio_tx_power);
+    /*Initialise Antenna Diversity*/
+    if(rf_use_antenna_diversity)
+        rf_if_write_antenna_diversity_settings();
+    rf_if_unlock();
+}
+
+/*
+ * \brief Function writes 16-bit address in RF address filter.
+ *
+ * \param short_address Given short address
+ *
+ * \return none
+ */
+static void rf_set_short_adr(uint8_t * short_address)
+{
+    rf_if_lock();
+    /*Wake up RF if sleeping*/
+    if(rf_flags_check(RFF_ON) == 0)
+    {
+        rf_if_disable_slptr();
+        rf_poll_trx_state_change(TRX_OFF);
+    }
+    /*Write address filter registers*/
+    rf_if_write_short_addr_registers(short_address);
+    /*RF back to sleep*/
+    if(rf_flags_check(RFF_ON) == 0)
+    {
+        rf_if_enable_slptr();
+    }
+    rf_if_unlock();
+}
+
+/*
+ * \brief Function writes PAN Id in RF PAN Id filter.
+ *
+ * \param pan_id Given PAN Id
+ *
+ * \return none
+ */
+static void rf_set_pan_id(uint8_t *pan_id)
+{
+    rf_if_lock();
+    /*Wake up RF if sleeping*/
+    if(rf_flags_check(RFF_ON) == 0)
+    {
+        rf_if_disable_slptr();
+        rf_poll_trx_state_change(TRX_OFF);
+    }
+    /*Write address filter registers*/
+    rf_if_write_pan_id_registers(pan_id);
+    /*RF back to sleep*/
+    if(rf_flags_check(RFF_ON) == 0)
+    {
+        rf_if_enable_slptr();
+    }
+    rf_if_unlock();
+}
+
+/*
+ * \brief Function writes 64-bit address in RF address filter.
+ *
+ * \param address Given 64-bit address
+ *
+ * \return none
+ */
+static void rf_set_address(uint8_t *address)
+{
+    rf_if_lock();
+    /*Wake up RF if sleeping*/
+    if(rf_flags_check(RFF_ON) == 0)
+    {
+        rf_if_disable_slptr();
+        rf_poll_trx_state_change(TRX_OFF);
+    }
+    /*Write address filter registers*/
+    rf_if_write_ieee_addr_registers(address);
+    /*RF back to sleep*/
+    if(rf_flags_check(RFF_ON) == 0)
+    {
+        rf_if_enable_slptr();
+    }
+    rf_if_unlock();
+}
+
+/*
+ * \brief Function sets the RF channel.
+ *
+ * \param ch New channel
+ *
+ * \return none
+ */
+static void rf_channel_set(uint8_t ch)
+{
+    rf_if_lock();
+    rf_phy_channel = ch;
+    if(ch < 0x1f)
+        rf_if_set_channel_register(ch);
+    rf_if_unlock();
+}
+
+
+/*
+ * \brief Function initialises the radio driver and resets the radio.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_init(void)
+{
+    /*Reset RF module*/
+    rf_if_reset_radio();
+
+    rf_if_lock();
+
+    /*Write RF settings*/
+    rf_write_settings();
+    /*Initialise PHY mode*/
+    rf_init_phy_mode();
+    /*Clear RF flags*/
+    rf_flags_reset();
+    /*Set RF in TRX OFF state*/
+    rf_if_change_trx_state(TRX_OFF);
+    /*Set RF in PLL_ON state*/
+    rf_if_change_trx_state(PLL_ON);
+    /*Start receiver*/
+    rf_receive();
+    /*Read randomness, and add to seed*/
+    randLIB_add_seed(rf_if_read_rnd());
+    /*Start RF calibration timer*/
+    rf_calibration_timer_start(RF_CALIBRATION_INTERVAL);
+
+    rf_if_unlock();
+}
+
+/**
+ * \brief Function gets called when MAC is setting radio off.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_off(void)
+{
+    if(rf_flags_check(RFF_ON))
+    {
+        rf_if_lock();
+        rf_cca_abort();
+        uint16_t while_counter = 0;
+        /*Wait while receiving*/
+        while(rf_if_read_trx_state() == BUSY_RX_AACK)
+        {
+            while_counter++;
+            if(while_counter == 0xffff)
+                break;
+        }
+        /*RF state change: RX_AACK_ON->PLL_ON->TRX_OFF->SLEEP*/
+        if(rf_if_read_trx_state() == RX_AACK_ON)
+        {
+            rf_if_change_trx_state(PLL_ON);
+        }
+        rf_if_change_trx_state(TRX_OFF);
+        rf_if_enable_slptr();
+
+        /*Disable Antenna Diversity*/
+        if(rf_use_antenna_diversity)
+            rf_if_disable_ant_div();
+        rf_if_unlock();
+    }
+
+    /*Clears all flags*/
+    rf_flags_reset();
+}
+
+/*
+ * \brief Function polls the RF state until it has changed to desired state.
+ *
+ * \param trx_state RF state
+ *
+ * \return none
+ */
+static void rf_poll_trx_state_change(rf_trx_states_t trx_state)
+{
+    uint16_t while_counter = 0;
+    // XXX lock apparently not needed
+    rf_if_lock();
+
+    if(trx_state != RF_TX_START)
+    {
+        if(trx_state == FORCE_PLL_ON)
+            trx_state = PLL_ON;
+        else if(trx_state == FORCE_TRX_OFF)
+            trx_state = TRX_OFF;
+
+        while(rf_if_read_trx_state() != trx_state)
+        {
+            while_counter++;
+            if(while_counter == 0x1ff)
+                break;
+        }
+    }
+    rf_if_unlock();
+}
+
+/*
+ * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO.
+ *
+ * \param data_ptr Pointer to TX data (excluding FCS)
+ * \param data_length Length of the TX data (excluding FCS)
+ * \param tx_handle Handle to transmission
+ * \return 0 Success
+ * \return -1 Busy
+ */
+static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol )
+{
+    (void)data_protocol;
+    rf_if_lock();
+    /*Check if transmitter is busy*/
+    if(rf_if_read_trx_state() == BUSY_RX_AACK || data_length > RF_MTU - 2)
+    {
+        rf_if_unlock();
+        /*Return busy*/
+        return -1;
+    }
+    else
+    {
+        expected_ack_sequence = -1;
+
+        /*Nanostack has a static TX buffer, which will remain valid until we*/
+        /*generate a callback, so we just note the pointer for reading later.*/
+        rf_tx_data = data_ptr;
+        rf_tx_length = data_length;
+        /*Start CCA timeout*/
+        rf_cca_timer_start(RF_CCA_BASE_BACKOFF + randLIB_get_random_in_range(0, RF_CCA_RANDOM_BACKOFF));
+        /*Store TX handle*/
+        mac_tx_handle = tx_handle;
+        rf_if_unlock();
+    }
+
+    /*Return success*/
+    return 0;
+}
+
+/*
+ * \brief Function aborts CCA process.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_cca_abort(void)
+{
+    rf_cca_timer_stop();
+    rf_flags_clear(RFF_CCA);
+    rf_disable_static_frame_buffer_protection();
+}
+
+/*
+ * \brief Function starts the transmission of the frame.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_start_tx(void)
+{
+    /*Only start transmitting from RX state*/
+    uint8_t trx_state = rf_if_read_trx_state();
+    if(trx_state != RX_AACK_ON)
+    {
+        rf_disable_static_frame_buffer_protection();
+        if(device_driver.phy_tx_done_cb){
+            device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
+        }
+    }
+    else
+    {
+        /*RF state change: ->PLL_ON->RF_TX_START*/
+        rf_if_change_trx_state(FORCE_PLL_ON);
+        rf_flags_clear(RFF_RX);
+        /*Now we're out of receive mode, can release protection*/
+        rf_disable_static_frame_buffer_protection();
+        rf_if_enable_tx_end_interrupt();
+        rf_flags_set(RFF_TX);
+        rf_if_change_trx_state(RF_TX_START);
+    }
+}
+
+/*
+ * \brief Function sets the RF in RX state.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_receive(void)
+{
+    uint16_t while_counter = 0;
+    if(rf_flags_check(RFF_ON) == 0)
+    {
+        rf_on();
+    }
+    /*If not yet in RX state set it*/
+    if(rf_flags_check(RFF_RX) == 0)
+    {
+        rf_if_lock();
+        /*Wait while receiving data*/
+        while(rf_if_read_trx_state() == BUSY_RX_AACK)
+        {
+            while_counter++;
+            if(while_counter == 0xffff)
+            {
+                break;
+            }
+        }
+
+        rf_if_change_trx_state(PLL_ON);
+
+        if((rf_mode == RF_MODE_SNIFFER) || (rf_mode == RF_MODE_ED))
+        {
+            rf_if_change_trx_state(RX_ON);
+        }
+        else
+        {
+            /*ACK is always received in promiscuous mode to bypass address filters*/
+            if(rf_rx_mode)
+            {
+                rf_rx_mode = 0;
+                rf_if_enable_promiscuous_mode();
+            }
+            else
+            {
+                rf_if_disable_promiscuous_mode();
+            }
+            rf_if_change_trx_state(RX_AACK_ON);
+        }
+        /*If calibration timer was unable to calibrate the RF, run calibration now*/
+        if(!rf_tuned)
+        {
+            /*Start calibration. This can be done in states TRX_OFF, PLL_ON or in any receive state*/
+            rf_if_calibration();
+            /*RF is tuned now*/
+            rf_tuned = 1;
+        }
+
+        rf_channel_set(rf_phy_channel);
+        rf_flags_set(RFF_RX);
+        // Don't receive packets when ED mode enabled
+        if (rf_mode != RF_MODE_ED)
+        {
+            rf_if_enable_rx_end_interrupt();
+        }
+        rf_if_unlock();
+    }
+}
+
+/*
+ * \brief Function calibrates the radio.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_calibration_cb(void)
+{
+    /*clear tuned flag to start tuning in rf_receive*/
+    rf_tuned = 0;
+    /*If RF is in default receive state, start calibration*/
+    if(rf_if_read_trx_state() == RX_AACK_ON)
+    {
+        rf_if_lock();
+        /*Set RF in PLL_ON state*/
+        rf_if_change_trx_state(PLL_ON);
+        /*Set RF in TRX_OFF state to start PLL tuning*/
+        rf_if_change_trx_state(TRX_OFF);
+        /*Set RF in RX_ON state to calibrate*/
+        rf_if_change_trx_state(RX_ON);
+        /*Calibrate FTN*/
+        rf_if_calibration();
+        /*RF is tuned now*/
+        rf_tuned = 1;
+        /*Back to default receive state*/
+        rf_flags_clear(RFF_RX);
+        rf_receive();
+        rf_if_unlock();
+    }
+}
+
+/*
+ * \brief Function sets RF_ON flag when radio is powered.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_on(void)
+{
+    /*Set RFF_ON flag*/
+    if(rf_flags_check(RFF_ON) == 0)
+    {
+        rf_if_lock();
+        rf_flags_set(RFF_ON);
+        /*Enable Antenna diversity*/
+        if(rf_use_antenna_diversity)
+            /*Set ANT_EXT_SW_EN to enable controlling of antenna diversity*/
+            rf_if_enable_ant_div();
+
+        /*Wake up from sleep state*/
+        rf_if_disable_slptr();
+        rf_poll_trx_state_change(TRX_OFF);
+        rf_if_unlock();
+    }
+}
+
+/*
+ * \brief Function handles the received ACK frame.
+ *
+ * \param seq_number Sequence number of received ACK
+ * \param data_pending Pending bit state in received ACK
+ *
+ * \return none
+ */
+static void rf_handle_ack(uint8_t seq_number, uint8_t data_pending)
+{
+    phy_link_tx_status_e phy_status;
+    rf_if_lock();
+    /*Received ACK sequence must be equal with transmitted packet sequence*/
+    if(expected_ack_sequence == seq_number)
+    {
+        rf_ack_wait_timer_stop();
+        expected_ack_sequence = -1;
+        /*When data pending bit in ACK frame is set, inform NET library*/
+        if(data_pending)
+            phy_status = PHY_LINK_TX_DONE_PENDING;
+        else
+            phy_status = PHY_LINK_TX_DONE;
+        /*Call PHY TX Done API*/
+        if(device_driver.phy_tx_done_cb){
+            device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle,phy_status, 0, 0);
+        }
+    }
+    rf_if_unlock();
+}
+
+/*
+ * \brief Function is a call back for RX end interrupt.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_handle_rx_end(void)
+{
+    /*Start receiver*/
+    rf_flags_clear(RFF_RX);
+    rf_receive();
+
+    /*Frame received interrupt*/
+    if(!rf_flags_check(RFF_RX)) {
+        return;
+    }
+
+    static uint8_t rf_buffer[RF_MTU];
+    uint8_t rf_lqi, rf_ed;
+    int8_t rf_rssi;
+    bool crc_good;
+
+    /*Read received packet*/
+    uint8_t len = rf_if_read_packet(rf_buffer, &rf_lqi, &rf_ed, &crc_good);
+    if (len < 5 || !crc_good) {
+        return;
+    }
+
+    /* Convert raw ED to dBm value (chip-dependent) */
+    rf_rssi = rf_if_scale_rssi(rf_ed);
+
+    /* Create a virtual LQI using received RSSI, forgetting actual HW LQI */
+    /* (should be done through PHY_EXTENSION_CONVERT_SIGNAL_INFO) */
+    rf_lqi = rf_scale_lqi(rf_rssi);
+
+    /*Handle received ACK*/
+    if((rf_buffer[0] & 0x07) == 0x02 && rf_mode != RF_MODE_SNIFFER)
+    {
+        /*Check if data is pending*/
+        bool pending = (rf_buffer[0] & 0x10);
+
+        /*Send sequence number in ACK handler*/
+        rf_handle_ack(rf_buffer[2], pending);
+    } else {
+        if( device_driver.phy_rx_cb ){
+            device_driver.phy_rx_cb(rf_buffer, len - 2, rf_lqi, rf_rssi, rf_radio_driver_id);
+        }
+    }
+}
+
+/*
+ * \brief Function is called when MAC is shutting down the radio.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_shutdown(void)
+{
+    /*Call RF OFF*/
+    rf_off();
+}
+
+/*
+ * \brief Function is a call back for TX end interrupt.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_handle_tx_end(void)
+{
+    rf_rx_mode = 0;
+    /*If ACK is needed for this transmission*/
+    if((rf_tx_data[0] & 0x20) && rf_flags_check(RFF_TX))
+    {
+        expected_ack_sequence = rf_tx_data[2];
+        rf_ack_wait_timer_start(rf_ack_wait_duration);
+        rf_rx_mode = 1;
+    }
+    rf_flags_clear(RFF_RX);
+    /*Start receiver*/
+    rf_receive();
+
+    /*Call PHY TX Done API*/
+    if(device_driver.phy_tx_done_cb){
+        device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 0, 0);
+    }
+}
+
+/*
+ * \brief Function is a call back for CCA ED done interrupt.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_handle_cca_ed_done(void)
+{
+    if (!rf_flags_check(RFF_CCA)) {
+        return;
+    }
+    rf_flags_clear(RFF_CCA);
+    /*Check the result of CCA process*/
+    if(rf_if_check_cca())
+    {
+        rf_start_tx();
+    }
+    else
+    {
+        /*Re-enable reception*/
+        rf_disable_static_frame_buffer_protection();
+        /*Send CCA fail notification*/
+        if(device_driver.phy_tx_done_cb){
+            device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0);
+        }
+    }
+}
+
+/*
+ * \brief Function returns the TX power variable.
+ *
+ * \param none
+ *
+ * \return radio_tx_power TX power variable
+ */
+MBED_UNUSED static uint8_t rf_tx_power_get(void)
+{
+  return radio_tx_power;
+}
+
+/*
+ * \brief Function enables the usage of Antenna diversity.
+ *
+ * \param none
+ *
+ * \return 0 Success
+ */
+MBED_UNUSED static int8_t rf_enable_antenna_diversity(void)
+{
+    int8_t ret_val = 0;
+    rf_use_antenna_diversity = 1;
+    return ret_val;
+}
+
+/*
+ * \brief Function gives the control of RF states to MAC.
+ *
+ * \param new_state RF state
+ * \param rf_channel RF channel
+ *
+ * \return 0 Success
+ */
+static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
+{
+    int8_t ret_val = 0;
+    switch (new_state)
+    {
+        /*Reset PHY driver and set to idle*/
+        case PHY_INTERFACE_RESET:
+            break;
+        /*Disable PHY Interface driver*/
+        case PHY_INTERFACE_DOWN:
+            rf_shutdown();
+            break;
+        /*Enable PHY Interface driver*/
+        case PHY_INTERFACE_UP:
+            rf_mode = RF_MODE_NORMAL;
+            rf_channel_set(rf_channel);
+            rf_receive();
+            rf_if_enable_irq();
+            break;
+        /*Enable wireless interface ED scan mode*/
+        case PHY_INTERFACE_RX_ENERGY_STATE:
+            rf_mode = RF_MODE_ED;
+            rf_channel_set(rf_channel);
+            rf_receive();
+            rf_if_disable_irq();
+            // Read status to clear pending flags.
+            rf_if_read_register(IRQ_STATUS);
+            // Must set interrupt mask to be able to read IRQ status. GPIO interrupt is disabled.
+            rf_if_enable_cca_ed_done_interrupt();
+            // ED can be initiated by writing arbitrary value to PHY_ED_LEVEL
+            rf_if_write_register(PHY_ED_LEVEL, 0xff);
+            break;
+        case PHY_INTERFACE_SNIFFER_STATE:             /**< Enable Sniffer state */
+            rf_mode = RF_MODE_SNIFFER;
+            rf_channel_set(rf_channel);
+            rf_flags_clear(RFF_RX);
+            rf_receive();
+            rf_if_enable_irq();
+            break;
+    }
+    return ret_val;
+}
+
+/*
+ * \brief Function controls the ACK pending, channel setting and energy detection.
+ *
+ * \param extension_type Type of control
+ * \param data_ptr Data from NET library
+ *
+ * \return 0 Success
+ */
+static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
+{
+    switch (extension_type)
+    {
+        /*Control MAC pending bit for Indirect data transmission*/
+        case PHY_EXTENSION_CTRL_PENDING_BIT:
+            if(*data_ptr)
+            {
+                rf_if_ack_pending_ctrl(1);
+            }
+            else
+            {
+                rf_if_ack_pending_ctrl(0);
+            }
+            break;
+        /*Return frame pending status*/
+        case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
+            *data_ptr = rf_if_last_acked_pending();
+            break;
+        /*Set channel*/
+        case PHY_EXTENSION_SET_CHANNEL:
+            break;
+        /*Read energy on the channel*/
+        case PHY_EXTENSION_READ_CHANNEL_ENERGY:
+            // End of the ED measurement is indicated by CCA_ED_DONE
+            while (!(rf_if_read_register(IRQ_STATUS) & CCA_ED_DONE));
+            // RF input power: RSSI base level + 1[db] * PHY_ED_LEVEL
+            *data_ptr = rf_sensitivity + rf_if_read_register(PHY_ED_LEVEL);
+            // Read status to clear pending flags.
+            rf_if_read_register(IRQ_STATUS);
+            // Next ED measurement is started, next PHY_EXTENSION_READ_CHANNEL_ENERGY call will return the result.
+            rf_if_write_register(PHY_ED_LEVEL, 0xff);
+            break;
+        /*Read status of the link*/
+        case PHY_EXTENSION_READ_LINK_STATUS:
+            break;
+        default:
+            break;
+    }
+    return 0;
+}
+
+/*
+ * \brief Function sets the addresses to RF address filters.
+ *
+ * \param address_type Type of address
+ * \param address_ptr Pointer to given address
+ *
+ * \return 0 Success
+ */
+static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
+{
+    int8_t ret_val = 0;
+    switch (address_type)
+    {
+        /*Set 48-bit address*/
+        case PHY_MAC_48BIT:
+            break;
+            /*Set 64-bit address*/
+        case PHY_MAC_64BIT:
+            rf_set_address(address_ptr);
+            break;
+        /*Set 16-bit address*/
+        case PHY_MAC_16BIT:
+            rf_set_short_adr(address_ptr);
+            break;
+        /*Set PAN Id*/
+        case PHY_MAC_PANID:
+            rf_set_pan_id(address_ptr);
+            break;
+    }
+    return ret_val;
+}
+
+/*
+ * \brief Function initialises the ACK wait time and returns the used PHY mode.
+ *
+ * \param none
+ *
+ * \return tmp Used PHY mode
+ */
+static void rf_init_phy_mode(void)
+{
+    uint8_t tmp = 0;
+    uint8_t part = rf_if_read_part_num();
+    /*Read used PHY Mode*/
+    tmp = rf_if_read_register(TRX_CTRL_2);
+    /*Set ACK wait time for used data rate*/
+    if(part == PART_AT86RF212)
+    {
+        if((tmp & 0x1f) == 0x00)
+        {
+            rf_sensitivity = -110;
+            rf_ack_wait_duration = 938;
+            tmp = BPSK_20;
+        }
+        else if((tmp & 0x1f) == 0x04)
+        {
+            rf_sensitivity = -108;
+            rf_ack_wait_duration = 469;
+            tmp = BPSK_40;
+        }
+        else if((tmp & 0x1f) == 0x14)
+        {
+            rf_sensitivity = -108;
+            rf_ack_wait_duration = 469;
+            tmp = BPSK_40_ALT;
+        }
+        else if((tmp & 0x1f) == 0x08)
+        {
+            rf_sensitivity = -101;
+            rf_ack_wait_duration = 50;
+            tmp = OQPSK_SIN_RC_100;
+        }
+        else if((tmp & 0x1f) == 0x09)
+        {
+            rf_sensitivity = -99;
+            rf_ack_wait_duration = 30;
+            tmp = OQPSK_SIN_RC_200;
+        }
+        else if((tmp & 0x1f) == 0x18)
+        {
+            rf_sensitivity = -102;
+            rf_ack_wait_duration = 50;
+            tmp = OQPSK_RC_100;
+        }
+        else if((tmp & 0x1f) == 0x19)
+        {
+            rf_sensitivity = -100;
+            rf_ack_wait_duration = 30;
+            tmp = OQPSK_RC_200;
+        }
+        else if((tmp & 0x1f) == 0x0c)
+        {
+            rf_sensitivity = -100;
+            rf_ack_wait_duration = 20;
+            tmp = OQPSK_SIN_250;
+        }
+        else if((tmp & 0x1f) == 0x0d)
+        {
+            rf_sensitivity = -98;
+            rf_ack_wait_duration = 25;
+            tmp = OQPSK_SIN_500;
+        }
+        else if((tmp & 0x1f) == 0x0f)
+        {
+            rf_sensitivity = -98;
+            rf_ack_wait_duration = 25;
+            tmp = OQPSK_SIN_500_ALT;
+        }
+        else if((tmp & 0x1f) == 0x1c)
+        {
+            rf_sensitivity = -101;
+            rf_ack_wait_duration = 20;
+            tmp = OQPSK_RC_250;
+        }
+        else if((tmp & 0x1f) == 0x1d)
+        {
+            rf_sensitivity = -99;
+            rf_ack_wait_duration = 25;
+            tmp = OQPSK_RC_500;
+        }
+        else if((tmp & 0x1f) == 0x1f)
+        {
+            rf_sensitivity = -99;
+            rf_ack_wait_duration = 25;
+            tmp = OQPSK_RC_500_ALT;
+        }
+        else if((tmp & 0x3f) == 0x2A)
+        {
+            rf_sensitivity = -91;
+            rf_ack_wait_duration = 25;
+            tmp = OQPSK_SIN_RC_400_SCR_ON;
+        }
+        else if((tmp & 0x3f) == 0x0A)
+        {
+            rf_sensitivity = -91;
+            rf_ack_wait_duration = 25;
+            tmp = OQPSK_SIN_RC_400_SCR_OFF;
+        }
+        else if((tmp & 0x3f) == 0x3A)
+        {
+            rf_sensitivity = -97;
+            rf_ack_wait_duration = 25;
+            tmp = OQPSK_RC_400_SCR_ON;
+        }
+        else if((tmp & 0x3f) == 0x1A)
+        {
+            rf_sensitivity = -97;
+            rf_ack_wait_duration = 25;
+            tmp = OQPSK_RC_400_SCR_OFF;
+        }
+        else if((tmp & 0x3f) == 0x2E)
+        {
+            rf_sensitivity = -93;
+            rf_ack_wait_duration = 13;
+            tmp = OQPSK_SIN_1000_SCR_ON;
+        }
+        else if((tmp & 0x3f) == 0x0E)
+        {
+            rf_sensitivity = -93;
+            rf_ack_wait_duration = 13;
+            tmp = OQPSK_SIN_1000_SCR_OFF;
+        }
+        else if((tmp & 0x3f) == 0x3E)
+        {
+            rf_sensitivity = -95;
+            rf_ack_wait_duration = 13;
+            tmp = OQPSK_RC_1000_SCR_ON;
+        }
+        else if((tmp & 0x3f) == 0x1E)
+        {
+            rf_sensitivity = -95;
+            rf_ack_wait_duration = 13;
+            tmp = OQPSK_RC_1000_SCR_OFF;
+        }
+    }
+    else
+    {
+        rf_sensitivity = -101;
+        rf_ack_wait_duration = 20;
+    }
+    /*Board design might reduces the sensitivity*/
+    //rf_sensitivity += RF_SENSITIVITY_CALIBRATION;
+}
+
+
+static uint8_t rf_scale_lqi(int8_t rssi)
+{
+    uint8_t scaled_lqi;
+
+    /*rssi < RF sensitivity*/
+    if(rssi < rf_sensitivity)
+        scaled_lqi=0;
+    /*-91 dBm < rssi < -81 dBm (AT86RF233 XPro)*/
+    /*-90 dBm < rssi < -80 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 10))
+        scaled_lqi=31;
+    /*-81 dBm < rssi < -71 dBm (AT86RF233 XPro)*/
+    /*-80 dBm < rssi < -70 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 20))
+        scaled_lqi=207;
+    /*-71 dBm < rssi < -61 dBm (AT86RF233 XPro)*/
+    /*-70 dBm < rssi < -60 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 30))
+        scaled_lqi=255;
+    /*-61 dBm < rssi < -51 dBm (AT86RF233 XPro)*/
+    /*-60 dBm < rssi < -50 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 40))
+        scaled_lqi=255;
+    /*-51 dBm < rssi < -41 dBm (AT86RF233 XPro)*/
+    /*-50 dBm < rssi < -40 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 50))
+        scaled_lqi=255;
+    /*-41 dBm < rssi < -31 dBm (AT86RF233 XPro)*/
+    /*-40 dBm < rssi < -30 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 60))
+        scaled_lqi=255;
+    /*-31 dBm < rssi < -21 dBm (AT86RF233 XPro)*/
+    /*-30 dBm < rssi < -20 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 70))
+        scaled_lqi=255;
+    /*rssi > RF saturation*/
+    else if(rssi > (rf_sensitivity + 80))
+        scaled_lqi=111;
+    /*-21 dBm < rssi < -11 dBm (AT86RF233 XPro)*/
+    /*-20 dBm < rssi < -10 dBm (AT86RF212B XPro)*/
+    else
+        scaled_lqi=255;
+
+    return scaled_lqi;
+}
+
+NanostackRfPhyAtmel::NanostackRfPhyAtmel(PinName spi_mosi, PinName spi_miso,
+        PinName spi_sclk, PinName spi_cs,  PinName spi_rst, PinName spi_slp, PinName spi_irq,
+        PinName i2c_sda, PinName i2c_scl)
+    : _mac(i2c_sda, i2c_scl), _mac_addr(), _rf(NULL), _mac_set(false),
+      _spi_mosi(spi_mosi), _spi_miso(spi_miso), _spi_sclk(spi_sclk),
+      _spi_cs(spi_cs), _spi_rst(spi_rst), _spi_slp(spi_slp), _spi_irq(spi_irq)
+{
+    _rf = new RFBits(_spi_mosi, _spi_miso, _spi_sclk, _spi_cs, _spi_rst, _spi_slp, _spi_irq);
+}
+
+NanostackRfPhyAtmel::~NanostackRfPhyAtmel()
+{
+    delete _rf;
+}
+
+int8_t NanostackRfPhyAtmel::rf_register()
+{
+    if (NULL == _rf) {
+        return -1;
+    }
+
+    rf_if_lock();
+
+    if (rf != NULL) {
+        rf_if_unlock();
+        error("Multiple registrations of NanostackRfPhyAtmel not supported");
+        return -1;
+    }
+
+    // Read the mac address if it hasn't been set by a user
+    rf = _rf;
+    if (!_mac_set) {
+        int ret = _mac.read_eui64((void*)_mac_addr);
+        if (ret < 0) {
+            rf = NULL;
+            rf_if_unlock();
+            return -1;
+        }
+    }
+
+    int8_t radio_id = rf_device_register(_mac_addr);
+    if (radio_id < 0) {
+        rf = NULL;
+    }
+
+    rf_if_unlock();
+    return radio_id;
+}
+
+void NanostackRfPhyAtmel::rf_unregister()
+{
+    rf_if_lock();
+
+    if (NULL == rf) {
+        rf_if_unlock();
+        return;
+    }
+
+    rf_device_unregister();
+    rf = NULL;
+
+    rf_if_unlock();
+}
+
+void NanostackRfPhyAtmel::get_mac_address(uint8_t *mac)
+{
+    rf_if_lock();
+
+    if (NULL == rf) {
+        error("NanostackRfPhyAtmel Must be registered to read mac address");
+        rf_if_unlock();
+        return;
+    }
+    memcpy((void*)mac, (void*)_mac_addr, sizeof(_mac_addr));
+
+    rf_if_unlock();
+}
+
+void NanostackRfPhyAtmel::set_mac_address(uint8_t *mac)
+{
+    rf_if_lock();
+
+    if (NULL != rf) {
+        error("NanostackRfPhyAtmel cannot change mac address when running");
+        rf_if_unlock();
+        return;
+    }
+    memcpy((void*)_mac_addr, (void*)mac, sizeof(_mac_addr));
+    _mac_set = true;
+
+    rf_if_unlock();
+}
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/source/at24mac.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/source/at24mac.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016-2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "at24mac.h"
+
+/* Device addressing */
+#define AT24MAC_EEPROM_ADDRESS		(0x0A<<4)
+#define AT24MAC_RW_PROTECT_ADDRESS	(0x06<<4)
+#define AT24MAC_SERIAL_ADDRESS		(0x0B<<4)
+
+/* Known memory blocks */
+#define AT24MAC_SERIAL_OFFSET	(0x80)
+#define AT24MAC_EUI64_OFFSET	(0x98)
+#define AT24MAC_EUI48_OFFSET	(0x9A)
+
+#define SERIAL_LEN 16
+#define EUI64_LEN 8
+#define EUI48_LEN 6
+
+AT24Mac::AT24Mac(PinName sda, PinName scl) : _i2c(sda, scl)
+{
+    // Do nothing
+}
+
+int AT24Mac::read_serial(void *buf)
+{
+    char offset = AT24MAC_SERIAL_OFFSET;
+    if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true))
+        return -1; //No ACK
+    return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char*)buf, SERIAL_LEN);
+}
+
+int AT24Mac::read_eui64(void *buf)
+{
+    char offset = AT24MAC_EUI64_OFFSET;
+    if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true))
+        return -1; //No ACK
+    return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char*)buf, EUI64_LEN);
+}
+
+int AT24Mac::read_eui48(void *buf)
+{
+    char offset = AT24MAC_EUI48_OFFSET;
+    if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true))
+        return -1; //No ACK
+    return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char*)buf, EUI48_LEN);
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/atmel-rf-driver/source/at24mac.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/atmel-rf-driver/source/at24mac.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef AT24MAC_H
+#define AT24MAC_H
+
+#include "PinNames.h"
+#include "I2C.h"
+
+/*
+ * AT24MAC drivers.
+ *
+ * This is a EEPROM chip designed to contain factory programmed read-only EUI-64 or EUI-48,
+ * a 128bit serial number and some user programmable EEPROM.
+ *
+ * AT24MAC602 contains EUI-64, use read_eui64()
+ * AT24MAC402 contains EUI-64, use read_eui48()
+ *
+ * NOTE: You cannot use both EUI-64 and EUI-48. Chip contains only one of those.
+ */
+
+class AT24Mac {
+public:
+    AT24Mac(PinName sda, PinName scl);
+
+    /**
+     * Read unique serial number from chip.
+     * \param buf pointer to write serial number to. Must have space for 16 bytes.
+     * \return zero on success, negative number on failure
+     */
+    int read_serial(void *buf);
+
+    /**
+     * Read EUI-64 from chip.
+     * \param buf pointer to write EUI-64 to. Must have space for 8 bytes.
+     * \return zero on success, negative number on failure
+     */
+    int read_eui64(void *buf);
+
+    /**
+     * Read EUI-48 from chip.
+     * \param buf pointer to write EUI-48 to. Must have space for 6 bytes.
+     * \return zero on success, negative number on failure
+     */
+    int read_eui48(void *buf);
+
+private:
+    mbed::I2C _i2c;
+};
+
+#endif /* AT24MAC_H */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/easy-connect.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/easy-connect.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,135 @@
+#ifndef __MAGIC_CONNECT_H__
+#define __MAGIC_CONNECT_H__
+
+#include "mbed.h"
+
+#define ETHERNET        1
+#define WIFI_ESP8266    2
+#define MESH_LOWPAN_ND  3
+#define MESH_THREAD     4
+#define WIFI_ODIN       5
+
+#if MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ESP8266
+#include "ESP8266Interface.h"
+
+#ifdef MBED_CONF_APP_ESP8266_DEBUG
+ESP8266Interface wifi(MBED_CONF_APP_ESP8266_TX, MBED_CONF_APP_ESP8266_RX, MBED_CONF_APP_ESP8266_DEBUG);
+#else
+ESP8266Interface wifi(MBED_CONF_APP_ESP8266_TX, MBED_CONF_APP_ESP8266_RX);
+#endif
+
+#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ODIN
+#include "OdinWiFiInterface.h"
+OdinWiFiInterface wifi;
+#elif MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET
+#include "EthernetInterface.h"
+EthernetInterface eth;
+#elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_LOWPAN_ND
+#define MESH
+#include "NanostackInterface.h"
+LoWPANNDInterface mesh;
+#elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_THREAD
+#define MESH
+#include "NanostackInterface.h"
+ThreadInterface mesh;
+#else
+#error "No connectivity method chosen. Please add 'config.network-interfaces.value' to your mbed_app.json (see README.md for more information)."
+#endif
+
+#if defined(MESH)
+#if MBED_CONF_APP_MESH_RADIO_TYPE == ATMEL
+#include "NanostackRfPhyAtmel.h"
+NanostackRfPhyAtmel rf_phy(ATMEL_SPI_MOSI, ATMEL_SPI_MISO, ATMEL_SPI_SCLK, ATMEL_SPI_CS,
+                           ATMEL_SPI_RST, ATMEL_SPI_SLP, ATMEL_SPI_IRQ, ATMEL_I2C_SDA, ATMEL_I2C_SCL);
+#elif MBED_CONF_APP_MESH_RADIO_TYPE == MCR20
+#include "NanostackRfPhyMcr20a.h"
+NanostackRfPhyMcr20a rf_phy(MCR20A_SPI_MOSI, MCR20A_SPI_MISO, MCR20A_SPI_SCLK, MCR20A_SPI_CS, MCR20A_SPI_RST, MCR20A_SPI_IRQ);
+#elif MBED_CONF_APP_MESH_RADIO_TYPE == SPIRIT1
+#include "NanostackRfPhySpirit1.h"
+NanostackRfPhySpirit1 rf_phy(SPIRIT1_SPI_MOSI, SPIRIT1_SPI_MISO, SPIRIT1_SPI_SCLK,
+			     SPIRIT1_DEV_IRQ, SPIRIT1_DEV_CS, SPIRIT1_DEV_SDN, SPIRIT1_BRD_LED);
+#endif //MBED_CONF_APP_RADIO_TYPE
+#endif //MESH
+
+#ifndef MESH
+// This is address to mbed Device Connector
+#define MBED_SERVER_ADDRESS "coap://api.connector.mbed.com:5684"
+#else
+// This is address to mbed Device Connector
+#define MBED_SERVER_ADDRESS "coaps://[2607:f0d0:2601:52::20]:5684"
+#endif
+
+#ifdef MBED_CONF_APP_ESP8266_SSID
+#define MBED_CONF_APP_WIFI_SSID MBED_CONF_APP_ESP8266_SSID
+#endif
+
+#ifdef MBED_CONF_APP_ESP8266_PASSWORD
+#define MBED_CONF_APP_WIFI_PASSWORD MBED_CONF_APP_ESP8266_PASSWORD
+#endif
+
+
+NetworkInterface* easy_connect(bool log_messages = false) {
+    NetworkInterface* network_interface = 0;
+    int connect_success = -1;
+#if MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ESP8266
+    if (log_messages) {
+        printf("[EasyConnect] Using WiFi (ESP8266) \n");
+        printf("[EasyConnect] Connecting to WiFi %s\n", MBED_CONF_APP_WIFI_SSID);
+    }
+    connect_success = wifi.connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2);
+    network_interface = &wifi;
+#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ODIN
+    if (log_messages) {
+        printf("[EasyConnect] Using WiFi (ODIN) \n");
+        printf("[EasyConnect] Connecting to WiFi %s\n", MBED_CONF_APP_WIFI_SSID);
+    }
+    connect_success = wifi.connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, NSAPI_SECURITY_WPA_WPA2);
+    network_interface = &wifi;
+#elif MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET
+    if (log_messages) {
+        printf("[EasyConnect] Using Ethernet\n");
+    }
+    connect_success = eth.connect();
+    network_interface = &eth;
+#endif
+#ifdef MESH
+    if (log_messages) {
+        printf("[EasyConnect] Using Mesh\n");
+        printf("[EasyConnect] Connecting to Mesh..\n");
+    }
+    mesh.initialize(&rf_phy);
+    connect_success = mesh.connect();
+    network_interface = &mesh;
+#endif
+    if(connect_success == 0) {
+        if (log_messages) {
+            printf("[EasyConnect] Connected to Network successfully\n");
+        }
+    } else {
+        if (log_messages) {
+            printf("[EasyConnect] Connection to Network Failed %d!\n", connect_success);
+        }
+        return NULL;
+    }
+    const char *ip_addr  = network_interface->get_ip_address();
+    const char *mac_addr = network_interface->get_mac_address();
+    if (ip_addr == NULL) {
+        if (log_messages) {
+            printf("[EasyConnect] ERROR - No IP address\n");
+        }
+        return NULL;
+    }
+    if (mac_addr == NULL) {
+        if (log_messages) {
+            printf("[EasyConnect] ERROR - No MAC address\n");
+        }
+        return NULL;
+    }
+    if (log_messages) {
+        printf("[EasyConnect] IP address %s\n", ip_addr);
+        printf("[EasyConnect] MAC address %s\n", mac_addr);
+    }
+    return network_interface;
+}
+
+#endif // __MAGIC_CONNECT_H__
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/esp8266-driver/#4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/FETCH_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/FETCH_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb		branch 'master' of https://github.com/ARMmbed/esp8266-driver
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/ORIG_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/ORIG_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/config
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/config	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/esp8266-driver/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/description
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/description	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/hooks/applypatch-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/hooks/applypatch-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/hooks/commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/hooks/commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/hooks/post-update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/hooks/post-update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/hooks/pre-applypatch.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/hooks/pre-applypatch.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/hooks/pre-commit.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/hooks/pre-commit.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/hooks/pre-rebase.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/hooks/pre-rebase.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/hooks/prepare-commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/hooks/prepare-commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/hooks/update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/hooks/update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/index
Binary file easy-connect/esp8266-driver/.git/index has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/info/exclude
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/info/exclude	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,26 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
+ESP8266/ATParser
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/logs/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/logs/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036523 +0000	clone: from https://github.com/ARMmbed/esp8266-driver/
+4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb 4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036523 +0000	checkout: moving from master to 4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb
+4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb 4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036523 +0000	checkout: moving from 4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb to master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/logs/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/logs/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036523 +0000	clone: from https://github.com/ARMmbed/esp8266-driver/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/logs/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/logs/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036523 +0000	clone: from https://github.com/ARMmbed/esp8266-driver/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/07/bcb9b245abc132562d04eda40e8a19f1597603
Binary file easy-connect/esp8266-driver/.git/objects/07/bcb9b245abc132562d04eda40e8a19f1597603 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/09/3cbfaa677ad0f1a8b2e9e71e5eb3c9b59e5c6c
Binary file easy-connect/esp8266-driver/.git/objects/09/3cbfaa677ad0f1a8b2e9e71e5eb3c9b59e5c6c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/16/80c8292e1addcea4defbe1d2469c4106964e89
Binary file easy-connect/esp8266-driver/.git/objects/16/80c8292e1addcea4defbe1d2469c4106964e89 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/18/7bb094d5f1910589e4bd343db0ce1fa0868c5f
Binary file easy-connect/esp8266-driver/.git/objects/18/7bb094d5f1910589e4bd343db0ce1fa0868c5f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/19/6587025cf513267b3951ed7ae861f6b5887854
Binary file easy-connect/esp8266-driver/.git/objects/19/6587025cf513267b3951ed7ae861f6b5887854 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/19/99dae3ef80f9c4cb363ee01d9696dca1e4ad61
Binary file easy-connect/esp8266-driver/.git/objects/19/99dae3ef80f9c4cb363ee01d9696dca1e4ad61 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/1c/f9de7a21e429683d2eb0b66fe432ed62076940
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/1c/f9de7a21e429683d2eb0b66fe432ed62076940	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xŽÑJÄ0E}ÎWûî’IÒd"‚>ŠëL“	-Ò풤âç[ëø4—áÞÃIë²Ì¬w½Š@ÙÖì2æTŒu4Lät¼.>—¹Xuã*×ãHH¦8Ça@#}6qLÁ:æX°`̦(Þú´VxžêÜúz›¤Â+·¾Ÿ‡4áiëòÍí,y{t>–ÜëAk•Ñßþ¿ê]¾¤v8]d·ç.0_w`á$Pêº@ëœ>÷'¼\ÞÈxRêcšÔc×àÏHtŠL½%[&(:Æ´ƒL&Œž}DögõÞokû
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/1d/a853686baeb82ad49a3096a35a6039e3784d0f
Binary file easy-connect/esp8266-driver/.git/objects/1d/a853686baeb82ad49a3096a35a6039e3784d0f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/1f/ebc6b296641ca1db45adc9dbeb6cd07a0c826f
Binary file easy-connect/esp8266-driver/.git/objects/1f/ebc6b296641ca1db45adc9dbeb6cd07a0c826f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/1f/fb7d341d8e640475216fbe547a27a414b6da8c
Binary file easy-connect/esp8266-driver/.git/objects/1f/fb7d341d8e640475216fbe547a27a414b6da8c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/22/3dd241b1fc8f44dd138118cf6fec74cd1a9bc0
Binary file easy-connect/esp8266-driver/.git/objects/22/3dd241b1fc8f44dd138118cf6fec74cd1a9bc0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/28/42cffee5a2e5ced2dd2be10ebef3706f615b42
Binary file easy-connect/esp8266-driver/.git/objects/28/42cffee5a2e5ced2dd2be10ebef3706f615b42 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/29/cc547a20c724f7bc42b054348b67bbeaed6b19
Binary file easy-connect/esp8266-driver/.git/objects/29/cc547a20c724f7bc42b054348b67bbeaed6b19 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/29/d63ae2ee0a233e2fbd9577cdddc7661bb783d1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/29/d63ae2ee0a233e2fbd9577cdddc7661bb783d1	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xm»NÄ0D©óW¢ÞÅv®GZ¡Ý
+šmøäØ×I´y?$öï	QQMsæhÆ®ó<f¨Uý#´è¡ò(ÛFc97„BwÒZ…ž´A"åDSiɀ’Y˅ÖJzßµl;OÒxÞÖJp…ÈzóÇ«ÚÉ%¹½ðLÛÚ8ÿ]ã(µEÝrR¼Æ¦2%k„žnw8ÙÁ¤Lñ\2}št$WžcÕ`
p`’±Êþ\Ù0xókéà´¬‘Ât?÷cJw܀jՕbOÊ4A¤B)ã×.o×¹#÷”V{£|0ÖRعH)UÕÅ9H%„5fðÛØH¹Äe\z´ÍøåvÕ®xß_$»v
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/2b/043ceb297fac4e61b9692b067dc0aa687e908e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/2b/043ceb297fac4e61b9692b067dc0aa687e908e	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xOANÃ0äìW슜Øq„Á…¨ÖÞub•Ø•í@û{L%>ÀiwF3³³.­k¨ ÌxS33uÆ©I;+µ×Ö"I©ï¤â•ò^r¯­Ä	3Ç
+äÔޚÁá¸ßÓd&D=õ^éÑô†¼áÎJۑ—·º¤OK¥¦ÓÂ^±Ô6îÝr]·Êg,·LÛtz”FÉAØI#¥p×¢¿úGˆ—pf\m˜·P/À9§\À紂KÑWCœaåÕ¶C~‹
§X„xfbó†6ÕÞ¹~§||‹­Gǀ‘þȏŠîx'v0s{¹T{‰¸rÃHt X…ógñÕ»}Þ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/2b/ac3dde128ea49dfedcf71a634d278a4d183721
Binary file easy-connect/esp8266-driver/.git/objects/2b/ac3dde128ea49dfedcf71a634d278a4d183721 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/2c/b42275ecb72337156ccc82bd4b294c76478cc8
Binary file easy-connect/esp8266-driver/.git/objects/2c/b42275ecb72337156ccc82bd4b294c76478cc8 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/2d/4c36ef2e6528e1c8327babe5bedd834d6e558d
Binary file easy-connect/esp8266-driver/.git/objects/2d/4c36ef2e6528e1c8327babe5bedd834d6e558d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/2e/9e58d448e915e171348d6fcc3881e007359e87
Binary file easy-connect/esp8266-driver/.git/objects/2e/9e58d448e915e171348d6fcc3881e007359e87 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/35/4b47b19c9e48a6d2cc99bfb84838355ff8e59b
Binary file easy-connect/esp8266-driver/.git/objects/35/4b47b19c9e48a6d2cc99bfb84838355ff8e59b has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/36/dcaec219088ae255ccd1b63a6bd213ea08b43a
Binary file easy-connect/esp8266-driver/.git/objects/36/dcaec219088ae255ccd1b63a6bd213ea08b43a has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/37/084b5e2bef8a8997323b0afb3d664c5143a7ed
Binary file easy-connect/esp8266-driver/.git/objects/37/084b5e2bef8a8997323b0afb3d664c5143a7ed has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/3b/6d076031a93285f075bf9342b24b64db0e6082
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/3b/6d076031a93285f075bf9342b24b64db0e6082	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x•ANÃ0EY糡Vvlj„lX°q€ñxÜX$vä¸M{{šŠ°ÿÿ§OišBÕÈ»’™Á÷Æ6Ò)o´‘U§,×$)¬’Ê ©µnU5cæXÀµž”E_wޒíXw¦¯…éÑ·%ê©V,q…Ç2¤aÀ0ÂWIŒéOëô²LÉñ>åÃ3ȦÕ}£–ð(¤Ýü
+ÿ?Y}Ï; ”ÖPxýÎà¯"»ÝiDÀèÀ"ý¬˜7pš±Ø0†rÙÃ[8ßÂч,e+¹ÑGï9³[8a8þu…b*0g^¶gî¯kÕ/àçpj
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/40/050a429b64dacc27067d0c6f5ec1aa9858cedd
Binary file easy-connect/esp8266-driver/.git/objects/40/050a429b64dacc27067d0c6f5ec1aa9858cedd has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/45/0cc128865ffb90b5cbfe5af193621644024fa7
Binary file easy-connect/esp8266-driver/.git/objects/45/0cc128865ffb90b5cbfe5af193621644024fa7 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/4a/3f18ae22a0402db6001e0b2145f79693c66a7f
Binary file easy-connect/esp8266-driver/.git/objects/4a/3f18ae22a0402db6001e0b2145f79693c66a7f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/4e/d87bf7fe37d5ba0de6c4e78868f604a82f8ecb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/4e/d87bf7fe37d5ba0de6c4e78868f604a82f8ecb	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+xmËJ1E]÷W¸ͳ;
ƒÌàÂÙ.üJR™4ôË<Àù{ã€;WUÎ¥¨ë¶e™
+H-J"A#iã•24rM|àRßç¤1œ¤Éݎ‰Öˆ6¼A/¸ö‚Öséñ9zRÂöZýç=
+g—Æ¢dQJzTbpÁºžlCc‡µÄ-ÁkLS.Û)Ásiãèâ}9ÕBߘŸÈ×àÊ(¡£4XÏXçîýúoS¹TÇuK´Ï·Óu*±Ú§&üëÞ)]	ö:ϐè«R.ð(„´-1a\0åx{Ærð´wÝÙ{òpþüh¸Ã™Z;XæÉB³hõ´ºÛ±q_
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/58/8eb441e386da562bc0b29358186a0414b2eb21
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/58/8eb441e386da562bc0b29358186a0414b2eb21	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x=Ž»N1D©÷+nˆìõs¥…Hé"(¨¯íkÅڇ#¯—E|=†‚nÎHg4>ÏsªÐkùP uŠ÷jà}$-Þ£…2ŒSÖ0ï]wÇBK= 
+?ÈàEtžE䂔<£AÙ`¬	Üx‹ºÃ­Þr3–J#¼có¾Ž	Žn›Ò:á~šÒ²}|žŸK#¸±L2xdœ±®µíg¥oÛºÂy«SËÇÒààþà„eþ—rÙÃSMT õÞ[­!”ôÙܚa¡>Òkº,m8¢'x¹^ºßoUÍ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/58/e9a0ed3ecc7e05ddf9578c6153c2a4882e8484
Binary file easy-connect/esp8266-driver/.git/objects/58/e9a0ed3ecc7e05ddf9578c6153c2a4882e8484 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/60/7744089602deb46784e2f5d7bd815837f65a1f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/60/7744089602deb46784e2f5d7bd815837f65a1f	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+x•ÐQJÄ0`ŸsŠ¹ÀJš4i"."¸‚4ùkBm³¦Sõøv‹ðiæáçû‡ñyš“ÖÝ
€T¨½¶¬Q-*ßjÕô®‡éB«ë`aLÄÅÌL•º€Æ©
+µêl«ƒB/{kÔZ!X%ÛÕR¸•c.ôKZ8_"
+=»…·qçã¾<¬Œ·Ü"¬÷TÕ¶k¤ªLEi¤~?ôšÿÑlÐ!Ž! —ô•Ü½ƒßv~¤	S¿ÁÃ:{Ny&Îôôzn•µ§ykœ‡/Ž}ÄBnG
+>×T0]°Å9‚fðw.ãaÉ~Óñ|¿VÆqy
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/63/6af254ddfee68e83cd550e5184e253efa469a0
Binary file easy-connect/esp8266-driver/.git/objects/63/6af254ddfee68e83cd550e5184e253efa469a0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/63/da515ed94f2f08c3adf90b51458c4891e61347
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/63/da515ed94f2f08c3adf90b51458c4891e61347	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x•ŽÁJÅ0E]÷+æ”$¤)ˆ(nü™N&¶<ڄd
+~¾õ-Ü»ºwq8.û¾)¸´‰ÀŒÉ†Œ~ž[K‚..ž9`–H(’›†JMô†ÙºƒÏy™Í.Y<e;Áـhfš:u-
Þ׶u-u•Ôõšg^ïçõTù¦þ$é|‹“5£›£GãøúËÿO1ŽŠá-%IÐÏZKSÈWN=Û±_PåRSJMz‡ÜʽðMô“˜¥êð†F_m
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/69/aa3c94dc3fbc0fa13e539c0e958d787d17c8a6
Binary file easy-connect/esp8266-driver/.git/objects/69/aa3c94dc3fbc0fa13e539c0e958d787d17c8a6 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/6f/c14e3cc6a40c322c8e5c4d8a2e9da552537027
Binary file easy-connect/esp8266-driver/.git/objects/6f/c14e3cc6a40c322c8e5c4d8a2e9da552537027 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/71/cc5953f21d106855490b4ff1b08472472c3a3d
Binary file easy-connect/esp8266-driver/.git/objects/71/cc5953f21d106855490b4ff1b08472472c3a3d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/72/02907f786dec6fedf5618a1df556ebf15679c1
Binary file easy-connect/esp8266-driver/.git/objects/72/02907f786dec6fedf5618a1df556ebf15679c1 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/74/b05f50b0d7e5e40753dceb5b55f44776572277
Binary file easy-connect/esp8266-driver/.git/objects/74/b05f50b0d7e5e40753dceb5b55f44776572277 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/76/27ac0bc2f5d7e79d81861e328d7a44757e81d0
Binary file easy-connect/esp8266-driver/.git/objects/76/27ac0bc2f5d7e79d81861e328d7a44757e81d0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/77/d37a0a4d1dcf2348571c8407560f6786e4daf3
Binary file easy-connect/esp8266-driver/.git/objects/77/d37a0a4d1dcf2348571c8407560f6786e4daf3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/83/1e027303af67fcf6df5adb872b801f6449ee3b
Binary file easy-connect/esp8266-driver/.git/objects/83/1e027303af67fcf6df5adb872b801f6449ee3b has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/83/76fae074f632e3ca81ce6dfc91944c3cb11847
Binary file easy-connect/esp8266-driver/.git/objects/83/76fae074f632e3ca81ce6dfc91944c3cb11847 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/85/42c211a5de5eeccef8a9a9997f9321ba6d880c
Binary file easy-connect/esp8266-driver/.git/objects/85/42c211a5de5eeccef8a9a9997f9321ba6d880c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/85/92c80138ba308aa332f6a427cfd97ac6eb3329
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/85/92c80138ba308aa332f6a427cfd97ac6eb3329	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x•ÁiÄ0DsV¿I–dBÈvHøÖ¯
+y‘µ‡í>
+¤œæðÞL:rÞÙ_ZÈb†â\Äl<ÌdF%¬)1h=~FœÔ+J#æeµË*‘Å/VG̘V˜À†Î.Á{ë?ÚvTúâʽ¿1d®ç6 \÷ԏkæý6¤#¿“qÑYFíèU­UoûΆœÿ#¨‹„.ߟÝÚ9|Ӊþƒè¶/$¸£JzªµVm
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/85/fbaf1da3ed19b09195fcb4138178b5f0f4c2c4
Binary file easy-connect/esp8266-driver/.git/objects/85/fbaf1da3ed19b09195fcb4138178b5f0f4c2c4 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/86/45716bafafd88b0d67b2c3d12b8b8e4bf46a0a
Binary file easy-connect/esp8266-driver/.git/objects/86/45716bafafd88b0d67b2c3d12b8b8e4bf46a0a has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/86/ed47c8bf40c86fdc569c7e678a8944f5e01c2a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/86/ed47c8bf40c86fdc569c7e678a8944f5e01c2a	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xmÉj1Dsž¯hÈَ4ÒôH`‚M ñŗä´´<"³E#çïãßrª¦ëUA¹ibê)'"-SÒ6T[
+Ê(­[QËL°Â#J×p)LK¾šM¢1ƒw¢µØ8£ÚÖkÔÆH]!Öè·Ìr؃wžÛ€èšœV¡'ªUpœD̓(±%W™’»)Á[—â’§¹£{³ä‹l\w;¶%ÓÙ,kòå¸T%ošV«Ümؕÿˆy_,lÆ)ÑÜÿn1wÅ®/À?±ê@éH0—¾‡D?…–Ï!¤i€Ýça°ä_B<¯¹Óõ¹2Þ'Z–ªzgˆãÉôÑÃ×ä¾)ïîÖ¥(—4’¿·<’*`y:
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/8a/21294bb1073d2d6804235b6bc6af2fb2d08ce6
Binary file easy-connect/esp8266-driver/.git/objects/8a/21294bb1073d2d6804235b6bc6af2fb2d08ce6 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/8a/ae3bd490162291eef8d92f0b169b9b8fd706a6
Binary file easy-connect/esp8266-driver/.git/objects/8a/ae3bd490162291eef8d92f0b169b9b8fd706a6 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/8b/3302ea06c0f2d012f20563700f48c7d75d4b3c
Binary file easy-connect/esp8266-driver/.git/objects/8b/3302ea06c0f2d012f20563700f48c7d75d4b3c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/8d/1823c75c461e49fa7dc8f7cd0bc3a4eb980ef6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/8d/1823c75c461e49fa7dc8f7cd0bc3a4eb980ef6	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+xTÛNÛ@í³¿b”¾r‚*BQÃ¥jTšH8!„¢=vVØ^wwIQûíÙØ\zIðCœÙŸ9sæسDÍ ··»ûÆëlnz°	#™ ÐuTDêvçîx¦%Ftì«È–Bc•‡-˜`š'Âbç2‹ëóHiH•±
++À.r4GvN)0"…X«;t§w¨TôÚ]t€ŽU¾Ð2ž[h°ÝííT‰3`f¨u‘…¨ÁιèVeZð­‚Þnw¡É*ÕØè3öBŠdÊBa0¤'Þ˜[ŠF”"Jiç®O…ÒfŒ«
+Cͬ rAäPÑóB¶"ÍêέÍ÷;²,ÛÂn+w’å8¦s6<>ù§[Dºzè"KÐÐø½šž-@äD*3ÚW"J UE¬‘rV1éRKKi©VÆLCi¬–³‚×õ¤Y5ÐäÏh!"ƒÆÀ‡¡ß€£?ô[r9œ|_Làrp~>M†§>ŒÏáx<:N†ãEŸ`0º‚/ÃÑI£Ýà}®y¢)YMt>mš·RS`ßplrd$-‹#Äd±ÅrÔ©4lCC¦”ÈTZaÝÑ_sq£ŽÞ[™I’¾.*{Ïžg+ÃAb89ôêüÁäp¿š…ÌìÎöԂ‘?pÃ{ðx“ÓYÁÈ°„	\sæ†|Å	þO¾-O‚…n²íèr?m¡³¾÷s=‹_4êÎ!&h®o‡W£>NQº!c´>mn€÷ðœ-Cš­C7LþCôNÉ^À-Gåóší´LT@rt+uô‹0ÅÔ m²˜-趖â½^©ϔ#Þ6ƒ¹ÐÔ,–‚CÏIÞéЛ»ô_"³[r©pß6zsJrE.ã÷kùýz4ÊÒ's÷÷S{زÒk¢··cME­Âj"ìà²÷neÉú
+}E’ó®ÅoÜóâ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/8e/0c9a889667fd3a837894a1cace2d8196a691a6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/8e/0c9a889667fd3a837894a1cace2d8196a691a6	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xŽÑN!E}æ+úN€Â$ƍïÆýJvW0ÿo݌‰¾´émÏ퍵”Ë€Y›»ÑˆÀi©é²ó˜(b¦”-*w‹´feÑ-Q‰¯Ðh£A™|Ò¤ŒÅuv³á²èÐFJ&¨Y{)³û8×ï{ïð¼OjðÐx˜ÖÛðZ™b- òtÎý´R
+V9â`à°—Ëâõ‹qÒ0.[ä	r«úñƒEx=½y(ÄK£Ÿ»þÔõJqtÈ{œÿ„-|Í·Õá1‰o-&hÜ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/8f/231b0645ab4e7081eccc0b3a1bf366c70634e7
Binary file easy-connect/esp8266-driver/.git/objects/8f/231b0645ab4e7081eccc0b3a1bf366c70634e7 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/8f/2bc9cd442ea21d44a52c8bab55333c6941fb17
Binary file easy-connect/esp8266-driver/.git/objects/8f/2bc9cd442ea21d44a52c8bab55333c6941fb17 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/90/10cd39078cc91486da1d08547eb05660362c2c
Binary file easy-connect/esp8266-driver/.git/objects/90/10cd39078cc91486da1d08547eb05660362c2c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/94/d0e46f45972aac11ae428b5cc64fe8a4ee6d27
Binary file easy-connect/esp8266-driver/.git/objects/94/d0e46f45972aac11ae428b5cc64fe8a4ee6d27 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/95/3bb50291cd5a3100d0e45b128a5d266235e24a
Binary file easy-connect/esp8266-driver/.git/objects/95/3bb50291cd5a3100d0e45b128a5d266235e24a has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/95/9c04625282673ad11f65ffd55ed8f97a1a0cea
Binary file easy-connect/esp8266-driver/.git/objects/95/9c04625282673ad11f65ffd55ed8f97a1a0cea has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/98/2da6743ef487d0d0947cb5fc1f0b305ff310d3
Binary file easy-connect/esp8266-driver/.git/objects/98/2da6743ef487d0d0947cb5fc1f0b305ff310d3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/9d/54161261715aa62843752a37a092b48db56c27
Binary file easy-connect/esp8266-driver/.git/objects/9d/54161261715aa62843752a37a092b48db56c27 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/a0/9061bb1823bd9c729a46cf3b2cd121063a5af1
Binary file easy-connect/esp8266-driver/.git/objects/a0/9061bb1823bd9c729a46cf3b2cd121063a5af1 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/a3/b83979ec8272d283fb1a2ad25c9b9e74d9e0cf
Binary file easy-connect/esp8266-driver/.git/objects/a3/b83979ec8272d283fb1a2ad25c9b9e74d9e0cf has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/a8/b5125912fe6450dcca33fa357ad7b5870cbeab
Binary file easy-connect/esp8266-driver/.git/objects/a8/b5125912fe6450dcca33fa357ad7b5870cbeab has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/a8/d252d67bcbf06bbeb53aff60cb01f96136ef92
Binary file easy-connect/esp8266-driver/.git/objects/a8/d252d67bcbf06bbeb53aff60cb01f96136ef92 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/aa/bf2bfd8ad215d2080613cfe16a1ade42b65525
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/aa/bf2bfd8ad215d2080613cfe16a1ade42b65525	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+xmÍNÃ0„9ç)VâL±ÿJj½ôÒ@k{ÝXŠ“à8*¼=¥7N3‡o4šñSΩB'íC-D`ƒ\ñVqÍ%¢jè´l±ÓÈlë„	N*ßêfÆBc£(퍋‚y£bðRY¯IiƒÆ
+%1î[üã#s䥵ŽËΆ 8Fã½GF•`\«¨4³±ÁµöS×¾¤¥NsOŽ¸Ô›l}7»µÒ.
+ëpa:Ý2«<1ÅXãïÃ~ù÷T«ƒí8š‡ïÝ%Õ~u›ðO¬9Q¹Ìë0@¡Ï•–
+ÜB,S†ýù”…g·iðú!|©iö!Àù°;69ÀõV1•|½ýiŒSÉXÓ4.?Ûs¡
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/ad/baed3a1a00735f51ba1e24c38d552a80acd3b8
Binary file easy-connect/esp8266-driver/.git/objects/ad/baed3a1a00735f51ba1e24c38d552a80acd3b8 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/b8/8add7ec5d94cae6d187ada1bcb5ab545eb846e
Binary file easy-connect/esp8266-driver/.git/objects/b8/8add7ec5d94cae6d187ada1bcb5ab545eb846e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/bb/8182f41bb5512e916d29be1c734aa9f1f19d2f
Binary file easy-connect/esp8266-driver/.git/objects/bb/8182f41bb5512e916d29be1c734aa9f1f19d2f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/c2/09d637a05d23a7390c41c594867e66cd7a2b61
Binary file easy-connect/esp8266-driver/.git/objects/c2/09d637a05d23a7390c41c594867e66cd7a2b61 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/c3/0ea2129fa524f9352ef4ec7388986fe0a3513f
Binary file easy-connect/esp8266-driver/.git/objects/c3/0ea2129fa524f9352ef4ec7388986fe0a3513f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/cc/460d8d2e1456b3734b3792da65ced4a132800f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/cc/460d8d2e1456b3734b3792da65ced4a132800f	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xPMKÄ0õœ_1àyKš6I‹¸ˆâMAoâ!ÓLl°mJ’.ûóM׫'OóÞ|¼÷˜!̳ÏÐôú&G" V ¾®ÔR×è„æ3Úôu£œDTZ#²ÕDZÊ!*˵âMmúFtÒq-ÑõM+P´¨Z‹œï3[C„‡1ú”Ã:R„g“r)Ça¼‚û-ÓŤŠìvu«”âZ	.9gÃ5è¾ÿo	öAií„RŸp²–,ÌT¬Ÿfp%ZvòË„-‚;`ápz‡Ý¹ÀÄØËßp1Ì`éì‚ò–_¥¢¿àæÅBÎÞ°ÁLšá»*šK×/ðøöº‡ª{òJpÛ´ûJê2
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/cc/760c5cfd58ef1044951e299f3ade8b9693ca1c
Binary file easy-connect/esp8266-driver/.git/objects/cc/760c5cfd58ef1044951e299f3ade8b9693ca1c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/cd/1bf66c5d69ec983c6dee28fc1e321f9f6467ec
Binary file easy-connect/esp8266-driver/.git/objects/cd/1bf66c5d69ec983c6dee28fc1e321f9f6467ec has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/d6/fc3baf28fbcb8e58792079af68bcc9c23e1dce
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/d6/fc3baf28fbcb8e58792079af68bcc9c23e1dce	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+xK
+Â0@]ç³$c>4 â\‰ˆÉÔŒS҉ÒÛ[÷n¼÷—2
+`p©DZLÑXÓÚ¢Íљ~ExäM¯÷SH*6¸Âyâø€‹ðŸü‚ûœæ™v\ïG@ë]g¼óÛ5§Uúþ„þ3-ü™ê:å(”ánÂ0·iâ*ÐS”ViVfð@‡
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/d9/141ca34383010414da53f1ca1b9e63f02d1c9c
Binary file easy-connect/esp8266-driver/.git/objects/d9/141ca34383010414da53f1ca1b9e63f02d1c9c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/d9/566bd8f78b611da45730ac75e7a07eca493a03
Binary file easy-connect/esp8266-driver/.git/objects/d9/566bd8f78b611da45730ac75e7a07eca493a03 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/da/dd0c5ed6c6246b0a1d800e832cf49b5ac008ea
Binary file easy-connect/esp8266-driver/.git/objects/da/dd0c5ed6c6246b0a1d800e832cf49b5ac008ea has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/db/de089f2f8ca06714f1f9c94212a5cb6d2aad02
Binary file easy-connect/esp8266-driver/.git/objects/db/de089f2f8ca06714f1f9c94212a5cb6d2aad02 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/dc/37b65ca877d969aa492f348626df6e1b0b1df0
Binary file easy-connect/esp8266-driver/.git/objects/dc/37b65ca877d969aa492f348626df6e1b0b1df0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/dd/16c394cb04f4bbad0e8d2103e5a33ff0e24bf5
Binary file easy-connect/esp8266-driver/.git/objects/dd/16c394cb04f4bbad0e8d2103e5a33ff0e24bf5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/de/b0b90a3ec974c3b1634155711cdd74ed498d2e
Binary file easy-connect/esp8266-driver/.git/objects/de/b0b90a3ec974c3b1634155711cdd74ed498d2e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/e2/1cfb7dc779c8f4eb259d1d2beeb13fd1d18a68
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/e2/1cfb7dc779c8f4eb259d1d2beeb13fd1d18a68	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xŽÁJÅ0E]ç+†·JÒ¤I"n]ëL2Z^Ӕtâß[ý—çr÷æVë*0ÎúI:3˜RR ëÍìva/‰'pèŒKžpÎêÀ뀉1²å2ë³ËÉzˬ
E=e4쐼Qø¥uøàãhð‰wܼœ¿4Ƚa¯Cnõ̵:ÍvžµÕZ]éuRøŸºzßóö †[MLÃrƒu?…‘  µs–ív–¯ÖïÐyCa‚å*p?õ³­[r
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/e2/f0dc5443e5a1d9c7ad96f98202c93749158758
Binary file easy-connect/esp8266-driver/.git/objects/e2/f0dc5443e5a1d9c7ad96f98202c93749158758 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/e4/2e2eeb911f57571bf2708fa7a9136f5bb677bb
Binary file easy-connect/esp8266-driver/.git/objects/e4/2e2eeb911f57571bf2708fa7a9136f5bb677bb has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/e4/c54243acb2e7a28d0913dee7ebbe369311e8b3
Binary file easy-connect/esp8266-driver/.git/objects/e4/c54243acb2e7a28d0913dee7ebbe369311e8b3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/ed/2c98d0a9878f01b5a9996497223be7e1361fac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/ed/2c98d0a9878f01b5a9996497223be7e1361fac	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x]ÁjÃ@D{öWäÚÄ´Sro΁¦ô¼ÎÊY‘]kYÉ1ýûn‚“BoÌ<¦Òã­{yZ4¿¿vRO~-
+_øB¥9ZFR`uýøÜߔ߼c$ñS¤¦Y­°ã’fWÕ§,có@Þ4Š£$ð<Th4hp™nôWzÒgô“U¦8e)æªè.?V³b|þÝW‡"9—yÌlaƒƒ ¹3A§šË‚3üÈT–ÔNÿÖpÙ÷‘þàƒÄ(3¦ìN{Ú"˜eݶ­§EÉT6×Ê6RN­‘KÚ.ý´3Ÿ¹½—²þºAš_*‚$
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/ee/fdaba7a9dee8e0b7db8b369517b7fe43258fbd
Binary file easy-connect/esp8266-driver/.git/objects/ee/fdaba7a9dee8e0b7db8b369517b7fe43258fbd has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/f0/bec599b1539dd61af8ccca0e7a640176f6709f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/f0/bec599b1539dd61af8ccca0e7a640176f6709f	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xuÍjÃ0„{öSì½`,YÒÊJÚK/í¬þáÊ
+²Œiž¾:õÖ¹ÍÇÌ؜R¬À{ªÅ{˜œL±æ‘I"ŵQr‘†‰¡‘ÊrìîTüRA+ïZm‚¬VÁY©&‹^¡&=	¤˜åÔÑVo¹À™Jõ3|>¨Îy_çÓP^ýúǎTRosz&ôˆÃ¨áyhêm{«/ðëÛfà°äâïß?ǯXo›ù§Öœƒëéò~퓃½e!ĒööârITc^Ö_~ÜT^
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/f1/c3f75ad0a80184aa30155e298f07f373a75263
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/objects/f1/c3f75ad0a80184aa30155e298f07f373a75263	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xÍJ1„=ç)ú¾ ù™é̂ˆ‡õàzpÑ'è$ÙYLZ2Qð흅}UEQ¥”¥ƒÓã]oÌ0eëLÐ8Œöz2cÔÁ‘	Ù!F¯Ñmú¢ÆµƒÝ'tĖY“uŽmi?zSJÑ#šüä’QôÝÏÒàHŽRç RàáBõrOs¡åó>Jy3x;âhŒ…¶Z«ÍÝ(;ÿ·¯Þ9^i¸­‹Ô$ÃóÇi²ˆªtX¹&x{ª¿Eåë\cJK¡ŸÖí *·àåtPøcJ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/f3/e3d6d5476b159f82b07d3dec0220e1047bd9b0
Binary file easy-connect/esp8266-driver/.git/objects/f3/e3d6d5476b159f82b07d3dec0220e1047bd9b0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/f9/7b41d3f75717a383be2c0410acb3137a725563
Binary file easy-connect/esp8266-driver/.git/objects/f9/7b41d3f75717a383be2c0410acb3137a725563 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/fc/0f1633de1d2b92aacc30e8cbee920f8e495b7f
Binary file easy-connect/esp8266-driver/.git/objects/fc/0f1633de1d2b92aacc30e8cbee920f8e495b7f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/objects/fd/612d3304a70f928496e13f3a54aba553b0dd9f
Binary file easy-connect/esp8266-driver/.git/objects/fd/612d3304a70f928496e13f3a54aba553b0dd9f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/packed-refs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/packed-refs	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,6 @@
+# pack-refs with: peeled 
+f0bec599b1539dd61af8ccca0e7a640176f6709f refs/remotes/origin/bulislaw_add_readme
+4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb refs/remotes/origin/master
+1999dae3ef80f9c4cb363ee01d9696dca1e4ad61 refs/tags/latest
+450cc128865ffb90b5cbfe5af193621644024fa7 refs/tags/v1.0
+29d63ae2ee0a233e2fbd9577cdddc7661bb783d1 refs/tags/v1.1
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.git/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.git/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.meta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.meta	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/.msub
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/.msub	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ESP8266/ATParser = https://github.com/ARMmbed/ATParser/#1:269f14532b98442669c50383782cbce1c67aced5
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/ATParser/#269f14532b98442669c50383782cbce1c67aced5
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/FETCH_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/FETCH_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+269f14532b98442669c50383782cbce1c67aced5		branch 'master' of https://github.com/ARMmbed/ATParser
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/ORIG_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/ORIG_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+269f14532b98442669c50383782cbce1c67aced5
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/config
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/config	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/ATParser/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/description
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/description	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/applypatch-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/applypatch-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/post-update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/post-update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-applypatch.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-applypatch.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-commit.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-commit.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-rebase.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/pre-rebase.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/prepare-commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/prepare-commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/hooks/update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/index
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/index has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/info/exclude
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/info/exclude	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,25 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 269f14532b98442669c50383782cbce1c67aced5 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036532 +0000	clone: from https://github.com/ARMmbed/ATParser/
+269f14532b98442669c50383782cbce1c67aced5 269f14532b98442669c50383782cbce1c67aced5 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036532 +0000	checkout: moving from master to 269f14532b98442669c50383782cbce1c67aced5
+269f14532b98442669c50383782cbce1c67aced5 269f14532b98442669c50383782cbce1c67aced5 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036532 +0000	checkout: moving from 269f14532b98442669c50383782cbce1c67aced5 to master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 269f14532b98442669c50383782cbce1c67aced5 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036532 +0000	clone: from https://github.com/ARMmbed/ATParser/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/logs/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 269f14532b98442669c50383782cbce1c67aced5 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036532 +0000	clone: from https://github.com/ARMmbed/ATParser/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/08/2f11ce298302a41ff877eed55ec226b944c24d
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/08/2f11ce298302a41ff877eed55ec226b944c24d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/26/9f14532b98442669c50383782cbce1c67aced5
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/26/9f14532b98442669c50383782cbce1c67aced5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/27/80390d5b3a7ed7a95478fc61b1a8632b843d1b
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/27/80390d5b3a7ed7a95478fc61b1a8632b843d1b has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/4d/677496a85bcdfd5a2d8bd5260f36d92bec09a5
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/4d/677496a85bcdfd5a2d8bd5260f36d92bec09a5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/52/f9e7d0c92be3026ed8e2d929f5a2f3af5c7216
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/52/f9e7d0c92be3026ed8e2d929f5a2f3af5c7216 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/7d/0e42380917cbd4e2b474ba5771a7e15215e74c
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/7d/0e42380917cbd4e2b474ba5771a7e15215e74c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/80/0d8517da4d091eb52094a1cac0a66903aed59a
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/80/0d8517da4d091eb52094a1cac0a66903aed59a has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/93/e4cb7ebd99ce690370a168ac831cacea4034a9
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/93/e4cb7ebd99ce690370a168ac831cacea4034a9 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/98/76baf6df887b76b6cb5da0a2e9bec41146001b
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/98/76baf6df887b76b6cb5da0a2e9bec41146001b has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/ac/0e4a88ca41a9de0f9d03f1d6b75ac2ba0b4ccc
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/ac/0e4a88ca41a9de0f9d03f1d6b75ac2ba0b4ccc has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/e2/3cc82f00dee6d8a91d5fd2bbdf6f4b548a0ffe
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/e2/3cc82f00dee6d8a91d5fd2bbdf6f4b548a0ffe has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/f3/e3d6d5476b159f82b07d3dec0220e1047bd9b0
Binary file easy-connect/esp8266-driver/ESP8266/ATParser/.git/objects/f3/e3d6d5476b159f82b07d3dec0220e1047bd9b0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/packed-refs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/packed-refs	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+# pack-refs with: peeled 
+269f14532b98442669c50383782cbce1c67aced5 refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+269f14532b98442669c50383782cbce1c67aced5
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.git/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.git/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/.meta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/.meta	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/ATParser.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/ATParser.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,333 @@
+/* Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+
+#include "ATParser.h"
+#include "mbed_debug.h"
+
+
+// getc/putc handling with timeouts
+int ATParser::putc(char c)
+{
+    Timer timer;
+    timer.start();
+
+    while (true) {
+        if (_serial->writeable()) {
+            return _serial->putc(c);
+        }
+        if (timer.read_ms() > _timeout) {
+            return -1;
+        }
+    }
+}
+
+int ATParser::getc()
+{
+    Timer timer;
+    timer.start();
+
+    while (true) {
+        if (_serial->readable()) {
+            return _serial->getc();
+        }
+        if (timer.read_ms() > _timeout) {
+            return -1;
+        }
+    }
+}
+
+void ATParser::flush()
+{
+    while (_serial->readable()) {
+        _serial->getc();
+    }
+}
+
+
+// read/write handling with timeouts
+int ATParser::write(const char *data, int size)
+{
+    int i = 0;
+    for ( ; i < size; i++) {
+        if (putc(data[i]) < 0) {
+            return -1;
+        }
+    }
+    return i;
+}
+
+int ATParser::read(char *data, int size)
+{
+    int i = 0;
+    for ( ; i < size; i++) {
+        int c = getc();
+        if (c < 0) {
+            return -1;
+        }
+        data[i] = c;
+    }
+    return i;
+}
+
+
+// printf/scanf handling
+int ATParser::vprintf(const char *format, va_list args)
+{
+    if (vsprintf(_buffer, format, args) < 0) {
+        return false;
+    }
+    int i = 0;
+    for ( ; _buffer[i]; i++) {
+        if (putc(_buffer[i]) < 0) {
+            return -1;
+        }
+    }
+    return i;
+}
+
+int ATParser::vscanf(const char *format, va_list args)
+{
+    // Since format is const, we need to copy it into our buffer to
+    // add the line's null terminator and clobber value-matches with asterisks.
+    //
+    // We just use the beginning of the buffer to avoid unnecessary allocations.
+    int i = 0;
+    int offset = 0;
+
+    while (format[i]) {
+        if (format[i] == '%' && format[i+1] != '%' && format[i+1] != '*') {
+            _buffer[offset++] = '%';
+            _buffer[offset++] = '*';
+            i++;
+        } else {
+            _buffer[offset++] = format[i++];
+        }
+    }
+
+    // Scanf has very poor support for catching errors
+    // fortunately, we can abuse the %n specifier to determine
+    // if the entire string was matched.
+    _buffer[offset++] = '%';
+    _buffer[offset++] = 'n';
+    _buffer[offset++] = 0;
+
+    // To workaround scanf's lack of error reporting, we actually
+    // make two passes. One checks the validity with the modified
+    // format string that only stores the matched characters (%n).
+    // The other reads in the actual matched values.
+    //
+    // We keep trying the match until we succeed or some other error
+    // derails us.
+    int j = 0;
+
+    while (true) {
+        // Ran out of space
+        if (j+1 >= _buffer_size - offset) {
+            return false;
+        }
+        // Recieve next character
+        int c = getc();
+        if (c < 0) {
+            return -1;
+        }
+        _buffer[offset + j++] = c;
+        _buffer[offset + j] = 0;
+
+        // Check for match
+        int count = -1;
+        sscanf(_buffer+offset, _buffer, &count);
+
+        // We only succeed if all characters in the response are matched
+        if (count == j) {
+            // Store the found results
+            vsscanf(_buffer+offset, format, args);
+            return j;
+        }
+    }
+}
+
+
+// Command parsing with line handling
+bool ATParser::vsend(const char *command, va_list args)
+{
+    // Create and send command
+    if (vsprintf(_buffer, command, args) < 0) {
+        return false;
+    }
+    for (int i = 0; _buffer[i]; i++) {
+        if (putc(_buffer[i]) < 0) {
+            return false;
+        }
+    }
+
+    // Finish with newline
+    for (int i = 0; _delimiter[i]; i++) {
+        if (putc(_delimiter[i]) < 0) {
+            return false;
+        }
+    }
+
+    debug_if(dbg_on, "AT> %s\r\n", _buffer);
+    return true;
+}
+
+bool ATParser::vrecv(const char *response, va_list args)
+{
+    // Iterate through each line in the expected response
+    while (response[0]) {
+        // Since response is const, we need to copy it into our buffer to
+        // add the line's null terminator and clobber value-matches with asterisks.
+        //
+        // We just use the beginning of the buffer to avoid unnecessary allocations.
+        int i = 0;
+        int offset = 0;
+
+        while (response[i]) {
+            if (memcmp(&response[i+1-_delim_size], _delimiter, _delim_size) == 0) {
+                i++;
+                break;
+            } else if (response[i] == '%' && response[i+1] != '%' && response[i+1] != '*') {
+                _buffer[offset++] = '%';
+                _buffer[offset++] = '*';
+                i++;
+            } else {
+                _buffer[offset++] = response[i++];
+            }
+        }
+
+        // Scanf has very poor support for catching errors
+        // fortunately, we can abuse the %n specifier to determine
+        // if the entire string was matched.
+        _buffer[offset++] = '%';
+        _buffer[offset++] = 'n';
+        _buffer[offset++] = 0;
+
+        // To workaround scanf's lack of error reporting, we actually
+        // make two passes. One checks the validity with the modified
+        // format string that only stores the matched characters (%n).
+        // The other reads in the actual matched values.
+        //
+        // We keep trying the match until we succeed or some other error
+        // derails us.
+        int j = 0;
+
+        while (true) {
+            // Recieve next character
+            int c = getc();
+            if (c < 0) {
+                return false;
+            }
+            _buffer[offset + j++] = c;
+            _buffer[offset + j] = 0;
+
+            // Check for oob data
+            for (int k = 0; k < _oobs.size(); k++) {
+                if (j == _oobs[k].len && memcmp(
+                        _oobs[k].prefix, _buffer+offset, _oobs[k].len) == 0) {
+                    debug_if(dbg_on, "AT! %s\r\n", _oobs[k].prefix);
+                    _oobs[k].cb();
+
+                    // oob may have corrupted non-reentrant buffer,
+                    // so we need to set it up again
+                    return vrecv(response, args);
+                }
+            }
+
+            // Check for match
+            int count = -1;
+            sscanf(_buffer+offset, _buffer, &count);
+
+            // We only succeed if all characters in the response are matched
+            if (count == j) {
+                debug_if(dbg_on, "AT= %s\r\n", _buffer+offset);
+                // Reuse the front end of the buffer
+                memcpy(_buffer, response, i);
+                _buffer[i] = 0;
+
+                // Store the found results
+                vsscanf(_buffer+offset, _buffer, args);
+
+                // Jump to next line and continue parsing
+                response += i;
+                break;
+            }
+
+            // Clear the buffer when we hit a newline or ran out of space
+            // running out of space usually means we ran into binary data
+            if (j+1 >= _buffer_size - offset ||
+                strcmp(&_buffer[offset + j-_delim_size], _delimiter) == 0) {
+
+                debug_if(dbg_on, "AT< %s", _buffer+offset);
+                j = 0;
+            }
+        }
+    }
+
+    return true;
+}
+
+
+// Mapping to vararg functions
+int ATParser::printf(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    int res = vprintf(format, args);
+    va_end(args);
+    return res;
+}
+
+int ATParser::scanf(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    int res = vscanf(format, args);
+    va_end(args);
+    return res;
+}
+
+bool ATParser::send(const char *command, ...)
+{
+    va_list args;
+    va_start(args, command);
+    bool res = vsend(command, args);
+    va_end(args);
+    return res;
+}
+
+bool ATParser::recv(const char *response, ...)
+{
+    va_list args;
+    va_start(args, response);
+    bool res = vrecv(response, args);
+    va_end(args);
+    return res;
+}
+
+
+// oob registration
+void ATParser::oob(const char *prefix, Callback<void()> cb)
+{
+    struct oob oob;
+    oob.len = strlen(prefix);
+    oob.prefix = prefix;
+    oob.cb = cb;
+    _oobs.push_back(oob);
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/ATParser.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/ATParser.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,234 @@
+/* Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+#ifndef AT_PARSER_H
+#define AT_PARSER_H
+
+#include "mbed.h"
+#include <cstdarg>
+#include <vector>
+#include "BufferedSerial.h"
+#include "Callback.h"
+
+
+/**
+* Parser class for parsing AT commands
+*
+* Here are some examples:
+* @code
+* ATParser at = ATParser(serial, "\r\n");
+* int value;
+* char buffer[100];
+*
+* at.send("AT") && at.recv("OK");
+* at.send("AT+CWMODE=%d", 3) && at.recv("OK");
+* at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value);
+* at.recv("+IPD,%d:", &value);
+* at.read(buffer, value);
+* at.recv("OK");
+* @endcode
+*/
+class ATParser
+{
+private:
+    // Serial information
+    BufferedSerial *_serial;
+    int _buffer_size;
+    char *_buffer;
+    int _timeout;
+
+    // Parsing information
+    const char *_delimiter;
+    int _delim_size;
+    bool dbg_on;
+
+    struct oob {
+        unsigned len;
+        const char *prefix;
+        mbed::Callback<void()> cb;
+    };
+    std::vector<oob> _oobs;
+
+public:
+    /**
+    * Constructor
+    *
+    * @param serial serial interface to use for AT commands
+    * @param buffer_size size of internal buffer for transaction
+    * @param timeout timeout of the connection
+    * @param delimiter string of characters to use as line delimiters
+    */
+    ATParser(BufferedSerial &serial, const char *delimiter = "\r\n", int buffer_size = 256, int timeout = 8000, bool debug = false) :
+        _serial(&serial),
+        _buffer_size(buffer_size) {
+        _buffer = new char[buffer_size];
+        setTimeout(timeout);
+        setDelimiter(delimiter);
+        debugOn(debug);
+    }
+
+    /**
+    * Destructor
+    */
+    ~ATParser() {
+        delete [] _buffer;
+    }
+
+    /**
+    * Allows timeout to be changed between commands
+    *
+    * @param timeout timeout of the connection
+    */
+    void setTimeout(int timeout) {
+        _timeout = timeout;
+    }
+
+    /**
+    * Sets string of characters to use as line delimiters
+    *
+    * @param delimiter string of characters to use as line delimiters
+    */
+    void setDelimiter(const char *delimiter) {
+        _delimiter = delimiter;
+        _delim_size = strlen(delimiter);
+    }
+    
+    /**
+    * Allows echo to be on or off
+    *
+    * @param echo 1 for echo and 0 turns it off
+    */
+    void debugOn(uint8_t on) {
+        dbg_on = (on) ? 1 : 0;
+    }
+
+    /**
+    * Sends an AT command
+    *
+    * Sends a formatted command using printf style formatting
+    * @see ::printf
+    *
+    * @param command printf-like format string of command to send which
+    *                is appended with the specified delimiter
+    * @param ... all printf-like arguments to insert into command
+    * @return true only if command is successfully sent
+    */
+    bool send(const char *command, ...);
+    bool vsend(const char *command, va_list args);
+
+    /**
+    * Recieve an AT response
+    *
+    * Recieves a formatted response using scanf style formatting
+    * @see ::scanf
+    *
+    * Responses are parsed line at a time using the specified delimiter.
+    * Any recieved data that does not match the response is ignored until
+    * a timeout occurs.
+    *
+    * @param response scanf-like format string of response to expect
+    * @param ... all scanf-like arguments to extract from response
+    * @return true only if response is successfully matched
+    */
+    bool recv(const char *response, ...);
+    bool vrecv(const char *response, va_list args);
+
+    /**
+    * Write a single byte to the underlying stream
+    *
+    * @param c The byte to write
+    * @return The byte that was written or -1 during a timeout
+    */
+    int putc(char c);
+
+    /**
+    * Get a single byte from the underlying stream
+    *
+    * @return The byte that was read or -1 during a timeout
+    */
+    int getc();
+
+    /**
+    * Write an array of bytes to the underlying stream
+    *
+    * @param data the array of bytes to write
+    * @param size number of bytes to write
+    * @return number of bytes written or -1 on failure
+    */
+    int write(const char *data, int size);
+
+    /**
+    * Read an array of bytes from the underlying stream
+    *
+    * @param data the destination for the read bytes
+    * @param size number of bytes to read
+    * @return number of bytes read or -1 on failure
+    */
+    int read(char *data, int size);
+
+    /**
+    * Direct printf to underlying stream
+    * @see ::printf
+    *
+    * @param format format string to pass to printf
+    * @param ... arguments to printf
+    * @return number of bytes written or -1 on failure
+    */
+    int printf(const char *format, ...);
+    int vprintf(const char *format, va_list args);
+
+    /**
+    * Direct scanf on underlying stream
+    * @see ::scanf
+    *
+    * @param format format string to pass to scanf
+    * @param ... arguments to scanf
+    * @return number of bytes read or -1 on failure
+    */
+    int scanf(const char *format, ...);
+    int vscanf(const char *format, va_list args);
+
+    /**
+    * Attach a callback for out-of-band data
+    * 
+    * @param prefix string on when to initiate callback
+    * @param func callback to call when string is read
+    * @note out-of-band data is only processed during a scanf call
+    */
+    void oob(const char *prefix, mbed::Callback<void()> func);
+
+    /**
+    * Attach a callback for out-of-band data
+    *
+    * @param prefix string on when to initiate callback
+    * @param obj pointer to object to call member function on
+    * @param method callback to call when string is read
+    * @note out-of-band data is only processed during a scanf call
+    */
+    template <typename T, typename M>
+    void oob(const char *prefix, T *obj, M method) {
+        return oob(prefix, mbed::Callback<void()>(obj, method));
+    }
+
+    /**
+    * Flushes the underlying stream
+    */
+    void flush();
+};
+#endif
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/Buffer/MyBuffer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/Buffer/MyBuffer.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,76 @@
+
+/**
+ * @file    Buffer.cpp
+ * @brief   Software Buffer - Templated Ring Buffer for most data types
+ * @author  sam grove
+ * @version 1.0
+ * @see     
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "MyBuffer.h"
+
+template <class T>
+MyBuffer<T>::MyBuffer(uint32_t size)
+{
+    _buf = new T [size];
+    _size = size;
+    clear();
+    
+    return;
+}
+
+template <class T>
+MyBuffer<T>::~MyBuffer()
+{
+    delete [] _buf;
+    
+    return;
+}
+
+template <class T>
+uint32_t MyBuffer<T>::getSize() 
+{ 
+    return this->_size; 
+}
+
+template <class T>
+void MyBuffer<T>::clear(void)
+{
+    _wloc = 0;
+    _rloc = 0;
+    memset(_buf, 0, _size);
+    
+    return;
+}
+
+template <class T>
+uint32_t MyBuffer<T>::peek(char c)
+{
+    return 1;
+}
+
+// make the linker aware of some possible types
+template class MyBuffer<uint8_t>;
+template class MyBuffer<int8_t>;
+template class MyBuffer<uint16_t>;
+template class MyBuffer<int16_t>;
+template class MyBuffer<uint32_t>;
+template class MyBuffer<int32_t>;
+template class MyBuffer<uint64_t>;
+template class MyBuffer<int64_t>;
+template class MyBuffer<char>;
+template class MyBuffer<wchar_t>;
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/Buffer/MyBuffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/Buffer/MyBuffer.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,163 @@
+
+/**
+ * @file    Buffer.h
+ * @brief   Software Buffer - Templated Ring Buffer for most data types
+ * @author  sam grove
+ * @version 1.0
+ * @see     
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#ifndef MYBUFFER_H
+#define MYBUFFER_H
+
+#include <stdint.h>
+#include <string.h>
+
+/** A templated software ring buffer
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "MyBuffer.h"
+ *
+ *  MyBuffer <char> buf;
+ *
+ *  int main()
+ *  {
+ *      buf = 'a';
+ *      buf.put('b');
+ *      char *head = buf.head();
+ *      puts(head);
+ *
+ *      char whats_in_there[2] = {0};
+ *      int pos = 0;
+ *
+ *      while(buf.available())
+ *      {   
+ *          whats_in_there[pos++] = buf;
+ *      }
+ *      printf("%c %c\n", whats_in_there[0], whats_in_there[1]);
+ *      buf.clear();
+ *      error("done\n\n\n");
+ *  }
+ * @endcode
+ */
+
+template <typename T>
+class MyBuffer
+{
+private:
+    T   *_buf;
+    volatile uint32_t   _wloc;
+    volatile uint32_t   _rloc;
+    uint32_t            _size;
+
+public:
+    /** Create a Buffer and allocate memory for it
+     *  @param size The size of the buffer
+     */
+    MyBuffer(uint32_t size = 0x100);
+    
+    /** Get the size of the ring buffer
+     * @return the size of the ring buffer
+     */
+     uint32_t getSize();
+    
+    /** Destry a Buffer and release it's allocated memory
+     */
+    ~MyBuffer();
+    
+    /** Add a data element into the buffer
+     *  @param data Something to add to the buffer
+     */
+    void put(T data);
+    
+    /** Remove a data element from the buffer
+     *  @return Pull the oldest element from the buffer
+     */
+    T get(void);
+    
+    /** Get the address to the head of the buffer
+     *  @return The address of element 0 in the buffer
+     */
+    T *head(void);
+    
+    /** Reset the buffer to 0. Useful if using head() to parse packeted data
+     */
+    void clear(void);
+    
+    /** Determine if anything is readable in the buffer
+     *  @return 1 if something can be read, 0 otherwise
+     */
+    uint32_t available(void);
+    
+    /** Overloaded operator for writing to the buffer
+     *  @param data Something to put in the buffer
+     *  @return
+     */
+    MyBuffer &operator= (T data)
+    {
+        put(data);
+        return *this;
+    }
+    
+    /** Overloaded operator for reading from the buffer
+     *  @return Pull the oldest element from the buffer 
+     */  
+    operator int(void)
+    {
+        return get();
+    }
+    
+     uint32_t peek(char c);
+    
+};
+
+template <class T>
+inline void MyBuffer<T>::put(T data)
+{
+    _buf[_wloc++] = data;
+    _wloc %= (_size-1);
+    
+    return;
+}
+
+template <class T>
+inline T MyBuffer<T>::get(void)
+{
+    T data_pos = _buf[_rloc++];
+    _rloc %= (_size-1);
+    
+    return data_pos;
+}
+
+template <class T>
+inline T *MyBuffer<T>::head(void)
+{
+    T *data_pos = &_buf[0];
+    
+    return data_pos;
+}
+
+template <class T>
+inline uint32_t MyBuffer<T>::available(void)
+{
+    return (_wloc == _rloc) ? 0 : 1;
+}
+
+#endif
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedPrint.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedPrint.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mbed_error.h"
+
+size_t BufferedSerialThunk(void *buf_serial, const void *s, size_t length);
+
+int BufferedPrintfC(void *stream, int size, const char* format, va_list arg)
+{
+    int r;
+    char buffer[512];
+    if (size >= 512) {
+        return -1;
+    }
+    memset(buffer, 0, size);
+    r = vsprintf(buffer, format, arg);
+    // this may not hit the heap but should alert the user anyways
+    if(r > (int32_t) size) {
+        error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__, size, r);
+        return 0;
+    }
+    if ( r > 0 ) {
+        BufferedSerialThunk(stream, buffer, r);
+    }
+    return r;
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedSerial.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedSerial.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,166 @@
+/**
+ * @file    BufferedSerial.cpp
+ * @brief   Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX
+ * @author  sam grove
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BufferedSerial.h"
+#include <stdarg.h>
+
+extern "C" int BufferedPrintfC(void *stream, int size, const char* format, va_list arg);
+
+BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name)
+    : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size))
+{
+    RawSerial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq);
+    this->_buf_size = buf_size;
+    this->_tx_multiple = tx_multiple;   
+    return;
+}
+
+BufferedSerial::~BufferedSerial(void)
+{
+    RawSerial::attach(NULL, RawSerial::RxIrq);
+    RawSerial::attach(NULL, RawSerial::TxIrq);
+
+    return;
+}
+
+int BufferedSerial::readable(void)
+{
+    return _rxbuf.available();  // note: look if things are in the buffer
+}
+
+int BufferedSerial::writeable(void)
+{
+    return 1;   // buffer allows overwriting by design, always true
+}
+
+int BufferedSerial::getc(void)
+{
+    return _rxbuf;
+}
+
+int BufferedSerial::putc(int c)
+{
+    _txbuf = (char)c;
+    BufferedSerial::prime();
+
+    return c;
+}
+
+int BufferedSerial::puts(const char *s)
+{
+    if (s != NULL) {
+        const char* ptr = s;
+    
+        while(*(ptr) != 0) {
+            _txbuf = *(ptr++);
+        }
+        _txbuf = '\n';  // done per puts definition
+        BufferedSerial::prime();
+    
+        return (ptr - s) + 1;
+    }
+    return 0;
+}
+
+extern "C" size_t BufferedSerialThunk(void *buf_serial, const void *s, size_t length)
+{
+    BufferedSerial *buffered_serial = (BufferedSerial *)buf_serial;
+    return buffered_serial->write(s, length);
+}
+
+int BufferedSerial::printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int r = BufferedPrintfC((void*)this, this->_buf_size, format, arg);
+    va_end(arg);
+    return r;
+}
+
+ssize_t BufferedSerial::write(const void *s, size_t length)
+{
+    if (s != NULL && length > 0) {
+        const char* ptr = (const char*)s;
+        const char* end = ptr + length;
+    
+        while (ptr != end) {
+            _txbuf = *(ptr++);
+        }
+        BufferedSerial::prime();
+    
+        return ptr - (const char*)s;
+    }
+    return 0;
+}
+
+
+void BufferedSerial::rxIrq(void)
+{
+    // read from the peripheral and make sure something is available
+    if(serial_readable(&_serial)) {
+        _rxbuf = serial_getc(&_serial); // if so load them into a buffer
+        // trigger callback if necessary
+        if (_cbs[RxIrq]) {
+            _cbs[RxIrq]();
+        }
+    }
+
+    return;
+}
+
+void BufferedSerial::txIrq(void)
+{
+    // see if there is room in the hardware fifo and if something is in the software fifo
+    while(serial_writable(&_serial)) {
+        if(_txbuf.available()) {
+            serial_putc(&_serial, (int)_txbuf.get());
+        } else {
+            // disable the TX interrupt when there is nothing left to send
+            RawSerial::attach(NULL, RawSerial::TxIrq);
+            // trigger callback if necessary
+            if (_cbs[TxIrq]) {
+                _cbs[TxIrq]();
+            }
+            break;
+        }
+    }
+
+    return;
+}
+
+void BufferedSerial::prime(void)
+{
+    // if already busy then the irq will pick this up
+    if(serial_writable(&_serial)) {
+        RawSerial::attach(NULL, RawSerial::TxIrq);    // make sure not to cause contention in the irq
+        BufferedSerial::txIrq();                // only write to hardware in one place
+        RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq);
+    }
+
+    return;
+}
+
+void BufferedSerial::attach(Callback<void()> func, IrqType type)
+{
+    _cbs[type] = func;
+}
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedSerial.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/BufferedSerial/BufferedSerial.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,168 @@
+
+/**
+ * @file    BufferedSerial.h
+ * @brief   Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX
+ * @author  sam grove
+ * @version 1.0
+ * @see     
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BUFFEREDSERIAL_H
+#define BUFFEREDSERIAL_H
+ 
+#include "mbed.h"
+#include "MyBuffer.h"
+
+/** A serial port (UART) for communication with other serial devices
+ *
+ * Can be used for Full Duplex communication, or Simplex by specifying
+ * one pin as NC (Not Connected)
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "BufferedSerial.h"
+ *
+ *  BufferedSerial pc(USBTX, USBRX);
+ *
+ *  int main()
+ *  { 
+ *      while(1)
+ *      {
+ *          Timer s;
+ *        
+ *          s.start();
+ *          pc.printf("Hello World - buffered\n");
+ *          int buffered_time = s.read_us();
+ *          wait(0.1f); // give time for the buffer to empty
+ *        
+ *          s.reset();
+ *          printf("Hello World - blocking\n");
+ *          int polled_time = s.read_us();
+ *          s.stop();
+ *          wait(0.1f); // give time for the buffer to empty
+ *        
+ *          pc.printf("printf buffered took %d us\n", buffered_time);
+ *          pc.printf("printf blocking took %d us\n", polled_time);
+ *          wait(0.5f);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/**
+ *  @class BufferedSerial
+ *  @brief Software buffers and interrupt driven tx and rx for Serial
+ */  
+class BufferedSerial : public RawSerial 
+{
+private:
+    MyBuffer <char> _rxbuf;
+    MyBuffer <char> _txbuf;
+    uint32_t      _buf_size;
+    uint32_t      _tx_multiple;
+ 
+    void rxIrq(void);
+    void txIrq(void);
+    void prime(void);
+
+    Callback<void()> _cbs[2];
+    
+public:
+    /** Create a BufferedSerial port, connected to the specified transmit and receive pins
+     *  @param tx Transmit pin
+     *  @param rx Receive pin
+     *  @param buf_size printf() buffer size
+     *  @param tx_multiple amount of max printf() present in the internal ring buffer at one time
+     *  @param name optional name
+     *  @note Either tx or rx may be specified as NC if unused
+     */
+    BufferedSerial(PinName tx, PinName rx, uint32_t buf_size = 256, uint32_t tx_multiple = 4,const char* name=NULL);
+    
+    /** Destroy a BufferedSerial port
+     */
+    virtual ~BufferedSerial(void);
+    
+    /** Check on how many bytes are in the rx buffer
+     *  @return 1 if something exists, 0 otherwise
+     */
+    virtual int readable(void);
+    
+    /** Check to see if the tx buffer has room
+     *  @return 1 always has room and can overwrite previous content if too small / slow
+     */
+    virtual int writeable(void);
+    
+    /** Get a single byte from the BufferedSerial Port.
+     *  Should check readable() before calling this.
+     *  @return A byte that came in on the Serial Port
+     */
+    virtual int getc(void);
+    
+    /** Write a single byte to the BufferedSerial Port.
+     *  @param c The byte to write to the Serial Port
+     *  @return The byte that was written to the Serial Port Buffer
+     */
+    virtual int putc(int c);
+    
+    /** Write a string to the BufferedSerial Port. Must be NULL terminated
+     *  @param s The string to write to the Serial Port
+     *  @return The number of bytes written to the Serial Port Buffer
+     */
+    virtual int puts(const char *s);
+    
+    /** Write a formatted string to the BufferedSerial Port.
+     *  @param format The string + format specifiers to write to the Serial Port
+     *  @return The number of bytes written to the Serial Port Buffer
+     */
+    virtual int printf(const char* format, ...);
+    
+    /** Write data to the Buffered Serial Port
+     *  @param s A pointer to data to send
+     *  @param length The amount of data being pointed to
+     *  @return The number of bytes written to the Serial Port Buffer
+     */
+    virtual ssize_t write(const void *s, std::size_t length);
+
+    /** Attach a function to call whenever a serial interrupt is generated
+     *  @param func A pointer to a void function, or 0 to set as none
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    virtual void attach(Callback<void()> func, IrqType type=RxIrq);
+
+    /** Attach a member function to call whenever a serial interrupt is generated
+     *  @param obj pointer to the object to call the member function on
+     *  @param method pointer to the member function to call
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    template <typename T>
+    void attach(T *obj, void (T::*method)(), IrqType type=RxIrq) {
+        attach(Callback<void()>(obj, method), type);
+    }
+
+    /** Attach a member function to call whenever a serial interrupt is generated
+     *  @param obj pointer to the object to call the member function on
+     *  @param method pointer to the member function to call
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    template <typename T>
+    void attach(T *obj, void (*method)(T*), IrqType type=RxIrq) {
+        attach(Callback<void()>(obj, method), type);
+    }
+};
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ATParser/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ATParser/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+# AT Command Parser
+
+An mbed-os compatible AT command parser.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ESP8266.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ESP8266.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,306 @@
+/* ESP8266 Example
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ESP8266.h"
+
+ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
+    : _serial(tx, rx, 1024), _parser(_serial)
+    , _packets(0), _packets_end(&_packets)
+{
+    _serial.baud(115200);
+    _parser.debugOn(debug);
+}
+
+bool ESP8266::startup(int mode)
+{
+    //only 3 valid modes
+    if(mode < 1 || mode > 3) {
+        return false;
+    }
+
+    bool success = reset()
+        && _parser.send("AT+CWMODE=%d", mode)
+        && _parser.recv("OK")
+        && _parser.send("AT+CIPMUX=1")
+        && _parser.recv("OK");
+
+    _parser.oob("+IPD", this, &ESP8266::_packet_handler);
+
+    return success;
+}
+
+bool ESP8266::reset(void)
+{
+    for (int i = 0; i < 2; i++) {
+        if (_parser.send("AT+RST")
+            && _parser.recv("OK\r\nready")) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool ESP8266::dhcp(bool enabled, int mode)
+{
+    //only 3 valid modes
+    if(mode < 0 || mode > 2) {
+        return false;
+    }
+
+    return _parser.send("AT+CWDHCP=%d,%d", enabled?1:0, mode)
+        && _parser.recv("OK");
+}
+
+bool ESP8266::connect(const char *ap, const char *passPhrase)
+{
+    return _parser.send("AT+CWJAP=\"%s\",\"%s\"", ap, passPhrase)
+        && _parser.recv("OK");
+}
+
+bool ESP8266::disconnect(void)
+{
+    return _parser.send("AT+CWQAP") && _parser.recv("OK");
+}
+
+const char *ESP8266::getIPAddress(void)
+{
+    if (!(_parser.send("AT+CIFSR")
+        && _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+
+    return _ip_buffer;
+}
+
+const char *ESP8266::getMACAddress(void)
+{
+    if (!(_parser.send("AT+CIFSR")
+        && _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+
+    return _mac_buffer;
+}
+
+const char *ESP8266::getGateway()
+{
+    if (!(_parser.send("AT+CIPSTA?")
+        && _parser.recv("+CIPSTA:gateway:\"%15[^\"]\"", _gateway_buffer)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+
+    return _gateway_buffer;
+}
+
+const char *ESP8266::getNetmask()
+{
+    if (!(_parser.send("AT+CIPSTA?")
+        && _parser.recv("+CIPSTA:netmask:\"%15[^\"]\"", _netmask_buffer)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+
+    return _netmask_buffer;
+}
+
+int8_t ESP8266::getRSSI()
+{
+    int8_t rssi;
+    char bssid[18];
+
+   if (!(_parser.send("AT+CWJAP?")
+        && _parser.recv("+CWJAP:\"%*[^\"]\",\"%17[^\"]\"", bssid)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+
+    if (!(_parser.send("AT+CWLAP=\"\",\"%s\",", bssid)
+        && _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi)
+        && _parser.recv("OK"))) {
+        return 0;
+    }
+
+    return rssi;
+}
+
+bool ESP8266::isConnected(void)
+{
+    return getIPAddress() != 0;
+}
+
+int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
+{
+    unsigned cnt = 0;
+    nsapi_wifi_ap_t ap;
+
+    if (!_parser.send("AT+CWLAP")) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    while (recv_ap(&ap)) {
+        if (cnt < limit) {
+            res[cnt] = WiFiAccessPoint(ap);
+        }
+
+        cnt++;
+        if (limit != 0 && cnt >= limit) {
+            break;
+        }
+    }
+
+    return cnt;
+}
+
+bool ESP8266::open(const char *type, int id, const char* addr, int port)
+{
+    //IDs only 0-4
+    if(id > 4) {
+        return false;
+    }
+
+    return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
+        && _parser.recv("OK");
+}
+
+bool ESP8266::send(int id, const void *data, uint32_t amount)
+{
+    //May take a second try if device is busy
+    for (unsigned i = 0; i < 2; i++) {
+        if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
+            && _parser.recv(">")
+            && _parser.write((char*)data, (int)amount) >= 0) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void ESP8266::_packet_handler()
+{
+    int id;
+    uint32_t amount;
+
+    // parse out the packet
+    if (!_parser.recv(",%d,%d:", &id, &amount)) {
+        return;
+    }
+
+    struct packet *packet = (struct packet*)malloc(
+            sizeof(struct packet) + amount);
+    if (!packet) {
+        return;
+    }
+
+    packet->id = id;
+    packet->len = amount;
+    packet->next = 0;
+
+    if (!(_parser.read((char*)(packet + 1), amount))) {
+        free(packet);
+        return;
+    }
+
+    // append to packet list
+    *_packets_end = packet;
+    _packets_end = &packet->next;
+}
+
+int32_t ESP8266::recv(int id, void *data, uint32_t amount)
+{
+    while (true) {
+        // check if any packets are ready for us
+        for (struct packet **p = &_packets; *p; p = &(*p)->next) {
+            if ((*p)->id == id) {
+                struct packet *q = *p;
+
+                if (q->len <= amount) { // Return and remove full packet
+                    memcpy(data, q+1, q->len);
+
+                    if (_packets_end == &(*p)->next) {
+                        _packets_end = p;
+                    }
+                    *p = (*p)->next;
+
+                    uint32_t len = q->len;
+                    free(q);
+                    return len;
+                } else { // return only partial packet
+                    memcpy(data, q+1, amount);
+
+                    q->len -= amount;
+                    memmove(q+1, (uint8_t*)(q+1) + amount, q->len);
+
+                    return amount;
+                }
+            }
+        }
+
+        // Wait for inbound packet
+        if (!_parser.recv("OK")) {
+            return -1;
+        }
+    }
+}
+
+bool ESP8266::close(int id)
+{
+    //May take a second try if device is busy
+    for (unsigned i = 0; i < 2; i++) {
+        if (_parser.send("AT+CIPCLOSE=%d", id)
+            && _parser.recv("OK")) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void ESP8266::setTimeout(uint32_t timeout_ms)
+{
+    _parser.setTimeout(timeout_ms);
+}
+
+bool ESP8266::readable()
+{
+    return _serial.readable();
+}
+
+bool ESP8266::writeable()
+{
+    return _serial.writeable();
+}
+
+void ESP8266::attach(Callback<void()> func)
+{
+    _serial.attach(func);
+}
+
+bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap)
+{
+    int sec;
+    bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%d", &sec, ap->ssid,
+                            &ap->rssi, &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4],
+                            &ap->bssid[5], &ap->channel);
+
+    ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
+
+    return ret;
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266/ESP8266.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266/ESP8266.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,213 @@
+/* ESP8266Interface Example
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ESP8266_H
+#define ESP8266_H
+
+#include "ATParser.h"
+
+/** ESP8266Interface class.
+    This is an interface to a ESP8266 radio.
+ */
+class ESP8266
+{
+public:
+    ESP8266(PinName tx, PinName rx, bool debug=false);
+
+    /**
+    * Startup the ESP8266
+    *
+    * @param mode mode of WIFI 1-client, 2-host, 3-both
+    * @return true only if ESP8266 was setup correctly
+    */
+    bool startup(int mode);
+
+    /**
+    * Reset ESP8266
+    *
+    * @return true only if ESP8266 resets successfully
+    */
+    bool reset(void);
+
+    /**
+    * Enable/Disable DHCP
+    *
+    * @param enabled DHCP enabled when true
+    * @param mode mode of DHCP 0-softAP, 1-station, 2-both
+    * @return true only if ESP8266 enables/disables DHCP successfully
+    */
+    bool dhcp(bool enabled, int mode);
+
+    /**
+    * Connect ESP8266 to AP
+    *
+    * @param ap the name of the AP
+    * @param passPhrase the password of AP
+    * @return true only if ESP8266 is connected successfully
+    */
+    bool connect(const char *ap, const char *passPhrase);
+
+    /**
+    * Disconnect ESP8266 from AP
+    *
+    * @return true only if ESP8266 is disconnected successfully
+    */
+    bool disconnect(void);
+
+    /**
+    * Get the IP address of ESP8266
+    *
+    * @return null-teriminated IP address or null if no IP address is assigned
+    */
+    const char *getIPAddress(void);
+
+    /**
+    * Get the MAC address of ESP8266
+    *
+    * @return null-terminated MAC address or null if no MAC address is assigned
+    */
+    const char *getMACAddress(void);
+
+     /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    const char *getGateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask 
+     *                  or null if no network mask has been recieved
+     */
+    const char *getNetmask();
+
+    /* Return RSSI for active connection
+     *
+     * @return      Measured RSSI
+     */
+    int8_t getRSSI();
+
+    /**
+    * Check if ESP8266 is conenected
+    *
+    * @return true only if the chip has an IP address
+    */
+    bool isConnected(void);
+
+    /** Scan for available networks
+     *
+     * @param  ap    Pointer to allocated array to store discovered AP
+     * @param  limit Size of allocated @a res array, or 0 to only count available AP
+     * @return       Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
+     *               see @a nsapi_error
+     */
+    int scan(WiFiAccessPoint *res, unsigned limit);
+
+    /**
+    * Open a socketed connection
+    *
+    * @param type the type of socket to open "UDP" or "TCP"
+    * @param id id to give the new socket, valid 0-4
+    * @param port port to open connection with
+    * @param addr the IP address of the destination
+    * @return true only if socket opened successfully
+    */
+    bool open(const char *type, int id, const char* addr, int port);
+
+    /**
+    * Sends data to an open socket
+    *
+    * @param id id of socket to send to
+    * @param data data to be sent
+    * @param amount amount of data to be sent - max 1024
+    * @return true only if data sent successfully
+    */
+    bool send(int id, const void *data, uint32_t amount);
+
+    /**
+    * Receives data from an open socket
+    *
+    * @param id id to receive from
+    * @param data placeholder for returned information
+    * @param amount number of bytes to be received
+    * @return the number of bytes received
+    */
+    int32_t recv(int id, void *data, uint32_t amount);
+
+    /**
+    * Closes a socket
+    *
+    * @param id id of socket to close, valid only 0-4
+    * @return true only if socket is closed successfully
+    */
+    bool close(int id);
+
+    /**
+    * Allows timeout to be changed between commands
+    *
+    * @param timeout_ms timeout of the connection
+    */
+    void setTimeout(uint32_t timeout_ms);
+
+    /**
+    * Checks if data is available
+    */
+    bool readable();
+
+    /**
+    * Checks if data can be written
+    */
+    bool writeable();
+
+    /**
+    * Attach a function to call whenever network state has changed
+    *
+    * @param func A pointer to a void function, or 0 to set as none
+    */
+    void attach(Callback<void()> func);
+
+    /**
+    * Attach a function to call whenever network state has changed
+    *
+    * @param obj pointer to the object to call the member function on
+    * @param method pointer to the member function to call
+    */
+    template <typename T, typename M>
+    void attach(T *obj, M method) {
+        attach(Callback<void()>(obj, method));
+    }
+
+private:
+    BufferedSerial _serial;
+    ATParser _parser;
+
+    struct packet {
+        struct packet *next;
+        int id;
+        uint32_t len;
+        // data follows
+    } *_packets, **_packets_end;
+    void _packet_handler();
+    bool recv_ap(nsapi_wifi_ap_t *ap);
+
+    char _ip_buffer[16];
+    char _gateway_buffer[16];
+    char _netmask_buffer[16];
+    char _mac_buffer[18];
+};
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266Interface.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266Interface.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,282 @@
+/* ESP8266 implementation of NetworkInterfaceAPI
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include "ESP8266Interface.h"
+
+// Various timeouts for different ESP8266 operations
+#define ESP8266_CONNECT_TIMEOUT 15000
+#define ESP8266_SEND_TIMEOUT    500
+#define ESP8266_RECV_TIMEOUT    0
+#define ESP8266_MISC_TIMEOUT    500
+
+// ESP8266Interface implementation
+ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug)
+    : _esp(tx, rx, debug)
+{
+    memset(_ids, 0, sizeof(_ids));
+    memset(_cbs, 0, sizeof(_cbs));
+
+    _esp.attach(this, &ESP8266Interface::event);
+}
+
+int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
+                                        uint8_t channel)
+{
+    if (channel != 0) {
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    set_credentials(ssid, pass, security);
+    return connect();
+}
+
+int ESP8266Interface::connect()
+{
+    _esp.setTimeout(ESP8266_CONNECT_TIMEOUT);
+
+    if (!_esp.startup(3)) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    if (!_esp.dhcp(true, 1)) {
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    if (!_esp.connect(ap_ssid, ap_pass)) {
+        return NSAPI_ERROR_NO_CONNECTION;
+    }
+
+    if (!_esp.getIPAddress()) {
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
+{
+    memset(ap_ssid, 0, sizeof(ap_ssid));
+    strncpy(ap_ssid, ssid, sizeof(ap_ssid));
+
+    memset(ap_pass, 0, sizeof(ap_pass));
+    strncpy(ap_pass, pass, sizeof(ap_pass));
+
+    ap_sec = security;
+
+    return 0;
+}
+
+int ESP8266Interface::set_channel(uint8_t channel)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+
+int ESP8266Interface::disconnect()
+{
+    _esp.setTimeout(ESP8266_MISC_TIMEOUT);
+
+    if (!_esp.disconnect()) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    return NSAPI_ERROR_OK;
+}
+
+const char *ESP8266Interface::get_ip_address()
+{
+    return _esp.getIPAddress();
+}
+
+const char *ESP8266Interface::get_mac_address()
+{
+    return _esp.getMACAddress();
+}
+
+const char *ESP8266Interface::get_gateway()
+{
+    return _esp.getGateway();
+}
+
+const char *ESP8266Interface::get_netmask()
+{
+    return _esp.getNetmask();
+}
+
+int8_t ESP8266Interface::get_rssi()
+{
+    return _esp.getRSSI();
+}
+
+int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count)
+{
+    return _esp.scan(res, count);
+}
+
+struct esp8266_socket {
+    int id;
+    nsapi_protocol_t proto;
+    bool connected;
+    SocketAddress addr;
+};
+
+int ESP8266Interface::socket_open(void **handle, nsapi_protocol_t proto)
+{
+    // Look for an unused socket
+    int id = -1;
+ 
+    for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
+        if (!_ids[i]) {
+            id = i;
+            _ids[i] = true;
+            break;
+        }
+    }
+ 
+    if (id == -1) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    
+    struct esp8266_socket *socket = new struct esp8266_socket;
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    
+    socket->id = id;
+    socket->proto = proto;
+    socket->connected = false;
+    *handle = socket;
+    return 0;
+}
+
+int ESP8266Interface::socket_close(void *handle)
+{
+    struct esp8266_socket *socket = (struct esp8266_socket *)handle;
+    int err = 0;
+    _esp.setTimeout(ESP8266_MISC_TIMEOUT);
+ 
+    if (!_esp.close(socket->id)) {
+        err = NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    _ids[socket->id] = false;
+    delete socket;
+    return err;
+}
+
+int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ESP8266Interface::socket_listen(void *handle, int backlog)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr)
+{
+    struct esp8266_socket *socket = (struct esp8266_socket *)handle;
+    _esp.setTimeout(ESP8266_MISC_TIMEOUT);
+
+    const char *proto = (socket->proto == NSAPI_UDP) ? "UDP" : "TCP";
+    if (!_esp.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+    
+    socket->connected = true;
+    return 0;
+}
+    
+int ESP8266Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
+{
+    struct esp8266_socket *socket = (struct esp8266_socket *)handle;
+    _esp.setTimeout(ESP8266_SEND_TIMEOUT);
+ 
+    if (!_esp.send(socket->id, data, size)) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+ 
+    return size;
+}
+
+int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
+{
+    struct esp8266_socket *socket = (struct esp8266_socket *)handle;
+    _esp.setTimeout(ESP8266_RECV_TIMEOUT);
+ 
+    int32_t recv = _esp.recv(socket->id, data, size);
+    if (recv < 0) {
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+ 
+    return recv;
+}
+
+int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
+{
+    struct esp8266_socket *socket = (struct esp8266_socket *)handle;
+
+    if (socket->connected && socket->addr != addr) {
+        _esp.setTimeout(ESP8266_MISC_TIMEOUT);
+        if (!_esp.close(socket->id)) {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        socket->connected = false;
+    }
+
+    if (!socket->connected) {
+        int err = socket_connect(socket, addr);
+        if (err < 0) {
+            return err;
+        }
+        socket->addr = addr;
+    }
+    
+    return socket_send(socket, data, size);
+}
+
+int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
+{
+    struct esp8266_socket *socket = (struct esp8266_socket *)handle;
+    int ret = socket_recv(socket, data, size);
+    if (ret >= 0 && addr) {
+        *addr = socket->addr;
+    }
+
+    return ret;
+}
+
+void ESP8266Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
+{
+    struct esp8266_socket *socket = (struct esp8266_socket *)handle;    
+    _cbs[socket->id].callback = callback;
+    _cbs[socket->id].data = data;
+}
+
+void ESP8266Interface::event() {
+    for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
+        if (_cbs[i].callback) {
+            _cbs[i].callback(_cbs[i].data);
+        }
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/ESP8266Interface.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/ESP8266Interface.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,275 @@
+/* ESP8266 implementation of NetworkInterfaceAPI
+ * Copyright (c) 2015 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ESP8266_INTERFACE_H
+#define ESP8266_INTERFACE_H
+
+#include "mbed.h"
+#include "ESP8266.h"
+
+
+#define ESP8266_SOCKET_COUNT 5
+
+/** ESP8266Interface class
+ *  Implementation of the NetworkStack for the ESP8266
+ */
+class ESP8266Interface : public NetworkStack, public WiFiInterface
+{
+public:
+    /** ESP8266Interface lifetime
+     * @param tx        TX pin
+     * @param rx        RX pin
+     * @param debug     Enable debugging
+     */
+    ESP8266Interface(PinName tx, PinName rx, bool debug = false);
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
+     *  If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int connect();
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network.
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
+     *  @param channel   This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE,
+                                  uint8_t channel = 0);
+
+    /** Set the WiFi network credentials
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection
+     *                   (defaults to NSAPI_SECURITY_NONE)
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
+
+    /** Set the WiFi network channel - NOT SUPPORTED
+     *
+     * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param channel   Channel on which the connection is to be made, or 0 for any (Default: 0)
+     *  @return          Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual int set_channel(uint8_t channel);
+
+    /** Stop the interface
+     *  @return             0 on success, negative on failure
+     */
+    virtual int disconnect();
+
+    /** Get the internally stored IP address
+     *  @return             IP address of the interface or null if not yet connected
+     */
+    virtual const char *get_ip_address();
+
+    /** Get the internally stored MAC address
+     *  @return             MAC address of the interface
+     */
+    virtual const char *get_mac_address();
+
+     /** Get the local gateway
+     *
+     *  @return         Null-terminated representation of the local gateway
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_gateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_netmask();
+
+    /** Gets the current radio signal strength for active connection
+     *
+     * @return          Connection strength in dBm (negative value)
+     */
+    virtual int8_t get_rssi();
+
+    /** Scan for available networks
+     *
+     * This function will block.
+     *
+     * @param  ap       Pointer to allocated array to store discovered AP
+     * @param  count    Size of allocated @a res array, or 0 to only count available AP
+     * @param  timeout  Timeout in milliseconds; 0 for no timeout (Default: 0)
+     * @return          Number of entries in @a, or if @a count was 0 number of available networks, negative on error
+     *                  see @a nsapi_error
+     */
+    virtual int scan(WiFiAccessPoint *res, unsigned count);
+
+    /** Translates a hostname to an IP address with specific version
+     *
+     *  The hostname may be either a domain name or an IP address. If the
+     *  hostname is an IP address, no network transactions will be performed.
+     *
+     *  If no stack-specific DNS resolution is provided, the hostname
+     *  will be resolve using a UDP socket on the stack.
+     *
+     *  @param address  Destination for the host SocketAddress
+     *  @param host     Hostname to resolve
+     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
+     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::gethostbyname;
+
+    /** Add a domain name server to list of servers to query
+     *
+     *  @param addr     Destination for the host address
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::add_dns_server;
+
+protected:
+    /** Open a socket
+     *  @param handle       Handle in which to store new socket
+     *  @param proto        Type of socket to open, NSAPI_TCP or NSAPI_UDP
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_open(void **handle, nsapi_protocol_t proto);
+
+    /** Close the socket
+     *  @param handle       Socket handle
+     *  @return             0 on success, negative on failure
+     *  @note On failure, any memory associated with the socket must still
+     *        be cleaned up
+     */
+    virtual int socket_close(void *handle);
+
+    /** Bind a server socket to a specific port
+     *  @param handle       Socket handle
+     *  @param address      Local address to listen for incoming connections on
+     *  @return             0 on success, negative on failure.
+     */
+    virtual int socket_bind(void *handle, const SocketAddress &address);
+
+    /** Start listening for incoming connections
+     *  @param handle       Socket handle
+     *  @param backlog      Number of pending connections that can be queued up at any
+     *                      one time [Default: 1]
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_listen(void *handle, int backlog);
+
+    /** Connects this TCP socket to the server
+     *  @param handle       Socket handle
+     *  @param address      SocketAddress to connect to
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_connect(void *handle, const SocketAddress &address);
+
+    /** Accept a new connection.
+     *  @param handle       Handle in which to store new socket
+     *  @param server       Socket handle to server to accept from
+     *  @return             0 on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_accept(void *handle, void **socket, SocketAddress *address);
+
+    /** Send data to the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer to send to the host
+     *  @param size         The length of the buffer to send
+     *  @return             Number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_send(void *handle, const void *data, unsigned size);
+
+    /** Receive data from the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer in which to store the data received from the host
+     *  @param size         The maximum length of the buffer
+     *  @return             Number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_recv(void *handle, void *data, unsigned size);
+
+    /** Send a packet to a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      The remote SocketAddress
+     *  @param data         The packet to be sent
+     *  @param size         The length of the packet to be sent
+     *  @return             The number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);
+
+    /** Receive a packet from a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      Destination for the remote SocketAddress or null
+     *  @param buffer       The buffer for storing the incoming packet data
+     *                      If a packet is too long to fit in the supplied buffer,
+     *                      excess bytes are discarded
+     *  @param size         The length of the buffer
+     *  @return             The number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);
+
+    /** Register a callback on state change of the socket
+     *  @param handle       Socket handle
+     *  @param callback     Function to call on state change
+     *  @param data         Argument to pass to callback
+     *  @note Callback may be called in an interrupt context.
+     */
+    virtual void socket_attach(void *handle, void (*callback)(void *), void *data);
+
+    /** Provide access to the NetworkStack object
+     *
+     *  @return The underlying NetworkStack object
+     */
+    virtual NetworkStack *get_stack()
+    {
+        return this;
+    }
+
+private:
+    ESP8266 _esp;
+    bool _ids[ESP8266_SOCKET_COUNT];
+
+    char ap_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
+    nsapi_security_t ap_sec;
+    uint8_t ap_ch;
+    char ap_pass[64]; /* The longest allowed passphrase */
+
+    void event();
+
+    struct {
+        void (*callback)(void *);
+        void *data;
+    } _cbs[ESP8266_SOCKET_COUNT];
+};
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b easy-connect/esp8266-driver/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/esp8266-driver/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,5 @@
+# esp8266 mbed-os driver
+The driver for the ESP8266 WiFi module
+
+## Firmware version
+esp8266 modules come in different shapes and forms, but most important difference is which firmware version it is programmed with. To make sure that your module has mbed-os compatible firmware follow update guide: https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mbed_lib.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mbed_lib.json	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,9 @@
+{
+    "name": "easy-connect",
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["COMMON_PAL"]
+        }
+    }
+}
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mcr20a-rf-driver/#d8810e105d7d35315aa708ec51d821156cad45e9
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/FETCH_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/FETCH_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+d8810e105d7d35315aa708ec51d821156cad45e9		branch 'master' of https://github.com/ARMmbed/mcr20a-rf-driver
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/ORIG_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/ORIG_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+d8810e105d7d35315aa708ec51d821156cad45e9
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/config
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/config	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/mcr20a-rf-driver/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/description
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/description	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/hooks/applypatch-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/hooks/applypatch-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/hooks/commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/hooks/commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/hooks/post-update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/hooks/post-update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/hooks/pre-applypatch.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/hooks/pre-applypatch.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/hooks/pre-commit.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/hooks/pre-commit.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/hooks/pre-rebase.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/hooks/pre-rebase.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/hooks/prepare-commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/hooks/prepare-commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/hooks/update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/hooks/update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/index
Binary file easy-connect/mcr20a-rf-driver/.git/index has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/info/exclude
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/info/exclude	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,25 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/logs/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/logs/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 d8810e105d7d35315aa708ec51d821156cad45e9 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036526 +0000	clone: from https://github.com/ARMmbed/mcr20a-rf-driver/
+d8810e105d7d35315aa708ec51d821156cad45e9 d8810e105d7d35315aa708ec51d821156cad45e9 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036527 +0000	checkout: moving from master to d8810e105d7d35315aa708ec51d821156cad45e9
+d8810e105d7d35315aa708ec51d821156cad45e9 d8810e105d7d35315aa708ec51d821156cad45e9 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036527 +0000	checkout: moving from d8810e105d7d35315aa708ec51d821156cad45e9 to master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/logs/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/logs/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 d8810e105d7d35315aa708ec51d821156cad45e9 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036526 +0000	clone: from https://github.com/ARMmbed/mcr20a-rf-driver/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/logs/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/logs/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 d8810e105d7d35315aa708ec51d821156cad45e9 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036526 +0000	clone: from https://github.com/ARMmbed/mcr20a-rf-driver/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/02/865db7ef99ebab8b7ed5e1b5c19180d7001e2f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/02/865db7ef99ebab8b7ed5e1b5c19180d7001e2f	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+x+)JMU027c040031Qðu22p)*ÓKfHâoÝñ÷þwÞNÃ9–ê¯9®üu]UÄÍG˜b¦ÍÖ_•ü©íH¸pØÆȅK‘Uù—¥•e–¤ëe0x3)
+k/øñ;fí¦„Ysë{´öÈ"+JMªZs(j™ÀºVÿ"ç?ç˜XWW‹î›®U‘\V\©—\PÀpøÓ©wdK|ßÅù•9ì?¶Û=MYé°SÏN=øv÷÷ª+õÚ#ç5ËC¥eÝäQ	ôí×[¿_jøß-ð—ïg¶}ñ¼¨SL«
+<p½
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/0a/8554f3274c0bd641370e7847051bacfdeb8a66
Binary file easy-connect/mcr20a-rf-driver/.git/objects/0a/8554f3274c0bd641370e7847051bacfdeb8a66 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/0c/1a2859120b36fac35ce950bd266d04e3ed8507
Binary file easy-connect/mcr20a-rf-driver/.git/objects/0c/1a2859120b36fac35ce950bd266d04e3ed8507 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/0e/4cf3ee99953ca19984fe31ffe0644f6ab37f04
Binary file easy-connect/mcr20a-rf-driver/.git/objects/0e/4cf3ee99953ca19984fe31ffe0644f6ab37f04 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/0f/a954a6c35d007da7c03f62ecc17f21f75652de
Binary file easy-connect/mcr20a-rf-driver/.git/objects/0f/a954a6c35d007da7c03f62ecc17f21f75652de has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/18/40de743f199fc7f402ff7bd3c56ccc58954c16
Binary file easy-connect/mcr20a-rf-driver/.git/objects/18/40de743f199fc7f402ff7bd3c56ccc58954c16 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/19/a06dee5ede2f7c27cce52cfb328e6006576c98
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/19/a06dee5ede2f7c27cce52cfb328e6006576c98	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x¥Ž1jÄ0ESëÓ/i$[2,!°EúÜ`4{
+ÙÈÚäúQ’#¤ùð^ñø¼ç¼5ÀÙ¼´*qŽÆ”8Zbo-êÅ0êˆs˜È9Ínöˆ4©ƒª”cš9ôÑY¦Ä™…x^Ðù<éqò#Û¨=Û}¯ð.{]ntTªO¸®¿<ð¿-ýÃÉô÷ü
+Æ9¯½÷v„‹F­U·ýn“‡Ô‡äýSôâ±=zð‹jÙÊz•›¤Ï™¥m|§²Ê9¨o¨p_±
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/20/8d0295c1411f67259867fd86272a9dfe43cc3d
Binary file easy-connect/mcr20a-rf-driver/.git/objects/20/8d0295c1411f67259867fd86272a9dfe43cc3d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/22/04c03fb0924bc71c988a1ce9a52d5db7e803c9
Binary file easy-connect/mcr20a-rf-driver/.git/objects/22/04c03fb0924bc71c988a1ce9a52d5db7e803c9 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/2d/75557d97f1cae0d34baf502dcfcbd07ce45343
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/2d/75557d97f1cae0d34baf502dcfcbd07ce45343	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+xeQKÃ0…}Þ¯¸ôن¶«0dˆÓ1ñe>Šƒ4¹Õ°47]‡Êþ»7íª¢o9¹'÷;9•õ”åììs8Ù`r	I£¨ÈdJuªÉtHÉyœò!ï¢!™È‡[A‘Ùµ§Ézè=ÁŠÇÒ"<Þ®‹l…(ïî?`–"¿%¡Å %é‚ÂÚßžt`Ü3әOuOäÓ¯T¬Æe	Û^ú¤rß¾yŠANxðT惃¼®ÇtBùæjøŽ5
+]è[¸yZÂ4UVîY÷{5îÐitÊ`Ì;c¾“·VªmjM:^ٛ)·”™ƒ´éàúöÿ75êSçÌó~sŽ}€VÒ+¶Ë?1Ž“ã䎃4
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/2e/9215af72d17010b1fd609eadb351a035386cf9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/2e/9215af72d17010b1fd609eadb351a035386cf9	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+x¥ÍjÃ@„{öSèÖCÁìãµ!”†”ôÐ[¥W­Vëb¯Y¯›æí+ÚGèe`¾‘ĈÒ4¬S%3ƒÕÞµ¬MGJ#ùÞ:Ó;…Ñ’
+MÀÞxT1ÚX-˜y.,»v§7žœ'Rè‚&çtgìÎú]£tçÛØV¸•KÊðÆ)G\2æ
öï¯éÏ¿Dé°^¹¦4=ƒnšNé¾·ž”Qª*uÿûPuP
+,2MòËZW¯ãŠþÊ°ÍÛ*éçñãeœ8Kv¿ùm€Û…3C¹0œOòø%uBâu~,0§2Æ;lË"ðŠwQŸ…Ãáø7\!3±ì„ºú¼azÃ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/31/b76e128c01acb9372970af3c0d4da92ba0ff3f
Binary file easy-connect/mcr20a-rf-driver/.git/objects/31/b76e128c01acb9372970af3c0d4da92ba0ff3f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/3d/16f39f0b355ed14d158a5ad2ef66c345fd2669
Binary file easy-connect/mcr20a-rf-driver/.git/objects/3d/16f39f0b355ed14d158a5ad2ef66c345fd2669 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/40/97116916be1b04358ba3e84569012380657836
Binary file easy-connect/mcr20a-rf-driver/.git/objects/40/97116916be1b04358ba3e84569012380657836 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/42/6961ba19e931271a202d1a43173b19976a45c4
Binary file easy-connect/mcr20a-rf-driver/.git/objects/42/6961ba19e931271a202d1a43173b19976a45c4 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/43/cb369dc7aa155af93995bb358bd259f891dda5
Binary file easy-connect/mcr20a-rf-driver/.git/objects/43/cb369dc7aa155af93995bb358bd259f891dda5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/4b/0221132ba0f8fb5cadb2609a9d7f8c2abc1e51
Binary file easy-connect/mcr20a-rf-driver/.git/objects/4b/0221132ba0f8fb5cadb2609a9d7f8c2abc1e51 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/4e/1413bd42d39b48bd0547d8814d9d70529dabad
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/4e/1413bd42d39b48bd0547d8814d9d70529dabad	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x¥ŽKj1³žSôÞ`Z­ÑBH0$ûÜ@în9k5ñõ#’#dYGQ\×ué@žzSq83atE„Œ‹ÉbASHÒÙ&+1æhSœ¶ÜôÖÁ¤Œ^TŠR	LYq9[Šê½žÇ?ïý«6øÐÚ.
+§¼µÜvx¾üò‘ÿøµŒ†;竹®/`æ9`ˆÆy8 !Nc¹]ÿ-šÞDàZ°ÕÇ°Ý÷­¶Ë
>ßAÚò­múíOX]
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/51/0214274c3a49819284e615389d631ca912ce15
Binary file easy-connect/mcr20a-rf-driver/.git/objects/51/0214274c3a49819284e615389d631ca912ce15 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/55/8982806e80b6ece3193ff27e41a449277f853c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/55/8982806e80b6ece3193ff27e41a449277f853c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+x•ŽQ
+!EûvnÀPGí	1´•ç{ÚŒfA»o 6ÐßáÀ¹\jµ®CZç£ç,9x˜x*T
+g0D&`ƒ 
ûàJÔìc‚(îØómH
+9â‚ô#Ă	AâX؂	 ð9–Ö%QëËc“ç/ÒåKkGju–ƹ	L<i-•öZ‹ÝîÿFþ¿8jÞT/ŠûúÚ”še¥n5ªÎ?)>¿|Ov
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/55/8ecca761792e7c80d03a5c0e99e47d49aadde3
Binary file easy-connect/mcr20a-rf-driver/.git/objects/55/8ecca761792e7c80d03a5c0e99e47d49aadde3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/55/ed7949e6509ddcfe671046dc8e6bc6453fb767
Binary file easy-connect/mcr20a-rf-driver/.git/objects/55/ed7949e6509ddcfe671046dc8e6bc6453fb767 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/59/48bc25260f0f636066c51c7a270d468f0583ce
Binary file easy-connect/mcr20a-rf-driver/.git/objects/59/48bc25260f0f636066c51c7a270d468f0583ce has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/5d/6da427b48ef68de41fac9f2478d7a05675c3b0
Binary file easy-connect/mcr20a-rf-driver/.git/objects/5d/6da427b48ef68de41fac9f2478d7a05675c3b0 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/62/0e5785b8fddff70d89319c3927eb08a1a9fad9
Binary file easy-connect/mcr20a-rf-driver/.git/objects/62/0e5785b8fddff70d89319c3927eb08a1a9fad9 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/63/037691d31e5413017548618fabfc13ea00962e
Binary file easy-connect/mcr20a-rf-driver/.git/objects/63/037691d31e5413017548618fabfc13ea00962e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/65/e678ec229fe585dede1e6d6ceb2d29fcfc62f1
Binary file easy-connect/mcr20a-rf-driver/.git/objects/65/e678ec229fe585dede1e6d6ceb2d29fcfc62f1 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/67/83dfd110a5b808c5e1a5c09af0ba4b4818a75d
Binary file easy-connect/mcr20a-rf-driver/.git/objects/67/83dfd110a5b808c5e1a5c09af0ba4b4818a75d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/70/ce9021485641775f9581928f71ef06450f418e
Binary file easy-connect/mcr20a-rf-driver/.git/objects/70/ce9021485641775f9581928f71ef06450f418e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/71/f0db96a14bcfad5c51286ba67aec53a3674224
Binary file easy-connect/mcr20a-rf-driver/.git/objects/71/f0db96a14bcfad5c51286ba67aec53a3674224 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/72/e873f0923bc4e89240029f43e9cb23ab674010
Binary file easy-connect/mcr20a-rf-driver/.git/objects/72/e873f0923bc4e89240029f43e9cb23ab674010 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/74/71c50c837b4b85d8f283182a23459d31793416
Binary file easy-connect/mcr20a-rf-driver/.git/objects/74/71c50c837b4b85d8f283182a23459d31793416 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/75/db2c976f25deba71e83141e88207472f633cfd
Binary file easy-connect/mcr20a-rf-driver/.git/objects/75/db2c976f25deba71e83141e88207472f633cfd has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/76/f34a69bbb943fe6f7fa00a011d7030e3383bf3
Binary file easy-connect/mcr20a-rf-driver/.git/objects/76/f34a69bbb943fe6f7fa00a011d7030e3383bf3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/79/a446a98e48485c9f91edf7bdb1d12167e3b7fc
Binary file easy-connect/mcr20a-rf-driver/.git/objects/79/a446a98e48485c9f91edf7bdb1d12167e3b7fc has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/7b/9a0ec7821de45f92ec0383eec2f02ea74932ff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/7b/9a0ec7821de45f92ec0383eec2f02ea74932ff	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x¥ŽÍjÃ0„{öSì=`ô/Ji¥âCK_@^­“‚	Yv_¿¢qŸ ·of‡Á8Ï_¤ä%U–£fè¤Ôàtp£p’;á…Tº’ÛN*nšä3Ý
+ä¦ÓŒ†!
nt'*EƒÂÔ?6*†J5~-טá•b¾œ|Ê>¯ðxùÕ-ÞõóX7,è'j1ÎOÀ•²’kf˜`¬©´Î-ô÷)Q€ãgÿr†¿kåDMÄ­ÞýéC°#l~ZiiÿÒ;=¿¿í”³/x݋îùæ/iÍ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/7b/caf35e20fdcb92e43d2aa23903f041411e958c
Binary file easy-connect/mcr20a-rf-driver/.git/objects/7b/caf35e20fdcb92e43d2aa23903f041411e958c has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/84/fa8c082c87a2c4e4362605979e4e89c0e931c7
Binary file easy-connect/mcr20a-rf-driver/.git/objects/84/fa8c082c87a2c4e4362605979e4e89c0e931c7 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/85/8335a2b2b1b7b003319143c879b6783c18e4cb
Binary file easy-connect/mcr20a-rf-driver/.git/objects/85/8335a2b2b1b7b003319143c879b6783c18e4cb has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/8e/cf5b680ac9e4c2e8720a48324efbf1b1bd86f3
Binary file easy-connect/mcr20a-rf-driver/.git/objects/8e/cf5b680ac9e4c2e8720a48324efbf1b1bd86f3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/90/b3c4025c969b2faa63f286c4571356b159a1a5
Binary file easy-connect/mcr20a-rf-driver/.git/objects/90/b3c4025c969b2faa63f286c4571356b159a1a5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/95/0e428af5013a721584e45d71b45421d40158bc
Binary file easy-connect/mcr20a-rf-driver/.git/objects/95/0e428af5013a721584e45d71b45421d40158bc has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/95/26bfc5c480d5eab26293f158095da3dcde9a0e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/95/26bfc5c480d5eab26293f158095da3dcde9a0e	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x]AK1…=÷W{vÃîvED¬–*ˆ—zÙdVC³I™l[Túߝd[-Þòò^æ{™Æúêzzñ=Ȝì0»‚¬ST2§6×dvHÙetùŒw1PˆB”íƠÈlú£³\ÀðZO° d[Z„çûeUÌ õÃãL‹J”QÃÞZz’.(ü£­ñsïIƽ2ùÔ&"ŸÎZ±:
Ë8ö–šÊmÿá)9MhàÉï¤
+p=H1ÈÛöÔN(ßÝß±F¡iw/sçÊÊ-ë4WãF§Æ^qgÌwÒùÐKµÎ­iҎGDöjÌ[*Nƒ´ùúͧÐä<Ô5¨;€lU&—9‡T —ôŽýü_Ãè0ú °ƒX
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/97/2c8c3de8a2a362d1dcb91e345dd7c5522e9305
Binary file easy-connect/mcr20a-rf-driver/.git/objects/97/2c8c3de8a2a362d1dcb91e345dd7c5522e9305 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/97/421f5031567f4fc597d9a56e029c23f00caa13
Binary file easy-connect/mcr20a-rf-driver/.git/objects/97/421f5031567f4fc597d9a56e029c23f00caa13 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/97/df0e645d35bdd2071ab3c147eff48d500dde44
Binary file easy-connect/mcr20a-rf-driver/.git/objects/97/df0e645d35bdd2071ab3c147eff48d500dde44 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/a2/42e35bcea673ac39310b463fa06311bdca17de
Binary file easy-connect/mcr20a-rf-driver/.git/objects/a2/42e35bcea673ac39310b463fa06311bdca17de has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/a2/8948345dfbd89719c60b765a9837ffbd434a2e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/a2/8948345dfbd89719c60b765a9837ffbd434a2e	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+xŽ½J1F­ó·^Ù!“ÿ€È‚¥•ýMæƄ%ɒ‰Šo­å9|œØk-„÷wsARRDãàÖh焰ܨ„Êš5j©Ðˆ¶Än8¨MH)Ú$<*Ô)Dë´´…ÔèÑ#ß4§Äð}æ>à÷†¥ÁkWxÈ¿´|tÁQ—Øë#¬ÊxëWm%ÜsÉ9;ì9éŸwöÔÇ 8K{ƒ™	n83¤#¦ږÌØ	^þ*(;´þ	ûW‹´Áì?ÓsßÏzYξ-P_„
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/a4/ac803efe4c6b4adecb1c9b56c16be1f7802c66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/a4/ac803efe4c6b4adecb1c9b56c16be1f7802c66	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+x¥Ž=
+1F­sŠéI&?“ÅÂÊÆd³
¸‰Ñóô6¼W|¼Xæ97@R«V™ì4bÈ%´{­L_’arZÇ4‰G¨¼4°Ö½tìåè8²VƒN	‰
+ÆH”¼ÕQ„W»•
+'.õÊpê¶×/oâ÷©7<c¸ó&–yÊGÚ¯`-QJÑmÏmü÷‘ÈKn9ÜáÍõ™Ë%ÁùxAy€©æ.Å RW 
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/a5/6963aed6bef9d940e8d5708e06be2d71d929c8
Binary file easy-connect/mcr20a-rf-driver/.git/objects/a5/6963aed6bef9d940e8d5708e06be2d71d929c8 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/a8/6dff3733344fb6369a5aaba25773f56042ff18
Binary file easy-connect/mcr20a-rf-driver/.git/objects/a8/6dff3733344fb6369a5aaba25773f56042ff18 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/aa/5667ef467392729cf49612b8da3e8ecbab9120
Binary file easy-connect/mcr20a-rf-driver/.git/objects/aa/5667ef467392729cf49612b8da3e8ecbab9120 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/aa/927dde7777cbb59654ea4f643e2eafd9d24db3
Binary file easy-connect/mcr20a-rf-driver/.git/objects/aa/927dde7777cbb59654ea4f643e2eafd9d24db3 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/ac/c25aa610ae854f7243fcce0205ab7b15be972d
Binary file easy-connect/mcr20a-rf-driver/.git/objects/ac/c25aa610ae854f7243fcce0205ab7b15be972d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/af/b0b546ecdd51f44169a66d906c5b65c2039da1
Binary file easy-connect/mcr20a-rf-driver/.git/objects/af/b0b546ecdd51f44169a66d906c5b65c2039da1 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/b1/ddea7d63ddbdc6e2ca59af6316f71ee8f9e70d
Binary file easy-connect/mcr20a-rf-driver/.git/objects/b1/ddea7d63ddbdc6e2ca59af6316f71ee8f9e70d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/b3/a7d6982e43c7ba5a1db261e467571b36215683
Binary file easy-connect/mcr20a-rf-driver/.git/objects/b3/a7d6982e43c7ba5a1db261e467571b36215683 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/b5/90d12182647706581b143c94012c1462d619b8
Binary file easy-connect/mcr20a-rf-driver/.git/objects/b5/90d12182647706581b143c94012c1462d619b8 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/b9/7c819a0e740b7f717b2981f75fe380827a1692
Binary file easy-connect/mcr20a-rf-driver/.git/objects/b9/7c819a0e740b7f717b2981f75fe380827a1692 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/b9/b1382eb53ac73320f1c20b2986a440c49722a6
Binary file easy-connect/mcr20a-rf-driver/.git/objects/b9/b1382eb53ac73320f1c20b2986a440c49722a6 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/bc/5fe10fd97e239e5a26019580bf7c84e08cd97d
Binary file easy-connect/mcr20a-rf-driver/.git/objects/bc/5fe10fd97e239e5a26019580bf7c84e08cd97d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/c3/0d737b6eb86ea642f9ff66603945d3ee045ebf
Binary file easy-connect/mcr20a-rf-driver/.git/objects/c3/0d737b6eb86ea642f9ff66603945d3ee045ebf has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/c3/f2caeea01d744dee5e4e7640bfcfcd8b47075e
Binary file easy-connect/mcr20a-rf-driver/.git/objects/c3/f2caeea01d744dee5e4e7640bfcfcd8b47075e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/c6/d6bc4cdb6628a5a9989fab8bc8e8cd9fd28168
Binary file easy-connect/mcr20a-rf-driver/.git/objects/c6/d6bc4cdb6628a5a9989fab8bc8e8cd9fd28168 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/c9/bad045a769d69d9709505db2db43c5c59da62d
Binary file easy-connect/mcr20a-rf-driver/.git/objects/c9/bad045a769d69d9709505db2db43c5c59da62d has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/ca/29a807256ea38445915c68d57eadff7c2f4331
Binary file easy-connect/mcr20a-rf-driver/.git/objects/ca/29a807256ea38445915c68d57eadff7c2f4331 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/ca/56cae6cae0f6ddd60baaa8a92e87599d32831f
Binary file easy-connect/mcr20a-rf-driver/.git/objects/ca/56cae6cae0f6ddd60baaa8a92e87599d32831f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/cc/4b9cb12a800bdcf4b9f125230c28bbff6d32dd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/cc/4b9cb12a800bdcf4b9f125230c28bbff6d32dd	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x+)JMU027c040031Qðu22p)*ÓKfHâoÝñ÷þwÞNÃ9–ê¯9®üu]UÄÍG˜b¦ÍÖ_•ü©íH¸pØÆȅK‘Uù—¥•e–¤ëe0x3)
+k/øñ;fí¦„Ysë{´öÈ"+JMªZs(j™ÀºVÿ"ç?ç˜XWW‹î›®U‘\V\©—\PÀpøÓ©wdK|ßÅù•9ì?¶Û=MYé°SÏN=øv÷÷ª+õÚ#ç5ËC¥eÝäQ	ôíú
[ÝÞÜ
ü☹,wBNtê!æ¹ô¡oŒ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/cc/964c3d20a90fac64f7e640fbdcecc105fd5970
Binary file easy-connect/mcr20a-rf-driver/.git/objects/cc/964c3d20a90fac64f7e640fbdcecc105fd5970 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/cc/f8ef134d4bd64a643af9f5d52802484df0caa9
Binary file easy-connect/mcr20a-rf-driver/.git/objects/cc/f8ef134d4bd64a643af9f5d52802484df0caa9 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/cd/38b72090af7baac8c9ccfb76709ea8eacad749
Binary file easy-connect/mcr20a-rf-driver/.git/objects/cd/38b72090af7baac8c9ccfb76709ea8eacad749 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/d3/e76502e4bc7bcc0a7d1c77182353b54018b6f6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/d3/e76502e4bc7bcc0a7d1c77182353b54018b6f6	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+x¥ÁjÃ0D{öW¹Œ,[±¡4Zz(´i¹n¤Ubp¤T’	ùû*Í'ô8ÃÎÛaL8ÆŒvèrd©¥^¶Äv¹g§­îVõb`QiûÆj©ÍP)²Ï°F3;ån{AJ*ëÓ³•Tܚ’Q´¯hÎÇñÊ!:GŠ3V‡?]›»~v¥C24qmÂé	M×õƒÔƒêñ(¤UqKÝÌÿU_ì-‹Í‘¼ç	kc8%¼Ð8͑H™òœÞ×Lt-?GòØî0&ŒçñºÙÖ÷Jˆü3sÊlëê#†;uœJçoÛO?]áÊ•n×Þp]ý~_¶
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/d5/04c2085fdd21e130930f01f2d9b393d88a8398
Binary file easy-connect/mcr20a-rf-driver/.git/objects/d5/04c2085fdd21e130930f01f2d9b393d88a8398 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/d5/806d6ebede85680f75302f3fdad97a0050fb73
Binary file easy-connect/mcr20a-rf-driver/.git/objects/d5/806d6ebede85680f75302f3fdad97a0050fb73 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/d6/583d3fcffde81ccd638d1a801d564f90d59b89
Binary file easy-connect/mcr20a-rf-driver/.git/objects/d6/583d3fcffde81ccd638d1a801d564f90d59b89 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/d7/8395e8087d68381c9476391fae880c1c76300f
Binary file easy-connect/mcr20a-rf-driver/.git/objects/d7/8395e8087d68381c9476391fae880c1c76300f has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/d8/810e105d7d35315aa708ec51d821156cad45e9
Binary file easy-connect/mcr20a-rf-driver/.git/objects/d8/810e105d7d35315aa708ec51d821156cad45e9 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/dc/169501b60ceb8f89ae8ddc1c6c261820f40c44
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/dc/169501b60ceb8f89ae8ddc1c6c261820f40c44	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+x¥MKÃ@†=çWÌQÂ~¥Ù€ˆP¬xÓ â­ÌìNÚ@’
ۍ¶ÿލü^†y_†‡g\Ç>®ìUŠÌ`+«u…ŠIªI­e#v¶nhS[í¤e㨘1ò”À°4R“7Ê놌%/*S{k¥ñ¯E¥„¾À%C„'ñÀ°Å9b\àîð“K÷›ºìpr8péÂxҘZn”Un…¢ÈmÖMüoPñ8!
8y8æ‘×]?dðûžÛײx‰ü¹¾ØžÁcBp!ÆeN}˜Àárbt‰¿àíüwì—q¼ÀÇö½]!€Ýê»=Rˆéú¦,¾Ö!u
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/dc/321419e543344fd18d7facb378c2f3b82f63e8
Binary file easy-connect/mcr20a-rf-driver/.git/objects/dc/321419e543344fd18d7facb378c2f3b82f63e8 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/dc/9eef5f8e370a525df1c7ed24d0125e3c2d75ab
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/dc/9eef5f8e370a525df1c7ed24d0125e3c2d75ab	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+x¥ŽKNÄ0DYû½GŠüËؖ
Ÿs4ív°”Ø‘Ç§ÇÀXV•ªêQݶÜÁ(Ó3ÌJjeµ³dЯ‚ö–Oj6>ēQ„Aib5‹—î- dr^«ÈvNA3Iã
3é$5£³Áè”ý½6xåÚ†3î
Ûw˯žèO?¤Áp!\y¢ºÝƒ²ÖYå‚	p+µ”b¸·ó¿‡Ä¹F†º÷¼å/칖Ë$^ò'G{^ÇŶ’Ë2‚ÇGð\¸-WxâÎÔ!…~z¸æ~Ä7Š¤hõ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/de/d8678fad855d8ca6b669dd448e03404ca6fc9f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/objects/de/d8678fad855d8ca6b669dd448e03404ca6fc9f	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+x]AK1…=÷W{vCº]a«¥
+â¥E!›Ìjh6)“m‹Jû۝ì¶V¼eò^æ{yµ5”euö=ȼj1»„¬ÕTH•S“²¤ì<©|ˆ6ødBŠñpk0j²«î ,æ0¼&Ì	YVáénQÈ)¢¼ø‚Jb|!JØZB‡1BGÊG'Ú?·LdÜәOMOäӟT<—el{퓪u÷(zChá1l”Žp5Œbošc:¡C{=|ÇY>ö-Ü>Ï`’k§Ö<÷{
®ÐôÚbʕ:c¾W>ÄNéeîl‘6¼"±÷nI3GåòÁõëO¦7.âdjk4‡Î ÛKQ±Êœ] SôŽÝì_ŒÝh7ú4ƒ
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/e1/e674c8b81f384254d415dcf6e42805a8eaad3a
Binary file easy-connect/mcr20a-rf-driver/.git/objects/e1/e674c8b81f384254d415dcf6e42805a8eaad3a has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/eb/6f2c8e201c9f8228bcecd525415fb534129e1b
Binary file easy-connect/mcr20a-rf-driver/.git/objects/eb/6f2c8e201c9f8228bcecd525415fb534129e1b has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/eb/99aed8db609de6df1874113d7ca16be82782d5
Binary file easy-connect/mcr20a-rf-driver/.git/objects/eb/99aed8db609de6df1874113d7ca16be82782d5 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/ee/8495c80d204ddf972bf5f61d4f6e8ecac88261
Binary file easy-connect/mcr20a-rf-driver/.git/objects/ee/8495c80d204ddf972bf5f61d4f6e8ecac88261 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/f3/2a5c3737a70dc828a90f140cf398ee9fbf176e
Binary file easy-connect/mcr20a-rf-driver/.git/objects/f3/2a5c3737a70dc828a90f140cf398ee9fbf176e has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/f4/32c6962076588227064fa4761bea534a62fbdf
Binary file easy-connect/mcr20a-rf-driver/.git/objects/f4/32c6962076588227064fa4761bea534a62fbdf has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/f5/710629b84db1290f7d4f8417fa638e896e3ae4
Binary file easy-connect/mcr20a-rf-driver/.git/objects/f5/710629b84db1290f7d4f8417fa638e896e3ae4 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/f5/f8b5f7d280ff8b10fd0ef96b3f739e5aca02ab
Binary file easy-connect/mcr20a-rf-driver/.git/objects/f5/f8b5f7d280ff8b10fd0ef96b3f739e5aca02ab has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/f6/fbfc172fc798d2f1c15a49fadae84ed3f6b3c6
Binary file easy-connect/mcr20a-rf-driver/.git/objects/f6/fbfc172fc798d2f1c15a49fadae84ed3f6b3c6 has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/fb/aec7f29a4a5fbc785378a235a9a866cc0d50ef
Binary file easy-connect/mcr20a-rf-driver/.git/objects/fb/aec7f29a4a5fbc785378a235a9a866cc0d50ef has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/objects/fc/1e7ca40846577040c56df52889ba212e0c24ae
Binary file easy-connect/mcr20a-rf-driver/.git/objects/fc/1e7ca40846577040c56df52889ba212e0c24ae has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/packed-refs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/packed-refs	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+# pack-refs with: peeled 
+a28948345dfbd89719c60b765a9837ffbd434a2e refs/remotes/origin/fixing_mbed_path
+d8810e105d7d35315aa708ec51d821156cad45e9 refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+d8810e105d7d35315aa708ec51d821156cad45e9
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.git/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.git/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.gitignore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.gitignore	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,6 @@
+*~
+*.swo
+*.swp
+build
+yotta_modules
+yotta_targets
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/.meta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/.meta	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/LICENSE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/LICENSE	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,6 @@
+# Example RF driver for Freescale 802.15.4 transceivers #
+
+Support for:
+ * MCR20A
+
+This driver is used with 6LoWPAN stack.
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/apache-2.0.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/apache-2.0.txt	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NANOSTACK_PHY_MCR20A_H_
+#define NANOSTACK_PHY_MCR20A_H_
+
+#include "mbed.h"
+#include "NanostackRfPhy.h"
+
+// Arduino pin defaults for convenience
+#if !defined(MCR20A_SPI_MOSI)
+#define MCR20A_SPI_MOSI   D11
+#endif
+#if !defined(MCR20A_SPI_MISO)
+#define MCR20A_SPI_MISO   D12
+#endif
+#if !defined(MCR20A_SPI_SCLK)
+#define MCR20A_SPI_SCLK   D13
+#endif
+#if !defined(MCR20A_SPI_CS)
+#define MCR20A_SPI_CS     D10
+#endif
+#if !defined(MCR20A_SPI_RST)
+#define MCR20A_SPI_RST    D5
+#endif
+#if !defined(MCR20A_SPI_IRQ)
+#define MCR20A_SPI_IRQ    D2
+#endif
+
+class NanostackRfPhyMcr20a : public NanostackRfPhy {
+public:
+    NanostackRfPhyMcr20a(PinName spi_mosi, PinName spi_miso,
+                         PinName spi_sclk, PinName spi_cs,  PinName spi_rst,
+                         PinName spi_irq);
+    ~NanostackRfPhyMcr20a();
+    int8_t rf_register();
+    void rf_unregister();
+    void get_mac_address(uint8_t *mac);
+    void set_mac_address(uint8_t *mac);
+
+private:
+    SPI _spi;
+    DigitalOut _rf_cs;
+    DigitalOut _rf_rst;
+    InterruptIn _rf_irq;
+    DigitalIn _rf_irq_pin;
+
+    void _pins_set();
+    void _pins_clear();
+};
+
+#endif /* NANOSTACK_PHY_MCR20A_H_ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/module.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/module.json	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,18 @@
+{
+  "name": "mcr20a-rf-driver",
+  "version": "0.0.1",
+  "description": "RF driver for Freescale MCR20A 2.4GHz 802.15.4 wireless transceiver",
+  "keywords": [
+    "rf",
+    "driver",
+    "802.15.4"
+  ],
+  "author": "Andrei Kovacs <Andrei.Kovacs@freescale.com>",
+  "license": "BSD 3-clause",
+  "dependencies": {
+    "nanostack-libservice": "^3.0.0",
+    "sal-stack-nanostack": "^5.0.0",
+    "mbed-drivers": "^1.0.0"
+  },
+  "targetDependencies": {}
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/source/MCR20Drv.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/source/MCR20Drv.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,675 @@
+/*!
+* Copyright (c) 2015, Freescale Semiconductor, Inc.
+* All rights reserved.
+*
+* \file MCR20Drv.c
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* o Redistributions of source code must retain the above copyright notice, this list
+*   of conditions and the following disclaimer.
+*
+* o Redistributions in binary form must reproduce the above copyright notice, this
+*   list of conditions and the following disclaimer in the documentation and/or
+*   other materials provided with the distribution.
+*
+* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+*   contributors may be used to endorse or promote products derived from this
+*   software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*****************************************************************************
+*                               INCLUDED HEADERS                            *
+*---------------------------------------------------------------------------*
+* Add to this section all the headers that this module needs to include.    *
+*---------------------------------------------------------------------------*
+*****************************************************************************/
+
+#include "platform/arm_hal_interrupt.h"
+#include "MCR20Drv.h"
+#include "MCR20Reg.h"
+#include "XcvrSpi.h"
+
+
+/*****************************************************************************
+*                               PRIVATE VARIABLES                           *
+*---------------------------------------------------------------------------*
+* Add to this section all the variables and constants that have local       *
+* (file) scope.                                                             *
+* Each of this declarations shall be preceded by the 'static' keyword.      *
+* These variables / constants cannot be accessed outside this module.       *
+*---------------------------------------------------------------------------*
+*****************************************************************************/
+uint32_t mPhyIrqDisableCnt = 1;
+
+/*****************************************************************************
+*                               PUBLIC VARIABLES                            *
+*---------------------------------------------------------------------------*
+* Add to this section all the variables and constants that have global      *
+* (project) scope.                                                          *
+* These variables / constants can be accessed outside this module.          *
+* These variables / constants shall be preceded by the 'extern' keyword in  *
+* the interface header.                                                     *
+*---------------------------------------------------------------------------*
+*****************************************************************************/
+
+/*****************************************************************************
+*                           PRIVATE FUNCTIONS PROTOTYPES                    *
+*---------------------------------------------------------------------------*
+* Add to this section all the functions prototypes that have local (file)   *
+* scope.                                                                    *
+* These functions cannot be accessed outside this module.                   *
+* These declarations shall be preceded by the 'static' keyword.             *
+*---------------------------------------------------------------------------*
+*****************************************************************************/
+
+/*****************************************************************************
+*                                PRIVATE FUNCTIONS                          *
+*---------------------------------------------------------------------------*
+* Add to this section all the functions that have local (file) scope.       *
+* These functions cannot be accessed outside this module.                   *
+* These definitions shall be preceded by the 'static' keyword.              *
+*---------------------------------------------------------------------------*
+*****************************************************************************/
+
+
+/*****************************************************************************
+*                             PUBLIC FUNCTIONS                              *
+*---------------------------------------------------------------------------*
+* Add to this section all the functions that have global (project) scope.   *
+* These functions can be accessed outside this module.                      *
+* These functions shall have their declarations (prototypes) within the     *
+* interface header file and shall be preceded by the 'extern' keyword.      *
+*---------------------------------------------------------------------------*
+*****************************************************************************/
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_Init
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_Init
+(
+void
+)
+{
+    xcvr_spi_init(gXcvrSpiInstance_c);
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000);
+
+    gXcvrDeassertCS_d();
+    MCR20Drv_RST_B_Deassert();
+    RF_IRQ_Init();
+    RF_IRQ_Disable();
+    mPhyIrqDisableCnt = 1;
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_DirectAccessSPIWrite
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_DirectAccessSPIWrite
+(
+uint8_t address,
+uint8_t value
+)
+{
+    uint16_t txData;
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 16000000);
+
+    gXcvrAssertCS_d();
+
+    txData = (address & TransceiverSPI_DirectRegisterAddressMask);
+    txData |= value << 8;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t *)&txData, 0, sizeof(txData));
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_DirectAccessSPIMultiByteWrite
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_DirectAccessSPIMultiByteWrite
+(
+uint8_t startAddress,
+uint8_t * byteArray,
+uint8_t numOfBytes
+)
+{
+    uint8_t txData;
+
+    if( (numOfBytes == 0) || (byteArray == 0) )
+    {
+        return;
+    }
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 16000000);
+
+    gXcvrAssertCS_d();
+
+    txData = (startAddress & TransceiverSPI_DirectRegisterAddressMask);
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, 0, sizeof(txData));
+    xcvr_spi_transfer(gXcvrSpiInstance_c, byteArray, 0, numOfBytes);
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_PB_SPIByteWrite
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_PB_SPIByteWrite
+(
+uint8_t address,
+uint8_t value
+)
+{
+    uint32_t txData;
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 16000000);
+
+    gXcvrAssertCS_d();
+
+    txData  = TransceiverSPI_WriteSelect            |
+        TransceiverSPI_PacketBuffAccessSelect |
+            TransceiverSPI_PacketBuffByteModeSelect;
+    txData |= (address) << 8;
+    txData |= (value)   << 16;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, 3);
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_PB_SPIBurstWrite
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_PB_SPIBurstWrite
+(
+uint8_t * byteArray,
+uint8_t numOfBytes
+)
+{
+    uint8_t txData;
+
+    if( (numOfBytes == 0) || (byteArray == 0) )
+    {
+        return;
+    }
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 16000000);
+
+    gXcvrAssertCS_d();
+
+    txData = TransceiverSPI_WriteSelect            |
+        TransceiverSPI_PacketBuffAccessSelect |
+            TransceiverSPI_PacketBuffBurstModeSelect;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, 0, 1);
+    xcvr_spi_transfer(gXcvrSpiInstance_c, byteArray, 0, numOfBytes);
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_DirectAccessSPIRead
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+
+uint8_t MCR20Drv_DirectAccessSPIRead
+(
+uint8_t address
+)
+{
+    uint8_t txData;
+    uint8_t rxData;
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000);
+
+    gXcvrAssertCS_d();
+
+    txData = (address & TransceiverSPI_DirectRegisterAddressMask) |
+        TransceiverSPI_ReadSelect;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, 0, sizeof(txData));
+    xcvr_spi_transfer(gXcvrSpiInstance_c, 0, &rxData, sizeof(rxData));
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+
+    return rxData;
+
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_DirectAccessSPIMultyByteRead
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+uint8_t MCR20Drv_DirectAccessSPIMultiByteRead
+(
+uint8_t startAddress,
+uint8_t * byteArray,
+uint8_t numOfBytes
+)
+{
+    uint8_t  txData;
+    uint8_t  phyIRQSTS1;
+
+    if( (numOfBytes == 0) || (byteArray == 0) )
+    {
+        return 0;
+    }
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000);
+
+    gXcvrAssertCS_d();
+
+    txData = (startAddress & TransceiverSPI_DirectRegisterAddressMask) |
+        TransceiverSPI_ReadSelect;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, &phyIRQSTS1, sizeof(txData));
+    xcvr_spi_transfer(gXcvrSpiInstance_c, 0, byteArray, numOfBytes);
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+
+    return phyIRQSTS1;
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_PB_SPIBurstRead
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+uint8_t MCR20Drv_PB_SPIBurstRead
+(
+uint8_t * byteArray,
+uint8_t numOfBytes
+)
+{
+    uint8_t  txData;
+    uint8_t  phyIRQSTS1;
+
+    if( (numOfBytes == 0) || (byteArray == 0) )
+    {
+        return 0;
+    }
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000);
+
+    gXcvrAssertCS_d();
+
+    txData = TransceiverSPI_ReadSelect |
+        TransceiverSPI_PacketBuffAccessSelect |
+            TransceiverSPI_PacketBuffBurstModeSelect;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, &txData, &phyIRQSTS1, sizeof(txData));
+    xcvr_spi_transfer(gXcvrSpiInstance_c, 0, byteArray, numOfBytes);
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+
+    return phyIRQSTS1;
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_IndirectAccessSPIWrite
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_IndirectAccessSPIWrite
+(
+uint8_t address,
+uint8_t value
+)
+{
+    uint32_t  txData;
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 16000000);
+
+    gXcvrAssertCS_d();
+
+    txData = TransceiverSPI_IARIndexReg;
+    txData |= (address) << 8;
+    txData |= (value)   << 16;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, 3);
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_IndirectAccessSPIMultiByteWrite
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_IndirectAccessSPIMultiByteWrite
+(
+uint8_t startAddress,
+uint8_t * byteArray,
+uint8_t numOfBytes
+)
+{
+    uint16_t  txData;
+
+    if( (numOfBytes == 0) || (byteArray == 0) )
+    {
+        return;
+    }
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 16000000);
+
+    gXcvrAssertCS_d();
+
+    txData = TransceiverSPI_IARIndexReg;
+    txData |= (startAddress)  << 8;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, sizeof(txData));
+    xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)byteArray, 0, numOfBytes);
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_IndirectAccessSPIRead
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+uint8_t MCR20Drv_IndirectAccessSPIRead
+(
+uint8_t address
+)
+{
+    uint16_t  txData;
+    uint8_t   rxData;
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000);
+
+    gXcvrAssertCS_d();
+
+    txData = TransceiverSPI_IARIndexReg | TransceiverSPI_ReadSelect;
+    txData |= (address) << 8;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, sizeof(txData));
+    xcvr_spi_transfer(gXcvrSpiInstance_c, 0, &rxData, sizeof(rxData));
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+
+    return rxData;
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_IndirectAccessSPIMultiByteRead
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_IndirectAccessSPIMultiByteRead
+(
+uint8_t startAddress,
+uint8_t * byteArray,
+uint8_t numOfBytes
+)
+{
+    uint16_t  txData;
+
+    if( (numOfBytes == 0) || (byteArray == 0) )
+    {
+        return;
+    }
+
+    ProtectFromMCR20Interrupt();
+
+    xcvr_spi_configure_speed(gXcvrSpiInstance_c, 8000000);
+
+    gXcvrAssertCS_d();
+
+    txData = (TransceiverSPI_IARIndexReg | TransceiverSPI_ReadSelect);
+    txData |= (startAddress) << 8;
+
+    xcvr_spi_transfer(gXcvrSpiInstance_c, (uint8_t*)&txData, 0, sizeof(txData));
+    xcvr_spi_transfer(gXcvrSpiInstance_c, 0, byteArray, numOfBytes);
+
+    gXcvrDeassertCS_d();
+    UnprotectFromMCR20Interrupt();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_IsIrqPending
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+uint32_t  MCR20Drv_IsIrqPending
+(
+void
+)
+{
+    return RF_isIRQ_Pending();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_IRQ_Disable
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_IRQ_Disable
+(
+void
+)
+{
+    platform_enter_critical();
+
+    if( mPhyIrqDisableCnt == 0 )
+    {
+        RF_IRQ_Disable();
+    }
+
+    mPhyIrqDisableCnt++;
+
+    platform_exit_critical();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_IRQ_Enable
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_IRQ_Enable
+(
+void
+)
+{
+    platform_enter_critical();
+
+    if( mPhyIrqDisableCnt )
+    {
+        mPhyIrqDisableCnt--;
+
+        if( mPhyIrqDisableCnt == 0 )
+        {
+            RF_IRQ_Enable();
+        }
+    }
+
+    platform_exit_critical();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_RST_Assert
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_RST_B_Assert
+(
+void
+)
+{
+    RF_RST_Set(0);
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_RST_Deassert
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_RST_B_Deassert
+(
+void
+)
+{
+    RF_RST_Set(1);
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_SoftRST_Assert
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_SoftRST_Assert
+(
+void
+)
+{
+    MCR20Drv_IndirectAccessSPIWrite(SOFT_RESET, (0x80));
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_SoftRST_Deassert
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_SoftRST_Deassert
+(
+void
+)
+{
+    MCR20Drv_IndirectAccessSPIWrite(SOFT_RESET, (0x00));
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_Soft_RESET
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_Soft_RESET
+(
+void
+)
+{
+    //assert SOG_RST
+    MCR20Drv_IndirectAccessSPIWrite(SOFT_RESET, (0x80));
+
+    //deassert SOG_RST
+    MCR20Drv_IndirectAccessSPIWrite(SOFT_RESET, (0x00));
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_RESET
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_RESET
+(
+void
+)
+{
+    volatile uint32_t delay = 1000;
+    //assert RST_B
+    MCR20Drv_RST_B_Assert();
+
+    while(delay--);
+
+    //deassert RST_B
+    MCR20Drv_RST_B_Deassert();
+}
+
+/*---------------------------------------------------------------------------
+* Name: MCR20Drv_Set_CLK_OUT_Freq
+* Description: -
+* Parameters: -
+* Return: -
+*---------------------------------------------------------------------------*/
+void MCR20Drv_Set_CLK_OUT_Freq
+(
+uint8_t freqDiv
+)
+{
+    uint8_t clkOutCtrlReg = (freqDiv & cCLK_OUT_DIV_Mask) | cCLK_OUT_EN | cCLK_OUT_EXTEND;
+
+    if(freqDiv == gCLK_OUT_FREQ_DISABLE)
+    {
+        clkOutCtrlReg = (cCLK_OUT_EXTEND | gCLK_OUT_FREQ_4_MHz); //reset value with clock out disabled
+    }
+
+    MCR20Drv_DirectAccessSPIWrite((uint8_t) CLK_OUT_CTRL, clkOutCtrlReg);
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/source/MCR20Drv.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/source/MCR20Drv.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,372 @@
+/*!
+* Copyright (c) 2015, Freescale Semiconductor, Inc.
+* All rights reserved.
+*
+* \file MCR20Drv.h
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* o Redistributions of source code must retain the above copyright notice, this list
+*   of conditions and the following disclaimer.
+*
+* o Redistributions in binary form must reproduce the above copyright notice, this
+*   list of conditions and the following disclaimer in the documentation and/or
+*   other materials provided with the distribution.
+*
+* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+*   contributors may be used to endorse or promote products derived from this
+*   software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __MCR20_DRV_H__
+#define __MCR20_DRV_H__
+
+
+/*****************************************************************************
+ *                               INCLUDED HEADERS                            *
+ *---------------------------------------------------------------------------*
+ * Add to this section all the headers that this module needs to include.    *
+ * Note that it is not a good practice to include header files into header   *
+ * files, so use this section only if there is no other better solution.     *
+ *---------------------------------------------------------------------------*
+ *****************************************************************************/
+
+/*****************************************************************************
+ *                             PRIVATE MACROS                                *
+ *---------------------------------------------------------------------------*
+ * Add to this section all the access macros, registers mappings, bit access *
+ * macros, masks, flags etc ...
+ *---------------------------------------------------------------------------*
+ *****************************************************************************/
+
+/* Disable XCVR clock output by default, to reduce power consumption */
+#ifndef gMCR20_ClkOutFreq_d 
+#define gMCR20_ClkOutFreq_d gCLK_OUT_FREQ_DISABLE
+#endif
+
+/*****************************************************************************
+ *                            PUBLIC FUNCTIONS                               *
+ *---------------------------------------------------------------------------*
+ * Add to this section all the global functions prototype preceded (as a     *
+ * good practice) by the keyword 'extern'                                    *
+ *---------------------------------------------------------------------------*
+ *****************************************************************************/
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_Init
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+extern void MCR20Drv_Init
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_SPI_DMA_Init
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_SPI_DMA_Init
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_Start_PB_DMA_SPI_Write
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_Start_PB_DMA_SPI_Write
+(
+  uint8_t * srcAddress,
+  uint8_t numOfBytes
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_Start_PB_DMA_SPI_Read
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_Start_PB_DMA_SPI_Read
+(
+  uint8_t * dstAddress,
+  uint8_t numOfBytes
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_DirectAccessSPIWrite
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_DirectAccessSPIWrite
+(
+ uint8_t address,
+ uint8_t value
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_DirectAccessSPIMultiByteWrite
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_DirectAccessSPIMultiByteWrite
+(
+ uint8_t startAddress,
+ uint8_t * byteArray,
+ uint8_t numOfBytes
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_PB_SPIBurstWrite
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_PB_SPIBurstWrite
+(
+ uint8_t * byteArray,
+ uint8_t numOfBytes
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_DirectAccessSPIRead
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+uint8_t MCR20Drv_DirectAccessSPIRead
+(
+ uint8_t address
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_DirectAccessSPIMultyByteRead
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+
+uint8_t MCR20Drv_DirectAccessSPIMultiByteRead
+(
+ uint8_t startAddress,
+ uint8_t * byteArray,
+ uint8_t numOfBytes
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_PB_SPIByteWrite
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_PB_SPIByteWrite
+(
+ uint8_t address,
+ uint8_t value
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_PB_SPIBurstRead
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+uint8_t MCR20Drv_PB_SPIBurstRead
+(
+ uint8_t * byteArray,
+ uint8_t numOfBytes
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_IndirectAccessSPIWrite
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_IndirectAccessSPIWrite
+(
+ uint8_t address,
+ uint8_t value
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_IndirectAccessSPIMultiByteWrite
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_IndirectAccessSPIMultiByteWrite
+(
+ uint8_t startAddress,
+ uint8_t * byteArray,
+ uint8_t numOfBytes
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_IndirectAccessSPIRead
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+uint8_t MCR20Drv_IndirectAccessSPIRead
+(
+ uint8_t address
+);
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_IndirectAccessSPIMultiByteRead
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_IndirectAccessSPIMultiByteRead
+(
+ uint8_t startAddress,
+ uint8_t * byteArray,
+ uint8_t numOfBytes
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_IsIrqPending
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+uint32_t MCR20Drv_IsIrqPending
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_IRQ_Disable
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_IRQ_Disable
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_IRQ_Enable
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_IRQ_Enable
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_RST_PortConfig
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_RST_B_PortConfig
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_RST_Assert
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_RST_B_Assert
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_RST_Deassert
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_RST_B_Deassert
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_SoftRST_Assert
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_SoftRST_Assert
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_SoftRST_Deassert
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_SoftRST_Deassert
+(
+  void
+);
+
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_RESET
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_RESET
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_Soft_RESET
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_Soft_RESET
+(
+  void
+);
+
+/*---------------------------------------------------------------------------
+ * Name: MCR20Drv_Set_CLK_OUT_Freq
+ * Description: -
+ * Parameters: -
+ * Return: -
+ *---------------------------------------------------------------------------*/
+void MCR20Drv_Set_CLK_OUT_Freq
+(
+  uint8_t freqDiv
+);
+
+#define ProtectFromMCR20Interrupt()   MCR20Drv_IRQ_Disable()
+#define UnprotectFromMCR20Interrupt() MCR20Drv_IRQ_Enable()
+
+#endif /* __MCR20_DRV_H__ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/source/MCR20Overwrites.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/source/MCR20Overwrites.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,309 @@
+/*!
+* Copyright (c) 2015, Freescale Semiconductor, Inc.
+* All rights reserved.
+*
+* \file MCR20Overwrites.h
+* Description: Overwrites header file for MCR20 Register values
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* o Redistributions of source code must retain the above copyright notice, this list
+*   of conditions and the following disclaimer.
+*
+* o Redistributions in binary form must reproduce the above copyright notice, this
+*   list of conditions and the following disclaimer in the documentation and/or
+*   other materials provided with the distribution.
+*
+* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+*   contributors may be used to endorse or promote products derived from this
+*   software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef OVERWRITES_H_
+#define OVERWRITES_H_
+
+typedef struct overwrites_tag {
+ char address;
+ char data;
+}overwrites_t;
+
+
+/*****************************************************************************************************************/
+//         This file is created exclusively for use with the transceiver 2.0 silicon
+//         and is provided for the world to use. It contains a list of all
+//         known overwrite values. Overwrite values are non-default register
+//         values that configure the transceiver device to a more optimally performing
+//         posture. It is expected that low level software (i.e. PHY) will
+//         consume this file as a #include, and transfer the contents to the
+//         the indicated addresses in the transceiver's memory space. This file has
+//         at least one required entry, that being its own version current version
+//         number, to be stored at transceiver's location 0x3B the
+//         OVERWRITES_VERSION_NUMBER register. The RAM register is provided in
+//         the transceiver address space to assist in future debug efforts. The
+//         analyst may read this location (once device has been booted with
+//         mysterious software) and have a good indication of what register
+//         overwrites were performed (with all versions of the overwrites.h file
+//         being archived forever at the Compass location shown above.
+//
+//     The transceiver has an indirect register (IAR) space. Write access to this space
+//         requires 3 or more writes:
+//         1st) the first write is an index value to the indirect (write Bit7=0, register access Bit 6=0) + 0x3E
+//         2nd) IAR Register #0x00 - 0xFF.
+//     3rd) The data to write
+//         nth) Burst mode additional data if required.
+//
+//     Write access to direct space requires only a single address, data pair.
+
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x0C}, //version 0C: new value for ACKDELAY targeting 198us (23 May, 2013, Larry Roshak)
+{0x23, 0x17}  //PA_PWR new default Power Step is "23"  
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3                         
+{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}, //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}, //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}, //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}, //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}, //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}, //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}, //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}, //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}, //PA_CAL_DIS=1  Disabled PA calibration 
+{0x52, 0x55}, //AGC_THR1 RSSI tune up 
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up 
+{0x66, 0x5F}, //ATT_RSSI1 tune up     
+{0x67, 0x8F}, //ATT_RSSI2 tune up     
+{0x68, 0x61}, //RSSI_OFFSET 
+{0x78, 0x03}, //CHF_PMAGAIN 
+{0x22, 0x50}, //CCA1_THRESH 
+{0x4D, 0x13}, //CORR_NVAL moved from 0x14 to 0x13 for 0.5 dB improved Rx Sensitivity 
+{0x39, 0x3D}  //ACKDELAY new value targeting a delay of 198us (23 May, 2013, Larry Roshak)
+};
+
+
+/* begin of deprecated versions
+
+==VERSION 1==
+(version 1 is empty)
+
+==VERSION 2==
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}  //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+};
+
+==VERSION 3==
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1: override VCOALC_REF_TX to 3 
+{0x92, 0x07}  //VCO_CTRL2: override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+};
+
+==VERSION 4==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x04}  //version 04 is the current version: update PA_COILTUNING default 
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1: override VCOALC_REF_TX to 3 
+{0x92, 0x07}  //VCO_CTRL2: override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+{0x8A, 0x71}  //PA_TUNING: override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+};
+
+==VERSION 5==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x05}  //version 05: updates Channel Filter Register set (21 Dec 2012, on behalf of S. Soca)
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3                         
+{0x92, 0x07}  //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+{0x8A, 0x71}  //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}  //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}  //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}  //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}  //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}  //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}  //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}  //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}  //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}  //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}  //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}  //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+};
+
+==VERSION 6==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x06}  //version 06: disable PA calibration 
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3                         
+{0x92, 0x07}  //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+{0x8A, 0x71}  //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}  //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}  //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}  //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}  //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}  //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}  //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}  //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}  //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}  //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}  //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}  //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}  //PA_CAL_DIS=1  Disabled PA calibration 
+};
+
+==VERSION 7==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x07}  //version 07: updated registers for ED/RSSI 
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3                         
+{0x92, 0x07},  //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+{0x8A, 0x71},  //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F},  //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F},  //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24},  //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24},  //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24},  //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24},  //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24},  //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24},  //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D},  //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D},  //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28},  //PA_CAL_DIS=1  Disabled PA calibration 
+{0x52, 0x73},  //AGC_THR1 RSSI tune up 
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up 
+{0x66, 0x5F}, //ATT_RSSI1 tune up 
+{0x67, 0x8F}, //ATT_RSSI2 tune up 
+{0x68, 0x60}, //RSSI_OFFSET 
+{0x69, 0x65}  //RSSI_SLOPE 
+};
+
+
+==VERSION 8==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x08}  //version 08: updated registers for ED/RSSI 
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3                         
+{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}, //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}, //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}, //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}, //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}, //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}, //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}, //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}, //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}, //PA_CAL_DIS=1  Disabled PA calibration 
+{0x52, 0x73}, //AGC_THR1 RSSI tune up 
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up 
+{0x66, 0x5F}, //ATT_RSSI1 tune up     
+{0x67, 0x8F}, //ATT_RSSI2 tune up     
+{0x69, 0x65}  //RSSI_SLOPE            
+{0x68, 0x61}, //RSSI_OFFSET 
+{0x78, 0x03}  //CHF_PMAGAIN 
+};
+
+
+==VERSION 9==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x09}  //version 09: updated registers for ED/RSSI and PowerStep 
+{0x23, 0x17}  //PA_PWR new default value                                
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3                         
+{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}, //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}, //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}, //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}, //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}, //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}, //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}, //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}, //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}, //PA_CAL_DIS=1  Disabled PA calibration 
+{0x52, 0x55}, //AGC_THR1 RSSI tune up 
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up 
+{0x66, 0x5F}, //ATT_RSSI1 tune up     
+{0x67, 0x8F}, //ATT_RSSI2 tune up     
+{0x68, 0x61}, //RSSI_OFFSET 
+{0x78, 0x03}  //CHF_PMAGAIN 
+};
+
+==VERSION A==
+overwrites_t const overwrites_direct[] ={
+{0x3B, 0x0A}  //version 0A: updated registers for CCA 
+{0x23, 0x17}  //PA_PWR new default Power Step is "23"  
+};
+
+overwrites_t const overwrites_indirect[] ={
+{0x31, 0x02}, //clear MISO_HIZ_EN (for single SPI master/slave pair) and SPI_PUL_EN (minimize HIB currents) 
+{0x91, 0xB3}, //VCO_CTRL1 override VCOALC_REF_TX to 3                         
+{0x92, 0x07}, //VCO_CTRL2 override VCOALC_REF_RX to 3, keep VCO_BUF_BOOST = 1 
+{0x8A, 0x71}, //PA_TUNING override PA_COILTUNING to 001 (27 Nov 2012, D. Brown, on behalf of S. Eid)
+{0x79, 0x2F}, //CHF_IBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7A, 0x2F}, //CHF_QBUF  Adjust the gm-C filter gain (+/- 6dB)         (21 Dec, 2012, on behalf of S. Soca)
+{0x7B, 0x24}, //CHF_IRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7C, 0x24}, //CHF_QRIN  Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7D, 0x24}, //CHF_IL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7E, 0x24}, //CHF_QL    Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x7F, 0x32}, //CHF_CC1   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x80, 0x1D}, //CHF_CCL   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x81, 0x2D}, //CHF_CC2   Adjust the filter center frequency (+/- 1MHz) (21 Dec, 2012, on behalf of S. Soca)
+{0x82, 0x24}, //CHF_IROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x83, 0x24}, //CHF_QROUT Adjust the filter bandwidth (+/- 0.5MHz)      (21 Dec, 2012, on behalf of S. Soca)
+{0x64, 0x28}, //PA_CAL_DIS=1  Disabled PA calibration 
+{0x52, 0x55}, //AGC_THR1 RSSI tune up 
+{0x53, 0x2D}, //AGC_THR2 RSSI tune up 
+{0x66, 0x5F}, //ATT_RSSI1 tune up     
+{0x67, 0x8F}, //ATT_RSSI2 tune up     
+{0x68, 0x61}, //RSSI_OFFSET 
+{0x78, 0x03}  //CHF_PMAGAIN 
+{0x22, 0x50}  //CCA1_THRESH 
+};
+
+end of deprecated versions */
+
+
+#endif  //OVERWRITES_H_
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/source/MCR20Reg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/source/MCR20Reg.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,730 @@
+/*!
+* Copyright (c) 2015, Freescale Semiconductor, Inc.
+* All rights reserved.
+*
+* \file MCR20reg.h
+* MCR20 Registers
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* o Redistributions of source code must retain the above copyright notice, this list
+*   of conditions and the following disclaimer.
+*
+* o Redistributions in binary form must reproduce the above copyright notice, this
+*   list of conditions and the following disclaimer in the documentation and/or
+*   other materials provided with the distribution.
+*
+* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+*   contributors may be used to endorse or promote products derived from this
+*   software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __MCR20_REG_H__
+#define __MCR20_REG_H__
+/*****************************************************************************
+ *                               INCLUDED HEADERS                            *
+ *---------------------------------------------------------------------------*
+ * Add to this section all the headers that this module needs to include.    *
+ * Note that it is not a good practice to include header files into header   *
+ * files, so use this section only if there is no other better solution.     *
+ *---------------------------------------------------------------------------*
+ *****************************************************************************/
+
+/****************************************************************************/
+/* Transceiver SPI Registers */
+/****************************************************************************/
+
+#define TransceiverSPI_IARIndexReg                  (0x3E)
+
+#define TransceiverSPI_ReadSelect                   (1<<7)
+#define TransceiverSPI_WriteSelect                  (0<<7)
+#define TransceiverSPI_RegisterAccessSelect         (0<<6)
+#define TransceiverSPI_PacketBuffAccessSelect       (1<<6)
+#define TransceiverSPI_PacketBuffBurstModeSelect    (0<<5)
+#define TransceiverSPI_PacketBuffByteModeSelect     (1<<5)
+
+#define TransceiverSPI_DirectRegisterAddressMask    (0x3F)
+
+#define IRQSTS1             0x00
+#define IRQSTS2             0x01
+#define IRQSTS3             0x02
+#define PHY_CTRL1           0x03
+#define PHY_CTRL2           0x04
+#define PHY_CTRL3           0x05
+#define RX_FRM_LEN          0x06
+#define PHY_CTRL4           0x07
+#define SRC_CTRL            0x08
+#define SRC_ADDRS_SUM_LSB   0x09
+#define SRC_ADDRS_SUM_MSB   0x0A
+#define CCA1_ED_FNL         0x0B
+#define EVENT_TMR_LSB       0x0C
+#define EVENT_TMR_MSB       0x0D
+#define EVENT_TMR_USB       0x0E
+#define TIMESTAMP_LSB       0x0F
+#define TIMESTAMP_MSB       0x10
+#define TIMESTAMP_USB       0x11
+#define T3CMP_LSB           0x12
+#define T3CMP_MSB           0x13
+#define T3CMP_USB           0x14
+#define T2PRIMECMP_LSB      0x15
+#define T2PRIMECMP_MSB      0x16
+#define T1CMP_LSB           0x17
+#define T1CMP_MSB           0x18
+#define T1CMP_USB           0x19
+#define T2CMP_LSB           0x1A
+#define T2CMP_MSB           0x1B
+#define T2CMP_USB           0x1C
+#define T4CMP_LSB           0x1D
+#define T4CMP_MSB           0x1E
+#define T4CMP_USB           0x1F
+#define PLL_INT0            0x20
+#define PLL_FRAC0_LSB       0x21
+#define PLL_FRAC0_MSB       0x22
+#define PA_PWR              0x23
+#define SEQ_STATE           0x24
+#define LQI_VALUE           0x25
+#define RSSI_CCA_CONT       0x26
+//--------------            0x27
+#define ASM_CTRL1           0x28
+#define ASM_CTRL2           0x29
+#define ASM_DATA_0          0x2A
+#define ASM_DATA_1          0x2B
+#define ASM_DATA_2          0x2C
+#define ASM_DATA_3          0x2D
+#define ASM_DATA_4          0x2E
+#define ASM_DATA_5          0x2F
+#define ASM_DATA_6          0x30
+#define ASM_DATA_7          0x31
+#define ASM_DATA_8          0x32
+#define ASM_DATA_9          0x33
+#define ASM_DATA_A          0x34
+#define ASM_DATA_B          0x35
+#define ASM_DATA_C          0x36
+#define ASM_DATA_D          0x37
+#define ASM_DATA_E          0x38
+#define ASM_DATA_F          0x39
+//-------------------       0x3A
+#define OVERWRITE_VER       0x3B
+#define CLK_OUT_CTRL        0x3C
+#define PWR_MODES           0x3D
+#define IAR_INDEX           0x3E
+#define IAR_DATA            0x3F
+
+
+#define PART_ID             0x00
+#define XTAL_TRIM           0x01
+#define PMC_LP_TRIM         0x02
+#define MACPANID0_LSB       0x03
+#define MACPANID0_MSB       0x04
+#define MACSHORTADDRS0_LSB  0x05
+#define MACSHORTADDRS0_MSB  0x06
+#define MACLONGADDRS0_0     0x07
+#define MACLONGADDRS0_8     0x08
+#define MACLONGADDRS0_16    0x09
+#define MACLONGADDRS0_24    0x0A
+#define MACLONGADDRS0_32    0x0B
+#define MACLONGADDRS0_40    0x0C
+#define MACLONGADDRS0_48    0x0D
+#define MACLONGADDRS0_56    0x0E
+#define RX_FRAME_FILTER     0x0F
+#define PLL_INT1            0x10
+#define PLL_FRAC1_LSB       0x11
+#define PLL_FRAC1_MSB       0x12
+#define MACPANID1_LSB       0x13
+#define MACPANID1_MSB       0x14
+#define MACSHORTADDRS1_LSB  0x15
+#define MACSHORTADDRS1_MSB  0x16
+#define MACLONGADDRS1_0     0x17
+#define MACLONGADDRS1_8     0x18
+#define MACLONGADDRS1_16    0x19
+#define MACLONGADDRS1_24    0x1A
+#define MACLONGADDRS1_32    0x1B
+#define MACLONGADDRS1_40    0x1C
+#define MACLONGADDRS1_48    0x1D
+#define MACLONGADDRS1_56    0x1E
+#define DUAL_PAN_CTRL       0x1F
+#define DUAL_PAN_DWELL      0x20
+#define DUAL_PAN_STS        0x21
+#define CCA1_THRESH         0x22
+#define CCA1_ED_OFFSET_COMP 0x23
+#define LQI_OFFSET_COMP     0x24
+#define CCA_CTRL            0x25
+#define CCA2_CORR_PEAKS     0x26
+#define CCA2_CORR_THRESH    0x27
+#define TMR_PRESCALE        0x28
+//----------------          0x29
+#define GPIO_DATA           0x2A
+#define GPIO_DIR            0x2B
+#define GPIO_PUL_EN         0x2C
+#define GPIO_PUL_SEL        0x2D
+#define GPIO_DS             0x2E
+//--------------            0x2F
+#define ANT_PAD_CTRL        0x30
+#define MISC_PAD_CTRL       0x31
+#define BSM_CTRL            0x32
+//---------------           0x33
+#define _RNG                0x34
+#define RX_BYTE_COUNT       0x35
+#define RX_WTR_MARK         0x36
+#define SOFT_RESET          0x37
+#define TXDELAY             0x38
+#define ACKDELAY            0x39
+#define SEQ_MGR_CTRL        0x3A
+#define SEQ_MGR_STS         0x3B
+#define SEQ_T_STS           0x3C
+#define ABORT_STS           0x3D
+#define CCCA_BUSY_CNT       0x3E
+#define SRC_ADDR_CHECKSUM1  0x3F
+#define SRC_ADDR_CHECKSUM2  0x40
+#define SRC_TBL_VALID1      0x41
+#define SRC_TBL_VALID2      0x42
+#define FILTERFAIL_CODE1    0x43
+#define FILTERFAIL_CODE2    0x44
+#define SLOT_PRELOAD        0x45
+//----------------          0x46
+#define CORR_VT             0x47
+#define SYNC_CTRL           0x48
+#define PN_LSB_0            0x49
+#define PN_LSB_1            0x4A
+#define PN_MSB_0            0x4B
+#define PN_MSB_1            0x4C
+#define CORR_NVAL           0x4D
+#define TX_MODE_CTRL        0x4E
+#define SNF_THR             0x4F
+#define FAD_THR             0x50
+#define ANT_AGC_CTRL        0x51
+#define AGC_THR1            0x52
+#define AGC_THR2            0x53
+#define AGC_HYS             0x54
+#define AFC                 0x55
+//---------------           0x56
+//---------------           0x57
+#define PHY_STS             0x58
+#define RX_MAX_CORR         0x59
+#define RX_MAX_PREAMBLE     0x5A
+#define RSSI                0x5B
+//---------------           0x5C
+//---------------           0x5D
+#define PLL_DIG_CTRL        0x5E
+#define VCO_CAL             0x5F
+#define VCO_BEST_DIFF       0x60
+#define VCO_BIAS            0x61
+#define KMOD_CTRL           0x62
+#define KMOD_CAL            0x63
+#define PA_CAL              0x64
+#define PA_PWRCAL           0x65
+#define ATT_RSSI1           0x66
+#define ATT_RSSI2           0x67
+#define RSSI_OFFSET         0x68
+#define RSSI_SLOPE          0x69
+#define RSSI_CAL1           0x6A
+#define RSSI_CAL2           0x6B
+//---------------           0x6C
+//---------------           0x6D
+#define XTAL_CTRL           0x6E
+#define XTAL_COMP_MIN       0x6F
+#define XTAL_COMP_MAX       0x70
+#define XTAL_GM             0x71
+//---------------           0x72
+//---------------           0x73
+#define LNA_TUNE            0x74
+#define LNA_AGCGAIN         0x75
+//---------------           0x76
+//---------------           0x77
+#define CHF_PMA_GAIN        0x78
+#define CHF_IBUF            0x79
+#define CHF_QBUF            0x7A
+#define CHF_IRIN            0x7B
+#define CHF_QRIN            0x7C
+#define CHF_IL              0x7D
+#define CHF_QL              0x7E
+#define CHF_CC1             0x7F
+#define CHF_CCL             0x80
+#define CHF_CC2             0x81
+#define CHF_IROUT           0x82
+#define CHF_QROUT           0x83
+//---------------           0x84
+//---------------           0x85
+#define RSSI_CTRL           0x86
+//---------------           0x87
+//---------------           0x88
+#define PA_BIAS             0x89
+#define PA_TUNING           0x8A
+//---------------           0x8B
+//---------------           0x8C
+#define PMC_HP_TRIM         0x8D
+#define VREGA_TRIM          0x8E
+//---------------           0x8F
+//---------------           0x90
+#define VCO_CTRL1           0x91
+#define VCO_CTRL2           0x92
+//---------------           0x93
+//---------------           0x94
+#define ANA_SPARE_OUT1      0x95
+#define ANA_SPARE_OUT2      0x96
+#define ANA_SPARE_IN        0x97
+#define MISCELLANEOUS       0x98
+//---------------           0x99
+#define SEQ_MGR_OVRD0       0x9A
+#define SEQ_MGR_OVRD1       0x9B
+#define SEQ_MGR_OVRD2       0x9C
+#define SEQ_MGR_OVRD3       0x9D
+#define SEQ_MGR_OVRD4       0x9E
+#define SEQ_MGR_OVRD5       0x9F
+#define SEQ_MGR_OVRD6       0xA0
+#define SEQ_MGR_OVRD7       0xA1
+//---------------           0xA2
+#define TESTMODE_CTRL       0xA3
+#define DTM_CTRL1           0xA4
+#define DTM_CTRL2           0xA5
+#define ATM_CTRL1           0xA6
+#define ATM_CTRL2           0xA7
+#define ATM_CTRL3           0xA8
+//---------------           0xA9
+#define LIM_FE_TEST_CTRL    0xAA
+#define CHF_TEST_CTRL       0xAB
+#define VCO_TEST_CTRL       0xAC
+#define PLL_TEST_CTRL       0xAD
+#define PA_TEST_CTRL        0xAE
+#define PMC_TEST_CTRL       0xAF
+#define SCAN_DTM_PROTECT_1  0xFE
+#define SCAN_DTM_PROTECT_0  0xFF
+
+// IRQSTS1 bits
+#define cIRQSTS1_RX_FRM_PEND         (1<<7)
+#define cIRQSTS1_PLL_UNLOCK_IRQ      (1<<6)
+#define cIRQSTS1_FILTERFAIL_IRQ      (1<<5)
+#define cIRQSTS1_RXWTRMRKIRQ         (1<<4)
+#define cIRQSTS1_CCAIRQ              (1<<3)
+#define cIRQSTS1_RXIRQ               (1<<2)
+#define cIRQSTS1_TXIRQ               (1<<1)
+#define cIRQSTS1_SEQIRQ              (1<<0)
+
+typedef union regIRQSTS1_tag{
+  uint8_t byte;
+  struct{
+    uint8_t SEQIRQ:1;
+    uint8_t TXIRQ:1;
+    uint8_t RXIRQ:1;
+    uint8_t CCAIRQ:1;
+    uint8_t RXWTRMRKIRQ:1;
+    uint8_t FILTERFAIL_IRQ:1;
+    uint8_t PLL_UNLOCK_IRQ:1;
+    uint8_t RX_FRM_PEND:1;
+  }bit;
+} regIRQSTS1_t;
+
+// IRQSTS2 bits
+#define cIRQSTS2_CRCVALID            (1<<7)
+#define cIRQSTS2_CCA                 (1<<6)
+#define cIRQSTS2_SRCADDR             (1<<5)
+#define cIRQSTS2_PI                  (1<<4)
+#define cIRQSTS2_TMRSTATUS           (1<<3)
+#define cIRQSTS2_ASM_IRQ             (1<<2)
+#define cIRQSTS2_PB_ERR_IRQ          (1<<1)
+#define cIRQSTS2_WAKE_IRQ            (1<<0)
+
+typedef union regIRQSTS2_tag{
+  uint8_t byte;
+  struct{
+    uint8_t WAKE_IRQ:1;
+    uint8_t PB_ERR_IRQ:1;
+    uint8_t ASM_IRQ:1;
+    uint8_t TMRSTATUS:1;
+    uint8_t PI:1;
+    uint8_t SRCADDR:1;
+    uint8_t CCA:1;
+    uint8_t CRCVALID:1;
+  }bit;
+} regIRQSTS2_t;
+
+// IRQSTS3 bits
+#define cIRQSTS3_TMR4MSK             (1<<7)
+#define cIRQSTS3_TMR3MSK             (1<<6)
+#define cIRQSTS3_TMR2MSK             (1<<5)
+#define cIRQSTS3_TMR1MSK             (1<<4)
+#define cIRQSTS3_TMR4IRQ             (1<<3)
+#define cIRQSTS3_TMR3IRQ             (1<<2)
+#define cIRQSTS3_TMR2IRQ             (1<<1)
+#define cIRQSTS3_TMR1IRQ             (1<<0)
+
+typedef union regIRQSTS3_tag{
+  uint8_t byte;
+  struct{
+    uint8_t TMR1IRQ:1;
+    uint8_t TMR2IRQ:1;
+    uint8_t TMR3IRQ:1;
+    uint8_t TMR4IRQ:1;
+    uint8_t TMR1MSK:1;
+    uint8_t TMR2MSK:1;
+    uint8_t TMR3MSK:1;
+    uint8_t TMR4MSK:1;
+  }bit;
+} regIRQSTS3_t;
+
+// PHY_CTRL1 bits
+#define cPHY_CTRL1_TMRTRIGEN           (1<<7)
+#define cPHY_CTRL1_SLOTTED             (1<<6)
+#define cPHY_CTRL1_CCABFRTX            (1<<5)
+#define cPHY_CTRL1_RXACKRQD            (1<<4)
+#define cPHY_CTRL1_AUTOACK             (1<<3)
+#define cPHY_CTRL1_XCVSEQ              (7<<0)
+
+typedef union regPHY_CTRL1_tag{
+  uint8_t byte;
+  struct{
+    uint8_t XCVSEQ:3;
+    uint8_t AUTOACK:1;
+    uint8_t RXACKRQD:1;
+    uint8_t CCABFRTX:1;
+    uint8_t SLOTTED:1;
+    uint8_t TMRTRIGEN:1;
+  }bit;
+} regPHY_CTRL1_t; 
+
+// PHY_CTRL2 bits
+#define cPHY_CTRL2_CRC_MSK             (1<<7)
+#define cPHY_CTRL2_PLL_UNLOCK_MSK      (1<<6)
+#define cPHY_CTRL2_FILTERFAIL_MSK      (1<<5)
+#define cPHY_CTRL2_RX_WMRK_MSK         (1<<4)
+#define cPHY_CTRL2_CCAMSK              (1<<3)
+#define cPHY_CTRL2_RXMSK               (1<<2)
+#define cPHY_CTRL2_TXMSK               (1<<1)
+#define cPHY_CTRL2_SEQMSK              (1<<0)
+
+typedef union regPHY_CTRL2_tag{
+  uint8_t byte;
+  struct{
+    uint8_t SEQMSK:1;
+    uint8_t TXMSK:1;
+    uint8_t RXMSK:1;
+    uint8_t CCAMSK:1;
+    uint8_t RX_WMRK_MSK:1;
+    uint8_t FILTERFAIL_MSK:1;
+    uint8_t PLL_UNLOCK_MSK:1;
+    uint8_t CRC_MSK:1;
+  }bit;
+} regPHY_CTRL2_t; 
+
+// PHY_CTRL3 bits
+#define cPHY_CTRL3_TMR4CMP_EN          (1<<7)
+#define cPHY_CTRL3_TMR3CMP_EN          (1<<6)
+#define cPHY_CTRL3_TMR2CMP_EN          (1<<5)
+#define cPHY_CTRL3_TMR1CMP_EN          (1<<4)
+#define cPHY_CTRL3_ASM_MSK             (1<<2)
+#define cPHY_CTRL3_PB_ERR_MSK          (1<<1)
+#define cPHY_CTRL3_WAKE_MSK            (1<<0)
+
+typedef union regPHY_CTRL3_tag{
+  uint8_t byte;
+  struct{
+    uint8_t WAKE_MSK:1;
+    uint8_t PB_ERR_MSK:1;
+    uint8_t ASM_MSK:1;
+    uint8_t RESERVED:1;
+    uint8_t TMR1CMP_EN:1;
+    uint8_t TMR2CMP_EN:1;
+    uint8_t TMR3CMP_EN:1;
+    uint8_t TMR4CMP_EN:1;
+  }bit;
+} regPHY_CTRL3_t;
+
+// RX_FRM_LEN bits
+#define cRX_FRAME_LENGTH               (0x7F)
+
+// PHY_CTRL4 bits
+#define cPHY_CTRL4_TRCV_MSK            (1<<7)
+#define cPHY_CTRL4_TC3TMOUT            (1<<6)
+#define cPHY_CTRL4_PANCORDNTR0         (1<<5)
+#define cPHY_CTRL4_CCATYPE             (3<<0)
+#define cPHY_CTRL4_CCATYPE_Shift_c     (3)
+#define cPHY_CTRL4_TMRLOAD             (1<<2)
+#define cPHY_CTRL4_PROMISCUOUS         (1<<1)
+#define cPHY_CTRL4_TC2PRIME_EN         (1<<0)
+
+typedef union regPHY_CTRL4_tag{
+  uint8_t byte;
+  struct{
+    uint8_t TC2PRIME_EN:1;
+    uint8_t PROMISCUOUS:1;
+    uint8_t TMRLOAD:1;
+    uint8_t CCATYPE:2;
+    uint8_t PANCORDNTR0:1;
+    uint8_t TC3TMOUT:1;
+    uint8_t TRCV_MSK:1;
+  }bit;
+} regPHY_CTRL4_t;
+
+// SRC_CTRL bits
+#define cSRC_CTRL_INDEX               (0x0F)
+#define cSRC_CTRL_INDEX_Shift_c       (4)
+#define cSRC_CTRL_ACK_FRM_PND         (1<<3)
+#define cSRC_CTRL_SRCADDR_EN          (1<<2)
+#define cSRC_CTRL_INDEX_EN            (1<<1)
+#define cSRC_CTRL_INDEX_DISABLE       (1<<0)
+
+typedef union regSRC_CTRL_tag{
+  uint8_t byte;
+  struct{
+    uint8_t INDEX_DISABLE:1;
+    uint8_t INDEX_EN:1;
+    uint8_t SRCADDR_EN:1;
+    uint8_t ACK_FRM_PND:1;
+    uint8_t INDEX:4;
+  }bit;
+} regSRC_CTRL_t;
+
+// ASM_CTRL1 bits
+#define cASM_CTRL1_CLEAR               (1<<7)
+#define cASM_CTRL1_START               (1<<6)
+#define cASM_CTRL1_SELFTST             (1<<5)
+#define cASM_CTRL1_CTR                 (1<<4)
+#define cASM_CTRL1_CBC                 (1<<3)
+#define cASM_CTRL1_AES                 (1<<2)
+#define cASM_CTRL1_LOAD_MAC            (1<<1)
+
+// ASM_CTRL2 bits
+#define cASM_CTRL2_DATA_REG_TYPE_SEL          (7)
+#define cASM_CTRL2_DATA_REG_TYPE_SEL_Shift_c  (5)
+#define cASM_CTRL2_TSTPAS                     (1<<1)
+
+// CLK_OUT_CTRL bits
+#define cCLK_OUT_CTRL_EXTEND           (1<<7)
+#define cCLK_OUT_CTRL_HIZ              (1<<6)
+#define cCLK_OUT_CTRL_SR               (1<<5)
+#define cCLK_OUT_CTRL_DS               (1<<4)
+#define cCLK_OUT_CTRL_EN               (1<<3)
+#define cCLK_OUT_CTRL_DIV              (7)
+
+// PWR_MODES bits
+#define cPWR_MODES_XTAL_READY          (1<<5)
+#define cPWR_MODES_XTALEN              (1<<4)
+#define cPWR_MODES_ASM_CLK_EN          (1<<3)
+#define cPWR_MODES_AUTODOZE            (1<<1)
+#define cPWR_MODES_PMC_MODE            (1<<0)
+
+// RX_FRAME_FILTER bits
+#define cRX_FRAME_FLT_FRM_VER             (0xC0)
+#define cRX_FRAME_FLT_FRM_VER_Shift_c     (6)
+#define cRX_FRAME_FLT_ACTIVE_PROMISCUOUS  (1<<5)
+#define cRX_FRAME_FLT_NS_FT               (1<<4)
+#define cRX_FRAME_FLT_CMD_FT              (1<<3)
+#define cRX_FRAME_FLT_ACK_FT              (1<<2)
+#define cRX_FRAME_FLT_DATA_FT             (1<<1)
+#define cRX_FRAME_FLT_BEACON_FT           (1<<0)
+
+typedef union regRX_FRAME_FILTER_tag{
+  uint8_t byte;
+  struct{
+    uint8_t FRAME_FLT_BEACON_FT:1;
+    uint8_t FRAME_FLT_DATA_FT:1;
+    uint8_t FRAME_FLT_ACK_FT:1;
+    uint8_t FRAME_FLT_CMD_FT:1;
+    uint8_t FRAME_FLT_NS_FT:1;
+    uint8_t FRAME_FLT_ACTIVE_PROMISCUOUS:1;
+    uint8_t FRAME_FLT_FRM_VER:2;
+  }bit;
+} regRX_FRAME_FILTER_t; 
+
+// DUAL_PAN_CTRL bits
+#define cDUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_MSK       (0xF0)
+#define cDUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_Shift_c   (4)
+#define cDUAL_PAN_CTRL_CURRENT_NETWORK            (1<<3)
+#define cDUAL_PAN_CTRL_PANCORDNTR1                (1<<2)
+#define cDUAL_PAN_CTRL_DUAL_PAN_AUTO              (1<<1)
+#define cDUAL_PAN_CTRL_ACTIVE_NETWORK             (1<<0)
+
+// DUAL_PAN_STS bits
+#define cDUAL_PAN_STS_RECD_ON_PAN1        (1<<7)
+#define cDUAL_PAN_STS_RECD_ON_PAN0        (1<<6)
+#define cDUAL_PAN_STS_DUAL_PAN_REMAIN     (0x3F)
+
+// CCA_CTRL bits
+#define cCCA_CTRL_AGC_FRZ_EN          (1<<6)
+#define cCCA_CTRL_CONT_RSSI_EN        (1<<5)
+#define cCCA_CTRL_LQI_RSSI_NOT_CORR   (1<<4)
+#define cCCA_CTRL_CCA3_AND_NOT_OR     (1<<3)
+#define cCCA_CTRL_POWER_COMP_EN_LQI   (1<<2)
+#define cCCA_CTRL_POWER_COMP_EN_ED    (1<<1)
+#define cCCA_CTRL_POWER_COMP_EN_CCA1  (1<<0)
+
+// GPIO_DATA bits
+#define cGPIO_DATA_7        (1<<7)
+#define cGPIO_DATA_6        (1<<6)
+#define cGPIO_DATA_5        (1<<5)
+#define cGPIO_DATA_4        (1<<4)
+#define cGPIO_DATA_3        (1<<3)
+#define cGPIO_DATA_2        (1<<2)
+#define cGPIO_DATA_1        (1<<1)
+#define cGPIO_DATA_0        (1<<0)
+
+// GPIO_DIR bits
+#define cGPIO_DIR_7         (1<<7)
+#define cGPIO_DIR_6         (1<<6)
+#define cGPIO_DIR_5         (1<<5)
+#define cGPIO_DIR_4         (1<<4)
+#define cGPIO_DIR_3         (1<<3)
+#define cGPIO_DIR_2         (1<<2)
+#define cGPIO_DIR_1         (1<<1)
+#define cGPIO_DIR_0         (1<<0)
+
+// GPIO_PUL_EN bits
+#define cGPIO_PUL_EN_7      (1<<7)
+#define cGPIO_PUL_EN_6      (1<<6)
+#define cGPIO_PUL_EN_5      (1<<5)
+#define cGPIO_PUL_EN_4      (1<<4)
+#define cGPIO_PUL_EN_3      (1<<3)
+#define cGPIO_PUL_EN_2      (1<<2)
+#define cGPIO_PUL_EN_1      (1<<1)
+#define cGPIO_PUL_EN_0      (1<<0)
+
+// GPIO_PUL_SEL bits
+#define cGPIO_PUL_SEL_7     (1<<7)
+#define cGPIO_PUL_SEL_6     (1<<6)
+#define cGPIO_PUL_SEL_5     (1<<5)
+#define cGPIO_PUL_SEL_4     (1<<4)
+#define cGPIO_PUL_SEL_3     (1<<3)
+#define cGPIO_PUL_SEL_2     (1<<2)
+#define cGPIO_PUL_SEL_1     (1<<1)
+#define cGPIO_PUL_SEL_0     (1<<0)
+
+// GPIO_DS bits
+#define cGPIO_DS_7          (1<<7)
+#define cGPIO_DS_6          (1<<6)
+#define cGPIO_DS_5          (1<<5)
+#define cGPIO_DS_4          (1<<4)
+#define cGPIO_DS_3          (1<<3)
+#define cGPIO_DS_2          (1<<2)
+#define cGPIO_DS_1          (1<<1)
+#define cGPIO_DS_0          (1<<0)
+
+// SPI_CTRL bits
+//#define cSPI_CTRL_MISO_HIZ_EN        (1<<1)
+//#define cSPI_CTRL_PB_PROTECT         (1<<0)
+
+// ANT_PAD_CTRL bits
+#define cANT_PAD_CTRL_ANTX_POL           (0x0F)
+#define cANT_PAD_CTRL_ANTX_POL_Shift_c   (4)
+#define cANT_PAD_CTRL_ANTX_CTRLMODE      (1<<3)
+#define cANT_PAD_CTRL_ANTX_HZ            (1<<2)
+#define cANT_PAD_CTRL_ANTX_EN            (3)
+
+// MISC_PAD_CTRL bits
+#define cMISC_PAD_CTRL_MISO_HIZ_EN        (1<<3)
+#define cMISC_PAD_CTRL_IRQ_B_OD           (1<<2)
+#define cMISC_PAD_CTRL_NON_GPIO_DS        (1<<1)
+#define cMISC_PAD_CTRL_ANTX_CURR          (1<<0)
+
+// ANT_AGC_CTRL bits
+#define cANT_AGC_CTRL_FAD_EN_Shift_c    (0)
+#define cANT_AGC_CTRL_FAD_EN_Mask_c     (1<<cANT_AGC_CTRL_FAD_EN_Shift_c)
+#define cANT_AGC_CTRL_ANTX_Shift_c      (1)
+#define cANT_AGC_CTRL_ANTX_Mask_c       (1<<cANT_AGC_CTRL_ANTX_Shift_c)
+
+// BSM_CTRL bits
+#define cBSM_CTRL_BSM_EN                  (1<<0)
+
+// SOFT_RESET bits
+#define cSOFT_RESET_SOG_RST            (1<<7)
+#define cSOFT_RESET_REGS_RST           (1<<4)
+#define cSOFT_RESET_PLL_RST            (1<<3)
+#define cSOFT_RESET_TX_RST             (1<<2)
+#define cSOFT_RESET_RX_RST             (1<<1)
+#define cSOFT_RESET_SEQ_MGR_RST        (1<<0)
+
+// SEQ_MGR_CTRL bits
+#define cSEQ_MGR_CTRL_SEQ_STATE_CTRL          (3)
+#define cSEQ_MGR_CTRL_SEQ_STATE_CTRL_Shift_c  (6)
+#define cSEQ_MGR_CTRL_NO_RX_RECYCLE           (1<<5)
+#define cSEQ_MGR_CTRL_LATCH_PREAMBLE          (1<<4)
+#define cSEQ_MGR_CTRL_EVENT_TMR_DO_NOT_LATCH  (1<<3)
+#define cSEQ_MGR_CTRL_CLR_NEW_SEQ_INHIBIT     (1<<2)
+#define cSEQ_MGR_CTRL_PSM_LOCK_DIS            (1<<1)
+#define cSEQ_MGR_CTRL_PLL_ABORT_OVRD          (1<<0)
+
+// SEQ_MGR_STS bits
+#define cSEQ_MGR_STS_TMR2_SEQ_TRIG_ARMED (1<<7)
+#define cSEQ_MGR_STS_RX_MODE             (1<<6)
+#define cSEQ_MGR_STS_RX_TIMEOUT_PENDING  (1<<5)
+#define cSEQ_MGR_STS_NEW_SEQ_INHIBIT     (1<<4)
+#define cSEQ_MGR_STS_SEQ_IDLE            (1<<3)
+#define cSEQ_MGR_STS_XCVSEQ_ACTUAL       (7)
+
+// ABORT_STS bits
+#define cABORT_STS_PLL_ABORTED        (1<<2)
+#define cABORT_STS_TC3_ABORTED        (1<<1)
+#define cABORT_STS_SW_ABORTED         (1<<0)
+
+// FILTERFAIL_CODE2 bits
+#define cFILTERFAIL_CODE2_PAN_SEL  (1<<7)
+#define cFILTERFAIL_CODE2_9_8      (3)
+
+// PHY_STS bits
+#define cPHY_STS_PLL_UNLOCK  (1<<7)
+#define cPHY_STS_PLL_LOCK_ERR        (1<<6)
+#define cPHY_STS_PLL_LOCK            (1<<5)
+#define cPHY_STS_CRCVALID            (1<<3)
+#define cPHY_STS_FILTERFAIL_FLAG_SEL (1<<2)
+#define cPHY_STS_SFD_DET             (1<<1)
+#define cPHY_STS_PREAMBLE_DET        (1<<0)
+
+// TESTMODE_CTRL bits
+#define cTEST_MODE_CTRL_HOT_ANT            (1<<4)
+#define cTEST_MODE_CTRL_IDEAL_RSSI_EN      (1<<3)
+#define cTEST_MODE_CTRL_IDEAL_PFC_EN       (1<<2)
+#define cTEST_MODE_CTRL_CONTINUOUS_EN      (1<<1)
+#define cTEST_MODE_CTRL_FPGA_EN            (1<<0)
+
+// DTM_CTRL1 bits
+#define cDTM_CTRL1_ATM_LOCKED  (1<<7)
+#define cDTM_CTRL1_DTM_EN      (1<<6)
+#define cDTM_CTRL1_PAGE5       (1<<5)
+#define cDTM_CTRL1_PAGE4       (1<<4)
+#define cDTM_CTRL1_PAGE3       (1<<3)
+#define cDTM_CTRL1_PAGE2       (1<<2)
+#define cDTM_CTRL1_PAGE1       (1<<1)
+#define cDTM_CTRL1_PAGE0       (1<<0)
+
+// TX_MODE_CTRL
+#define cTX_MODE_CTRL_TX_INV   (1<<4)
+#define cTX_MODE_CTRL_BT_EN    (1<<3)
+#define cTX_MODE_CTRL_DTS2     (1<<2)
+#define cTX_MODE_CTRL_DTS1     (1<<1)
+#define cTX_MODE_CTRL_DTS0     (1<<0)
+
+#define cTX_MODE_CTRL_DTS_MASK (7)
+
+// CLK_OUT_CTRL bits
+#define cCLK_OUT_EXTEND        (1<<7)
+#define cCLK_OUT_HIZ           (1<<6)
+#define cCLK_OUT_SR            (1<<5)
+#define cCLK_OUT_DS            (1<<4)
+#define cCLK_OUT_EN            (1<<3)
+#define cCLK_OUT_DIV_Mask      (7<<0)
+
+#define gCLK_OUT_FREQ_32_MHz      (0)
+#define gCLK_OUT_FREQ_16_MHz      (1)
+#define gCLK_OUT_FREQ_8_MHz       (2)
+#define gCLK_OUT_FREQ_4_MHz       (3)
+#define gCLK_OUT_FREQ_1_MHz       (4)
+#define gCLK_OUT_FREQ_250_KHz     (5)
+#define gCLK_OUT_FREQ_62_5_KHz    (6)
+#define gCLK_OUT_FREQ_32_78_KHz   (7)
+#define gCLK_OUT_FREQ_DISABLE     (8)
+
+
+
+
+#endif /* __MCR20_REG_H__ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1782 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "NanostackRfPhyMcr20a.h"
+#include "ns_types.h"
+#include "platform/arm_hal_interrupt.h"
+#include "nanostack/platform/arm_hal_phy.h"
+#include "toolchain.h"
+#include <string.h>
+
+/* Freescale headers which are for C files */
+extern "C" {
+#include "MCR20Drv.h"
+#include "MCR20Reg.h"
+#include "MCR20Overwrites.h"
+}
+
+
+#define RF_BUFFER_SIZE 128
+
+/*Radio RX and TX state definitions*/
+#define RFF_ON 0x01
+#define RFF_RX 0x02
+#define RFF_TX 0x04
+#define RFF_CCA 0x08
+
+#define RF_MODE_NORMAL  0
+#define RF_MODE_SNIFFER 1
+
+#define RF_CCA_THRESHOLD 75 /* -75 dBm */
+
+#define RF_TX_POWER_MAX 0
+
+/* PHY constants in symbols */
+#define gPhyWarmUpTime_c       9
+#define gPhySHRDuration_c     10
+#define gPhySymbolsPerOctet_c  2
+#define gPhyAckWaitDuration_c 54
+
+#define gCcaED_c               0
+#define gCcaCCA_MODE1_c        1
+
+#define gXcvrRunState_d       gXcvrPwrAutodoze_c
+#define gXcvrLowPowerState_d  gXcvrPwrHibernate_c
+
+
+/* MCR20A XCVR states */
+typedef enum xcvrState_tag{
+  gIdle_c,
+  gRX_c,
+  gTX_c,
+  gCCA_c,
+  gTR_c,
+  gCCCA_c,
+}xcvrState_t;
+
+/* MCR20A XCVR low power states */
+typedef enum xcvrPwrMode_tag{
+    gXcvrPwrIdle_c,
+    gXcvrPwrAutodoze_c,
+    gXcvrPwrDoze_c,
+    gXcvrPwrHibernate_c
+}xcvrPwrMode_t;
+
+
+/*RF Part Type*/
+typedef enum
+{
+    FREESCALE_UNKNOW_DEV = 0,
+    FREESCALE_MCR20A
+}rf_trx_part_e;
+
+/*Atmel RF states*/
+typedef enum
+{
+    NOP = 0x00,
+    BUSY_RX = 0x01,
+    RF_TX_START = 0x02,
+    FORCE_TRX_OFF = 0x03,
+    FORCE_PLL_ON = 0x04,
+    RX_ON = 0x06,
+    TRX_OFF = 0x08,
+    PLL_ON = 0x09,
+    BUSY_RX_AACK = 0x11,
+    SLEEP = 0x0F,
+    RX_AACK_ON = 0x16,
+    TX_ARET_ON = 0x19
+}rf_trx_states_t;
+
+/*RF receive buffer*/
+static uint8_t rf_buffer[RF_BUFFER_SIZE];
+
+/* TX info */
+static uint8_t  radio_tx_power = 0x17; /* 0 dBm */
+static uint8_t  mac_tx_handle = 0;
+static uint8_t  need_ack = 0;
+static uint16_t tx_len = 0;
+
+/* RF driver data */
+static xcvrState_t mPhySeqState;
+static xcvrPwrMode_t mPwrState;
+static phy_device_driver_s device_driver;
+static uint8_t mStatusAndControlRegs[8];
+static uint8_t rf_rnd = 0;
+static int8_t  rf_radio_driver_id = -1;
+static uint8_t MAC_address[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+
+/* Driver instance handle and hardware */
+static NanostackRfPhyMcr20a *rf = NULL;
+static SPI *spi = NULL;
+static DigitalOut *cs = NULL;
+static DigitalOut *rst = NULL;
+static InterruptIn *irq = NULL;
+static DigitalIn *irq_pin = NULL;
+
+/* Channel info */                 /* 2405    2410    2415    2420    2425    2430    2435    2440    2445    2450    2455    2460    2465    2470    2475    2480 */
+static const uint8_t  pll_int[16] =  {0x0B,   0x0B,   0x0B,   0x0B,   0x0B,   0x0B,   0x0C,   0x0C,   0x0C,   0x0C,   0x0C,   0x0C,   0x0D,   0x0D,   0x0D,   0x0D};
+static const uint16_t pll_frac[16] = {0x2800, 0x5000, 0x7800, 0xA000, 0xC800, 0xF000, 0x1800, 0x4000, 0x6800, 0x9000, 0xB800, 0xE000, 0x0800, 0x3000, 0x5800, 0x8000};
+static uint8_t rf_phy_channel = 0;
+
+/* Channel configurations for 2.4 */
+static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK};
+
+static const phy_device_channel_page_s phy_channel_pages[] = {
+        { CHANNEL_PAGE_0, &phy_24ghz},
+        { CHANNEL_PAGE_0, NULL}
+};
+
+
+static rf_trx_part_e rf_radio_type_read(void);
+
+MBED_UNUSED static void rf_ack_wait_timer_start(uint16_t slots);
+MBED_UNUSED static void rf_ack_wait_timer_stop(void);
+MBED_UNUSED static void rf_handle_cca_ed_done(void);
+MBED_UNUSED static void rf_handle_tx_end(void);
+MBED_UNUSED static void rf_handle_rx_end(void);
+MBED_UNUSED static void rf_on(void);
+MBED_UNUSED static void rf_receive(void);
+MBED_UNUSED static void rf_poll_trx_state_change(rf_trx_states_t trx_state);
+MBED_UNUSED static void rf_init(void);
+MBED_UNUSED static void rf_set_mac_address(const uint8_t *ptr);
+MBED_UNUSED static int8_t rf_device_register(void);
+MBED_UNUSED static void rf_device_unregister(void);
+MBED_UNUSED static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol );
+MBED_UNUSED static void rf_cca_abort(void);
+MBED_UNUSED static void rf_read_mac_address(uint8_t *ptr);
+MBED_UNUSED static int8_t rf_read_random(void);
+MBED_UNUSED static void rf_calibration_cb(void);
+MBED_UNUSED static void rf_init_phy_mode(void);
+MBED_UNUSED static void rf_ack_wait_timer_interrupt(void);
+MBED_UNUSED static void rf_calibration_timer_interrupt(void);
+MBED_UNUSED static void rf_calibration_timer_start(uint32_t slots);
+MBED_UNUSED static void rf_cca_timer_interrupt(void);
+MBED_UNUSED static void rf_cca_timer_start(uint32_t slots);
+MBED_UNUSED static uint16_t rf_get_phy_mtu_size(void);
+MBED_UNUSED static uint8_t rf_scale_lqi(int8_t rssi);
+
+/**
+ *  RF output power write
+ *
+ * \brief TX power has to be set before network start.
+ *
+ * \param power
+ *              See datasheet for TX power settings
+ *
+ * \return 0, Supported Value
+ * \return -1, Not Supported Value
+ */
+MBED_UNUSED static int8_t rf_tx_power_set(uint8_t power);
+MBED_UNUSED static uint8_t rf_tx_power_get(void);
+MBED_UNUSED static int8_t rf_enable_antenna_diversity(void);
+
+/* Private functions */
+MBED_UNUSED static void    rf_abort(void);
+MBED_UNUSED static void    rf_promiscuous(uint8_t mode);
+MBED_UNUSED static void    rf_get_timestamp(uint32_t *pRetClk);
+MBED_UNUSED static void    rf_set_timeout(uint32_t *pEndTime);
+MBED_UNUSED static void    rf_set_power_state(xcvrPwrMode_t newState);
+MBED_UNUSED static uint8_t rf_if_read_rnd(void);
+MBED_UNUSED static uint8_t rf_convert_LQI(uint8_t hwLqi);
+MBED_UNUSED static uint8_t rf_get_channel_energy(void);
+MBED_UNUSED static uint8_t rf_convert_energy_level(uint8_t energyLevel);
+MBED_UNUSED static int8_t  rf_convert_LQI_to_RSSI(uint8_t lqi);
+MBED_UNUSED static int8_t  rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
+MBED_UNUSED static int8_t  rf_extension(phy_extension_type_e extension_type,uint8_t *data_ptr);
+MBED_UNUSED static int8_t  rf_address_write(phy_address_type_e address_type,uint8_t *address_ptr);
+MBED_UNUSED static void rf_mac64_read(uint8_t *address);
+
+
+
+/*
+ * \brief Read connected radio part.
+ *
+ * This function only return valid information when rf_init() is called
+ *
+ * \return
+ */
+static rf_trx_part_e rf_radio_type_read(void)
+{
+    return FREESCALE_MCR20A;
+}
+
+/*
+ * \brief Function initialises and registers the RF driver.
+ *
+ * \param none
+ *
+ * \return rf_radio_driver_id Driver ID given by NET library
+ */
+static int8_t rf_device_register(void)
+{
+    rf_trx_part_e radio_type;
+
+    rf_init();
+
+
+
+    radio_type = rf_radio_type_read();
+    if(radio_type == FREESCALE_MCR20A)
+    {
+        /*Set pointer to MAC address*/
+        device_driver.PHY_MAC = MAC_address;
+        device_driver.driver_description = (char*)"FREESCALE_MAC";
+
+        //Create setup Used Radio chips
+        /*Type of RF PHY is SubGHz*/
+        device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
+
+        device_driver.phy_channel_pages = phy_channel_pages;
+        /*Maximum size of payload is 127*/
+        device_driver.phy_MTU = 127;
+        /*No header in PHY*/
+        device_driver.phy_header_length = 0;
+        /*No tail in PHY*/
+        device_driver.phy_tail_length = 0;
+        /*Set address write function*/
+        device_driver.address_write = &rf_address_write;
+        /*Set RF extension function*/
+        device_driver.extension = &rf_extension;
+        /*Set RF state control function*/
+        device_driver.state_control = &rf_interface_state_control;
+        /*Set transmit function*/
+        device_driver.tx = &rf_start_cca;
+        /*Upper layer callbacks init to NULL*/
+        device_driver.phy_rx_cb = NULL;
+        device_driver.phy_tx_done_cb = NULL;
+        /*Virtual upper data callback init to NULL*/
+        device_driver.arm_net_virtual_rx_cb = NULL;
+        device_driver.arm_net_virtual_tx_cb = NULL;
+
+        /*Register device driver*/
+        rf_radio_driver_id = arm_net_phy_register(&device_driver);
+    }
+
+    return rf_radio_driver_id;
+}
+
+/*
+ * \brief Function unregisters the RF driver.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_device_unregister(void)
+{
+    arm_net_phy_unregister(rf_radio_driver_id);
+}
+
+/*
+ * \brief Function returns the generated 8-bit random value for seeding Pseudo-random generator.
+ *
+ * \param none
+ *
+ * \return random value
+ */
+static int8_t rf_read_random(void)
+{
+    return rf_rnd;
+}
+
+/*
+ * \brief Function is a call back for ACK wait timeout.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_ack_wait_timer_interrupt(void)
+{
+    /* The packet was transmitted successfully, but no ACK was received */
+    if (device_driver.phy_tx_done_cb) {
+        device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
+    }
+    rf_receive();
+}
+
+/*
+ * \brief Function is a call back for calibration interval timer.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_calibration_timer_interrupt(void)
+{
+}
+
+/*
+ * \brief Function is a call back for cca interval timer.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_cca_timer_interrupt(void)
+{
+    /* CCA time-out handled by Hardware */
+}
+
+
+/*
+ * \brief Function starts the ACK wait time-out.
+ *
+ * \param slots The ACK wait time-out in [symbols]
+ *
+ * \return none
+ */
+static void rf_ack_wait_timer_start(uint16_t time)
+{
+    uint32_t timeout;
+
+    rf_get_timestamp(&timeout);
+    timeout += time;
+    rf_set_timeout(&timeout);
+}
+
+/*
+ * \brief Function starts the calibration interval.
+ *
+ * \param slots Given slots, resolution 50us
+ *
+ * \return none
+ */
+static void rf_calibration_timer_start(uint32_t slots)
+{
+    (void)slots;
+}
+
+/*
+ * \brief Function starts the CCA timout.
+ *
+ * \param slots Given slots, resolution 50us
+ *
+ * \return none
+ */
+static void rf_cca_timer_start(uint32_t slots)
+{
+    (void)slots;
+}
+
+/*
+ * \brief Function stops the ACK wait timeout.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_ack_wait_timer_stop(void)
+{
+}
+
+/*
+ * \brief Function reads the MAC address array.
+ *
+ * \param ptr Pointer to read array
+ *
+ * \return none
+ */
+static void rf_read_mac_address(uint8_t *ptr)
+{
+    memcpy(ptr, MAC_address, 8);
+}
+
+/*
+ * \brief Function sets the MAC address array.
+ *
+ * \param ptr Pointer to given MAC address array
+ *
+ * \return none
+ */
+static void rf_set_mac_address(const uint8_t *ptr)
+{
+    memcpy(MAC_address, ptr, 8);
+}
+
+static uint16_t rf_get_phy_mtu_size(void)
+{
+    return device_driver.phy_MTU;
+}
+
+/*
+ * \brief Function writes 16-bit address in RF address filter.
+ *
+ * \param short_address Given short address
+ *
+ * \return none
+ */
+static void rf_set_short_adr(uint8_t * short_address)
+{
+    /* Write one register at a time to be accessible from hibernate mode */
+    MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_MSB, short_address[0]);
+    MCR20Drv_IndirectAccessSPIWrite(MACSHORTADDRS0_LSB, short_address[1]);
+}
+
+/*
+ * \brief Function writes PAN Id in RF PAN Id filter.
+ *
+ * \param pan_id Given PAN Id
+ *
+ * \return none
+ */
+static void rf_set_pan_id(uint8_t *pan_id)
+{
+    /* Write one register at a time to be accessible from hibernate mode */
+    MCR20Drv_IndirectAccessSPIWrite(MACPANID0_MSB, pan_id[0]);
+    MCR20Drv_IndirectAccessSPIWrite(MACPANID0_LSB, pan_id[1]);
+}
+
+/*
+ * \brief Function writes 64-bit address in RF address filter.
+ *
+ * \param address Given 64-bit address
+ *
+ * \return none
+ */
+static void rf_set_address(uint8_t *address)
+{
+    /* Write one register at a time to be accessible from hibernate mode */
+    MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_0,  address[7]);
+    MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_8,  address[6]);
+    MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_16, address[5]);
+    MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_24, address[4]);
+    MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_32, address[3]);
+    MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_40, address[2]);
+    MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_48, address[1]);
+    MCR20Drv_IndirectAccessSPIWrite(MACLONGADDRS0_56, address[0]);
+}
+
+/*
+ * \brief Function sets the RF channel.
+ *
+ * \param ch New channel
+ *
+ * \return none
+ */
+static void rf_channel_set(uint8_t channel)
+{
+    rf_phy_channel = channel;
+    MCR20Drv_DirectAccessSPIWrite(PLL_INT0, pll_int[channel - 11]);
+    MCR20Drv_DirectAccessSPIMultiByteWrite(PLL_FRAC0_LSB, (uint8_t *) &pll_frac[channel - 11], 2);
+}
+
+
+/*
+ * \brief Function initialises the radio driver and resets the radio.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_init(void)
+{
+    uint32_t index;
+    mPhySeqState = gIdle_c;
+    mPwrState = gXcvrPwrIdle_c;
+    /*Reset RF module*/
+    MCR20Drv_RESET();
+    /* Initialize the transceiver SPI driver */
+    MCR20Drv_Init();
+    /* Disable Tristate on MISO for SPI reads */
+    MCR20Drv_IndirectAccessSPIWrite(MISC_PAD_CTRL, 0x02);
+    /* Set XCVR clock output settings */
+    MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d);
+    /* Set default XCVR power state */
+    rf_set_power_state(gXcvrRunState_d);
+
+    /* PHY_CTRL1 default HW settings  + AUTOACK enabled */
+    mStatusAndControlRegs[PHY_CTRL1] = cPHY_CTRL1_AUTOACK;
+    /* PHY_CTRL2 : mask all PP interrupts */
+    mStatusAndControlRegs[PHY_CTRL2] = cPHY_CTRL2_CRC_MSK | \
+                                       cPHY_CTRL2_PLL_UNLOCK_MSK | \
+                                       /*cPHY_CTRL2_FILTERFAIL_MSK | */ \
+                                       cPHY_CTRL2_RX_WMRK_MSK | \
+                                       cPHY_CTRL2_CCAMSK | \
+                                       cPHY_CTRL2_RXMSK | \
+                                       cPHY_CTRL2_TXMSK | \
+                                       cPHY_CTRL2_SEQMSK;
+    /* PHY_CTRL3 : enable timer 3 and disable remaining interrupts */
+    mStatusAndControlRegs[PHY_CTRL3] = cPHY_CTRL3_ASM_MSK    | \
+                                       cPHY_CTRL3_PB_ERR_MSK | \
+                                       cPHY_CTRL3_WAKE_MSK   | \
+                                       cPHY_CTRL3_TMR3CMP_EN;
+    /* PHY_CTRL4 unmask global TRX interrupts, enable 16 bit mode for TC2 - TC2 prime EN */
+    mStatusAndControlRegs[PHY_CTRL4] = cPHY_CTRL4_TC2PRIME_EN | (gCcaCCA_MODE1_c << cPHY_CTRL4_CCATYPE_Shift_c);
+    /* Clear all PP IRQ bits to avoid unexpected interrupts immediately after initialization */
+    mStatusAndControlRegs[IRQSTS1] = cIRQSTS1_PLL_UNLOCK_IRQ | \
+                                     cIRQSTS1_FILTERFAIL_IRQ | \
+                                     cIRQSTS1_RXWTRMRKIRQ | \
+                                     cIRQSTS1_CCAIRQ | \
+                                     cIRQSTS1_RXIRQ | \
+                                     cIRQSTS1_TXIRQ | \
+                                     cIRQSTS1_SEQIRQ;
+    
+    mStatusAndControlRegs[IRQSTS2] = cIRQSTS2_ASM_IRQ | cIRQSTS2_PB_ERR_IRQ | cIRQSTS2_WAKE_IRQ;
+    /* Mask and clear all TMR IRQs */
+    mStatusAndControlRegs[IRQSTS3] = cIRQSTS3_TMR4MSK | cIRQSTS3_TMR3MSK | cIRQSTS3_TMR2MSK | cIRQSTS3_TMR1MSK | \
+                                     cIRQSTS3_TMR4IRQ | cIRQSTS3_TMR3IRQ | cIRQSTS3_TMR2IRQ | cIRQSTS3_TMR1IRQ;
+    /* Write settings to XCVR */
+    MCR20Drv_DirectAccessSPIMultiByteWrite(PHY_CTRL1, &mStatusAndControlRegs[PHY_CTRL1], 5);
+    /* Clear all interrupts */
+    MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, &mStatusAndControlRegs[IRQSTS1], 3);
+    
+    /*  RX_FRAME_FILTER. Accept FrameVersion 0 and 1 packets, reject all others */
+    MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, (cRX_FRAME_FLT_FRM_VER | \
+                                                      cRX_FRAME_FLT_BEACON_FT | \
+                                                      cRX_FRAME_FLT_DATA_FT | \
+                                                      cRX_FRAME_FLT_CMD_FT ));
+    /* Direct register overwrites */
+    for (index = 0; index < sizeof(overwrites_direct)/sizeof(overwrites_t); index++)
+        MCR20Drv_DirectAccessSPIWrite(overwrites_direct[index].address, overwrites_direct[index].data);
+    /* Indirect register overwrites */
+    for (index = 0; index < sizeof(overwrites_indirect)/sizeof(overwrites_t); index++)
+        MCR20Drv_IndirectAccessSPIWrite(overwrites_indirect[index].address, overwrites_indirect[index].data);
+
+    /* Set the CCA energy threshold value */
+    MCR20Drv_IndirectAccessSPIWrite(CCA1_THRESH, RF_CCA_THRESHOLD);
+    /* Set prescaller to obtain 1 symbol (16us) timebase */
+    MCR20Drv_IndirectAccessSPIWrite(TMR_PRESCALE, 0x05);
+
+    MCR20Drv_IRQ_Enable();
+
+    /*Read random variable. This will be used when seeding pseudo-random generator*/
+    rf_rnd = rf_if_read_rnd();
+    /*Read eui64*/
+    rf_mac64_read(MAC_address);
+    /*set default channel to 11*/
+    rf_channel_set(11);
+    /*Start receiver*/
+    rf_receive();
+}
+
+/**
+ * \brief Function gets called when MAC is setting radio off.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_off(void)
+{
+    /* Abort any ongoing sequences */
+    rf_abort();
+    /* Set XCVR in a low power state */
+    rf_set_power_state(gXcvrLowPowerState_d);
+}
+
+/*
+ * \brief Function polls the RF state until it has changed to desired state.
+ *
+ * \param trx_state RF state
+ *
+ * \return none
+ */
+static void rf_poll_trx_state_change(rf_trx_states_t trx_state)
+{
+    (void)trx_state;
+}
+
+/*
+ * \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO.
+ *
+ * \param data_ptr Pointer to TX data
+ * \param data_length Length of the TX data
+ * \param tx_handle Handle to transmission
+ * \return 0 Success
+ * \return -1 Busy
+ */
+static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol )
+{
+    uint8_t ccaMode;
+
+    /* Parameter validation */
+    if( !data_ptr || (data_length > 125) || (PHY_LAYER_PAYLOAD != data_protocol) )
+    {
+        return -1;
+    }
+
+    if( mPhySeqState == gRX_c )
+    {
+        uint8_t phyReg = MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F;
+        /* Check for an Rx in progress. */
+        if((phyReg <= 0x06) || (phyReg == 0x15) || (phyReg == 0x16))
+        {
+            if (device_driver.phy_tx_done_cb) {
+                device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
+            }
+            return -1;
+        }
+        rf_abort();
+    }
+
+    /*Check if transmitter is busy*/
+    if( mPhySeqState != gIdle_c )
+    {
+        /*Return busy*/
+        return -1;
+    }
+
+    /*Store TX handle*/
+    mac_tx_handle = tx_handle;
+    /*Check if transmitted data needs to be acked*/
+    need_ack = (*data_ptr & 0x20) == 0x20;
+
+    /* Set XCVR power state in run mode */
+    rf_set_power_state(gXcvrRunState_d);
+    /* Load data into XCVR */
+    tx_len = data_length + 2;
+    MCR20Drv_PB_SPIBurstWrite(data_ptr - 1, data_length + 1);
+    MCR20Drv_PB_SPIByteWrite(0,tx_len);
+    
+    /* Set CCA mode 1 */
+    ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE;
+    if( ccaMode != gCcaCCA_MODE1_c )
+    {
+        mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c);
+        mStatusAndControlRegs[PHY_CTRL4] |= gCcaCCA_MODE1_c << cPHY_CTRL4_CCATYPE_Shift_c;
+        MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]);
+    }
+
+    /* Read XCVR registers */
+    mStatusAndControlRegs[0] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[1], 4);
+    mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
+    mStatusAndControlRegs[PHY_CTRL1] |= gCCA_c;
+    mPhySeqState = gCCA_c;
+
+    /* Ensure that no spurious interrupts are raised */
+    mStatusAndControlRegs[IRQSTS3] &= 0xF0; /* do not change other IRQ status */
+    mStatusAndControlRegs[IRQSTS3] |= (cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ);
+    MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
+
+    /* Write XCVR settings */
+    MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
+    
+    /* Unmask SEQ interrupt */
+    mStatusAndControlRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
+    MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, mStatusAndControlRegs[PHY_CTRL2]);
+
+    /*Return success*/
+    return 0;
+}
+
+/*
+ * \brief Function aborts CCA process.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_cca_abort(void)
+{
+    rf_abort();
+}
+
+/*
+ * \brief Function starts the transmission of the frame. Called from ISR context!
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_start_tx(void)
+{
+    /* Perform TxRxAck sequence if required by phyTxMode */
+    if( need_ack )
+    {
+        mStatusAndControlRegs[PHY_CTRL1] |= cPHY_CTRL1_RXACKRQD;
+        mPhySeqState = gTR_c;
+    }
+    else
+    {
+        mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_RXACKRQD);
+        mPhySeqState = gTX_c;
+    }
+
+    mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
+    mStatusAndControlRegs[PHY_CTRL1] |= mPhySeqState;
+    
+    /* Unmask SEQ interrupt */
+    mStatusAndControlRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
+
+    /* Start the sequence immediately */
+    MCR20Drv_DirectAccessSPIMultiByteWrite(PHY_CTRL1, &mStatusAndControlRegs[PHY_CTRL1], 2);
+
+    if( need_ack )
+    {
+        rf_ack_wait_timer_start(gPhyWarmUpTime_c + gPhySHRDuration_c + tx_len * gPhySymbolsPerOctet_c + gPhyAckWaitDuration_c);
+    }
+}
+
+/*
+ * \brief Function sets the RF in RX state. Called from ISR context!
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_receive(void)
+{
+    uint8_t phyRegs[5];
+
+    /* RX can start only from Idle state */
+    if( mPhySeqState != gIdle_c )
+    {
+        return;
+    }
+
+    /* Set XCVR power state in run mode */
+    rf_set_power_state(gXcvrRunState_d);
+    /* read XVCR settings */
+    phyRegs[IRQSTS1] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &phyRegs[IRQSTS2], 4);
+    /* unmask SEQ interrupt */
+    phyRegs[PHY_CTRL2] &= ~(cPHY_CTRL2_SEQMSK);
+    /* set XcvrSeq to RX */
+    phyRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
+    phyRegs[PHY_CTRL1] |=  gRX_c;
+    mPhySeqState = gRX_c;
+    /* Ensure that no spurious interrupts are raised */
+    phyRegs[IRQSTS3] &= 0xF0; /* do not change other IRQ status */
+    phyRegs[IRQSTS3] |= cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ;
+    /* sync settings with XCVR */
+    MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, phyRegs, 5);
+}
+
+/*
+ * \brief Function calibrates the radio.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_calibration_cb(void)
+{
+}
+
+/*
+ * \brief Function sets RF_ON flag when radio is powered.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_on(void)
+{
+}
+
+/*
+ * \brief Function is a call back for RX end interrupt.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_handle_rx_end(void)
+{
+    uint8_t rf_lqi = MCR20Drv_DirectAccessSPIRead(LQI_VALUE);
+    int8_t rf_rssi = 0;
+    uint8_t len = mStatusAndControlRegs[RX_FRM_LEN] - 2;
+    
+
+    /*Start receiver*/
+    rf_receive();
+
+    /*Check the length is valid*/
+    if(len > 1 && len < RF_BUFFER_SIZE)
+    {
+        rf_lqi  = rf_convert_LQI(rf_lqi);
+        rf_rssi = rf_convert_LQI_to_RSSI(rf_lqi);
+        /*gcararu: Scale LQI using received RSSI, to match the LQI reported by the ATMEL radio */
+        rf_lqi  = rf_scale_lqi(rf_rssi);
+
+        /*Read received packet*/
+        MCR20Drv_PB_SPIBurstRead(rf_buffer, len);
+        if (device_driver.phy_rx_cb) {
+            device_driver.phy_rx_cb(rf_buffer, len, rf_lqi, rf_rssi, rf_radio_driver_id);
+        }
+    }
+}
+
+/*
+ * \brief Function is called when MAC is shutting down the radio.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_shutdown(void)
+{
+    /*Call RF OFF*/
+    rf_off();
+}
+
+/*
+ * \brief Function is a call back for TX end interrupt.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_handle_tx_end(void)
+{
+    uint8_t rx_frame_pending = mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_RX_FRM_PEND;
+
+    /*Start receiver*/
+    rf_receive();
+
+    if (!device_driver.phy_tx_done_cb) {
+        return;
+    }
+
+    /*Call PHY TX Done API*/
+    if( need_ack )
+    {
+        if( rx_frame_pending )
+        {
+            device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE_PENDING, 1, 1);
+        }
+        else
+        {
+            // arm_net_phy_tx_done(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
+            device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_DONE, 1, 1);
+        }
+    }
+    else
+    {
+        device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_SUCCESS, 1, 1);
+    }
+}
+
+/*
+ * \brief Function is a call back for CCA ED done interrupt.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_handle_cca_ed_done(void)
+{
+    /*Check the result of CCA process*/
+    if( !(mStatusAndControlRegs[IRQSTS2] & cIRQSTS2_CCA) ) 
+    {
+        rf_start_tx();
+    }
+    else if (device_driver.phy_tx_done_cb)
+    {
+        /*Send CCA fail notification*/
+        device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
+    }
+}
+
+/*
+ * \brief Function sets the TX power variable.
+ *
+ * \param power TX power setting
+ *
+ * \return 0 Success
+ * \return -1 Fail
+ */
+static int8_t rf_tx_power_set(uint8_t power)
+{
+    /* gcapraru: Map MCR20A Tx power levels over ATMEL values */
+    static uint8_t pwrLevelMapping[16] = {25,25,25,24,24,24,23,23,22,22,21,20,19,18,17,14};
+
+    if( power > 15 )
+    {
+        return -1;
+    }
+
+    radio_tx_power = power;
+    MCR20Drv_DirectAccessSPIWrite(PA_PWR, pwrLevelMapping[power]);
+    return 0;
+}
+
+/*
+ * \brief Function returns the TX power variable.
+ *
+ * \param none
+ *
+ * \return radio_tx_power TX power variable
+ */
+static uint8_t rf_tx_power_get(void)
+{
+    return radio_tx_power;
+}
+
+/*
+ * \brief Function enables the usage of Antenna diversity.
+ *
+ * \param none
+ *
+ * \return 0 Success
+ */
+static int8_t rf_enable_antenna_diversity(void)
+{
+    uint8_t phyReg;
+
+    phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_AGC_CTRL);
+    phyReg |= cANT_AGC_CTRL_FAD_EN_Mask_c;
+    MCR20Drv_IndirectAccessSPIWrite(ANT_AGC_CTRL, phyReg);
+
+    phyReg = MCR20Drv_IndirectAccessSPIRead(ANT_PAD_CTRL);
+    phyReg |= 0x02;
+    MCR20Drv_IndirectAccessSPIWrite(ANT_PAD_CTRL, phyReg);
+    
+    return 0;
+}
+
+/*
+ * \brief Function gives the control of RF states to MAC.
+ *
+ * \param new_state RF state
+ * \param rf_channel RF channel
+ *
+ * \return 0 Success
+ */
+static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
+{
+    int8_t ret_val = 0;
+    switch (new_state)
+    {
+        /*Reset PHY driver and set to idle*/
+        case PHY_INTERFACE_RESET:
+            break;
+        /*Disable PHY Interface driver*/
+        case PHY_INTERFACE_DOWN:
+            rf_shutdown();
+            break;
+        /*Enable PHY Interface driver*/
+        case PHY_INTERFACE_UP:
+            rf_channel_set(rf_channel);
+            rf_receive();
+            break;
+        /*Enable wireless interface ED scan mode*/
+        case PHY_INTERFACE_RX_ENERGY_STATE:
+            rf_abort();
+            rf_channel_set(rf_channel);
+            break;
+        case PHY_INTERFACE_SNIFFER_STATE:             /**< Enable Sniffer state */
+            rf_promiscuous(1);
+            rf_channel_set(rf_channel);
+            rf_receive();
+            break;
+    }
+    return ret_val;
+}
+
+/*
+ * \brief Function controls the ACK pending, channel setting and energy detection.
+ *
+ * \param extension_type Type of control
+ * \param data_ptr Data from NET library
+ *
+ * \return 0 Success
+ */
+static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
+{
+    switch (extension_type)
+    {
+        /*Control MAC pending bit for Indirect data transmission*/
+        case PHY_EXTENSION_CTRL_PENDING_BIT:
+        {
+            uint8_t reg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL);
+
+            if(*data_ptr)
+            {
+                reg |= cSRC_CTRL_ACK_FRM_PND;
+            }
+            else
+            {
+                reg &= ~cSRC_CTRL_ACK_FRM_PND;
+            }
+            
+            MCR20Drv_DirectAccessSPIWrite(SRC_CTRL, reg);
+            break;
+            
+        }
+        /*Return frame pending status*/
+        case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
+            *data_ptr = MCR20Drv_DirectAccessSPIRead(IRQSTS1 & cIRQSTS1_RX_FRM_PEND);
+            break;
+        /*Set channel*/
+        case PHY_EXTENSION_SET_CHANNEL:
+            break;
+        /*Read energy on the channel*/
+        case PHY_EXTENSION_READ_CHANNEL_ENERGY:
+            *data_ptr = rf_get_channel_energy();
+            break;
+        /*Read status of the link*/
+        case PHY_EXTENSION_READ_LINK_STATUS:
+            break;
+        case PHY_EXTENSION_CONVERT_SIGNAL_INFO:
+            break;
+    }
+    return 0;
+}
+
+/*
+ * \brief Function sets the addresses to RF address filters.
+ *
+ * \param address_type Type of address
+ * \param address_ptr Pointer to given address
+ *
+ * \return 0 Success
+ */
+static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
+{
+    int8_t ret_val = 0;
+    switch (address_type)
+    {
+        /*Set 48-bit address*/
+        case PHY_MAC_48BIT:
+            break;
+            /*Set 64-bit address*/
+        case PHY_MAC_64BIT:
+            rf_set_address(address_ptr);
+            break;
+        /*Set 16-bit address*/
+        case PHY_MAC_16BIT:
+            rf_set_short_adr(address_ptr);
+            break;
+        /*Set PAN Id*/
+        case PHY_MAC_PANID:
+            rf_set_pan_id(address_ptr);
+            break;
+    }
+    return ret_val;
+}
+
+static void rf_mac64_read(uint8_t *address)
+{
+    /* Write one register at a time to be accessible from hibernate mode */
+    address[7] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_0);
+    address[6] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_8);
+    address[5] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_16);
+    address[4] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_24);
+    address[3] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_32);
+    address[2] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_40);
+    address[1] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_48);
+    address[0] = MCR20Drv_DirectAccessSPIRead(MACLONGADDRS0_56);
+
+}
+
+/*
+ * \brief Function initialises the ACK wait time and returns the used PHY mode.
+ *
+ * \param none
+ *
+ * \return tmp Used PHY mode
+ */
+static void rf_init_phy_mode(void)
+{
+}
+
+/*
+ * \brief Function is a RF interrupt vector. End of frame in RX and TX are handled here as well as CCA process interrupt.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void PHY_InterruptHandler(void)
+{
+    uint8_t xcvseqCopy;
+
+    /* Disable and clear transceiver(IRQ_B) interrupt */
+    MCR20Drv_IRQ_Disable();
+    //MCR20Drv_IRQ_Clear();
+
+    /* Read transceiver interrupt status and control registers */
+    mStatusAndControlRegs[IRQSTS1] =
+        MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 7);
+
+    xcvseqCopy = mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ;
+    
+    /* Flter Fail IRQ */
+    if( (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_FILTERFAIL_IRQ) &&
+       !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_FILTERFAIL_MSK) )
+    {
+        if( xcvseqCopy == gRX_c )
+        {
+            /* Abort current SEQ */
+            mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
+            MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
+            /* Wait for Sequence Idle */
+            while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0);
+            /* Clear IRQ flags: */
+            MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ);
+            /* Restart Rx asap */
+            mStatusAndControlRegs[PHY_CTRL1] |= gRX_c;
+            MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
+        }
+    }
+    
+    /* TMR3 IRQ: ACK wait time-out */
+    if( (mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3IRQ) &&
+       !(mStatusAndControlRegs[IRQSTS3] & cIRQSTS3_TMR3MSK) )
+    {
+        /* Disable TMR3 IRQ */
+        mStatusAndControlRegs[IRQSTS3] |= cIRQSTS3_TMR3MSK;
+
+        if( xcvseqCopy == gTR_c )
+        {
+            /* Set XCVR to Idle */
+            mPhySeqState = gIdle_c;
+            mStatusAndControlRegs[PHY_CTRL1] &=  ~( cPHY_CTRL1_XCVSEQ );
+            /* Mask interrupts */
+            mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK;
+            /* Sync settings with XCVR */
+            MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5);
+            
+            rf_ack_wait_timer_interrupt();
+            MCR20Drv_IRQ_Enable();
+            return;
+        }
+    }
+
+    /* Sequencer interrupt, the autosequence has completed */
+    if( (mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_SEQIRQ) && 
+       !(mStatusAndControlRegs[PHY_CTRL2] & cPHY_CTRL2_SEQMSK) )
+    {
+        /* Set XCVR to Idle */
+        mPhySeqState = gIdle_c;
+        mStatusAndControlRegs[PHY_CTRL1] &=  ~( cPHY_CTRL1_XCVSEQ );
+        /* Mask interrupts */
+        mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_CCAMSK | cPHY_CTRL2_RXMSK | cPHY_CTRL2_TXMSK | cPHY_CTRL2_SEQMSK;
+        /* Sync settings with XCVR */
+        MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 5);
+                                                               
+        /* PLL unlock, the autosequence has been aborted due to PLL unlock */
+        if( mStatusAndControlRegs[IRQSTS1] & cIRQSTS1_PLL_UNLOCK_IRQ )
+        {
+            if(xcvseqCopy == gRX_c)
+            {
+                rf_receive();
+            }
+            MCR20Drv_IRQ_Enable();
+            return;
+        }
+
+        switch(xcvseqCopy)
+        {
+        case gTX_c:
+        case gTR_c:
+            rf_handle_tx_end();
+            break;
+
+        case gRX_c:
+            rf_handle_rx_end();
+            break;
+
+        case gCCA_c:
+            rf_handle_cca_ed_done();
+            break;
+
+        default:
+            break;
+        }
+        
+        MCR20Drv_IRQ_Enable();
+        return;
+    }
+    /* Other IRQ. Clear XCVR interrupt flags */
+    MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
+    MCR20Drv_IRQ_Enable();
+}
+
+/*
+ * \brief Function forces the XCVR to Idle state.
+ *
+ * \param none
+ *
+ * \return none
+ */
+static void rf_abort(void)
+{
+    /* Mask XCVR irq */
+    MCR20Drv_IRQ_Disable();
+
+    mPhySeqState = gIdle_c;
+
+    mStatusAndControlRegs[IRQSTS1] = MCR20Drv_DirectAccessSPIMultiByteRead(IRQSTS2, &mStatusAndControlRegs[IRQSTS2], 5);
+    
+    /* Mask SEQ interrupt */
+    mStatusAndControlRegs[PHY_CTRL2] |= cPHY_CTRL2_SEQMSK;
+    MCR20Drv_DirectAccessSPIWrite(PHY_CTRL2, mStatusAndControlRegs[PHY_CTRL2]);
+
+    if( (mStatusAndControlRegs[PHY_CTRL1] & cPHY_CTRL1_XCVSEQ) != gIdle_c )
+    {
+        /* Abort current SEQ */
+        mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
+        MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
+        
+        /* Wait for Sequence Idle (if not already) */
+        while ((MCR20Drv_DirectAccessSPIRead(SEQ_STATE) & 0x1F) != 0);
+        //while ( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ));
+        mStatusAndControlRegs[IRQSTS1] |= cIRQSTS1_SEQIRQ;
+    }
+
+    /* Clear all PP IRQ bits to avoid unexpected interrupts and mask TMR3 interrupt.
+       Do not change TMR IRQ status. */
+    mStatusAndControlRegs[IRQSTS3] &= 0xF0;
+    mStatusAndControlRegs[IRQSTS3] |= (cIRQSTS3_TMR3MSK | cIRQSTS3_TMR3IRQ);
+    MCR20Drv_DirectAccessSPIMultiByteWrite(IRQSTS1, mStatusAndControlRegs, 3);
+
+    /* Unmask XCVR irq */
+    MCR20Drv_IRQ_Enable();
+}
+
+/*
+ * \brief Function reads a time-stamp value from XCVR [symbols]
+ *
+ * \param pEndTime pointer to location where time-stamp will be stored
+ *
+ * \return none
+ */
+static void rf_get_timestamp(uint32_t *pRetClk)
+{
+    if(NULL == pRetClk)
+    {
+        return;
+    }
+
+    platform_enter_critical();
+
+    *pRetClk = 0;
+    MCR20Drv_DirectAccessSPIMultiByteRead(EVENT_TMR_LSB, (uint8_t *) pRetClk, 3);
+
+    platform_exit_critical();
+}
+
+/*
+ * \brief Function set a time-out to an XCVR sequence.
+ *
+ * \param pEndTime pointer to the sequence time-out value [symbols]
+ *
+ * \return none
+ */
+static void rf_set_timeout(uint32_t *pEndTime)
+{
+    uint8_t phyReg;
+    
+    if(NULL == pEndTime)
+    {
+        return;
+    }
+    
+    platform_enter_critical();
+    
+    phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
+    phyReg &= 0xF0;                    /* do not change IRQ status */
+    phyReg |= (cIRQSTS3_TMR3MSK);      /* mask TMR3 interrupt */
+    MCR20Drv_DirectAccessSPIWrite(IRQSTS3, phyReg);
+    
+    MCR20Drv_DirectAccessSPIMultiByteWrite(T3CMP_LSB, (uint8_t *) pEndTime, 3);
+    
+    phyReg &= ~(cIRQSTS3_TMR3MSK);      /* unmask TMR3 interrupt */
+    phyReg |= (cIRQSTS3_TMR3IRQ);       /* aknowledge TMR3 IRQ */
+    MCR20Drv_DirectAccessSPIWrite(IRQSTS3, phyReg);
+    
+    platform_exit_critical();
+}
+
+/*
+ * \brief Function reads a random number from RF.
+ *
+ * \param none 
+ *
+ * \return 8-bit random number
+ */
+static uint8_t rf_if_read_rnd(void)
+{
+    uint8_t phyReg;
+
+    MCR20Drv_IRQ_Disable();
+    /* Check if XCVR is idle */
+    phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1);
+
+    if( (phyReg & cPHY_CTRL1_XCVSEQ) == gIdle_c )
+    {
+        /* Program a new sequence */
+        MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, phyReg | gCCA_c);
+        /* Wait for sequence to finish */
+        while( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ) );
+        /* Clear interrupt flag */
+        MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_SEQIRQ);
+    }
+
+    MCR20Drv_IRQ_Enable();
+
+    return MCR20Drv_IndirectAccessSPIRead(_RNG);
+}
+
+/*
+ * \brief Function converts LQI into RSSI.
+ *
+ * \param LQI 
+ *
+ * \return RSSI
+ */
+static int8_t rf_convert_LQI_to_RSSI(uint8_t lqi)
+{
+    int32_t rssi = (50*lqi - 16820) / 163;
+    return (int8_t)rssi;
+}
+
+/*
+ * \brief Function scale the LQI value reported by RF into a 0-255 value.
+ *
+ * \param hwLqi - the LQI value reported by RF
+ *
+ * \return scaled LQI
+ */
+static uint8_t rf_convert_LQI(uint8_t hwLqi)
+{
+    uint32_t tmpLQI;
+
+    /* LQI Saturation Level */
+    if (hwLqi >= 230)
+    {
+        return 0xFF;
+    }
+    else if (hwLqi <= 9)
+    {
+        return 0;
+    }
+    else
+    {
+        /* Rescale the LQI values from min to saturation to the 0x00 - 0xFF range */
+        /* The LQI value mst be multiplied by ~1.1087 */
+        /* tmpLQI =  hwLqi * 7123 ~= hwLqi * 65536 * 0.1087 = hwLqi * 2^16 * 0.1087*/
+        tmpLQI = ((uint32_t)hwLqi * (uint32_t)7123 );
+        /* tmpLQI =  (tmpLQI / 2^16) + hwLqi */
+        tmpLQI = (uint32_t)(tmpLQI >> 16) + (uint32_t)hwLqi;
+
+        return (uint8_t)tmpLQI;
+    }
+}
+
+/*
+ * \brief Function enables/disables Rx promiscuous mode.
+ *
+ * \param state of XCVR promiscuous mode
+ *
+ * \return none
+ */
+static void rf_promiscuous(uint8_t state)
+{
+    uint8_t rxFrameFltReg, phyCtrl4Reg;
+
+    rxFrameFltReg = MCR20Drv_IndirectAccessSPIRead(RX_FRAME_FILTER);
+    phyCtrl4Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL4);
+
+    if( state )
+    {
+        /* FRM_VER[1:0] = b00. 00: Any FrameVersion accepted (0,1,2 & 3) */
+        /* All frame types accepted*/
+        phyCtrl4Reg   |= cPHY_CTRL4_PROMISCUOUS;
+        rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER);
+        rxFrameFltReg |=  (cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT);
+    }
+    else
+    {
+        phyCtrl4Reg   &= ~cPHY_CTRL4_PROMISCUOUS;
+        /* FRM_VER[1:0] = b11. Accept FrameVersion 0 and 1 packets, reject all others */
+        /* Beacon, Data and MAC command frame types accepted */
+        rxFrameFltReg &= ~(cRX_FRAME_FLT_FRM_VER);
+        rxFrameFltReg |= (0x03 << cRX_FRAME_FLT_FRM_VER_Shift_c);
+        rxFrameFltReg &= ~(cRX_FRAME_FLT_ACK_FT | cRX_FRAME_FLT_NS_FT);
+    }
+
+    MCR20Drv_IndirectAccessSPIWrite(RX_FRAME_FILTER, rxFrameFltReg);
+    MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, phyCtrl4Reg);
+}
+
+/*
+ * \brief Function used to switch XCVR power state.
+ *
+ * \param state The XCVR power mode
+ *
+ * \return none
+ */
+static void rf_set_power_state(xcvrPwrMode_t newState)
+{
+    uint8_t pwrMode;
+    uint8_t xtalState;
+
+    if( mPwrState == newState )
+    {
+        return;
+    }
+
+    /* Read power settings from RF */
+    pwrMode = MCR20Drv_DirectAccessSPIRead(PWR_MODES);
+    xtalState = pwrMode & cPWR_MODES_XTALEN;
+    
+    switch( newState )
+    {
+    case gXcvrPwrIdle_c:
+        pwrMode &= ~(cPWR_MODES_AUTODOZE);
+        pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_PMC_MODE);
+        break;
+    case gXcvrPwrAutodoze_c:
+        pwrMode |= (cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
+        break;
+    case gXcvrPwrDoze_c:
+        pwrMode &= ~(cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
+        pwrMode |= cPWR_MODES_XTALEN;
+        break;
+    case gXcvrPwrHibernate_c:
+        pwrMode &= ~(cPWR_MODES_XTALEN | cPWR_MODES_AUTODOZE | cPWR_MODES_PMC_MODE);
+        break;
+    default:
+        return;
+    }
+    
+    mPwrState = newState;
+    MCR20Drv_DirectAccessSPIWrite(PWR_MODES, pwrMode);
+    
+    if( !xtalState && (pwrMode & cPWR_MODES_XTALEN))
+    {
+        /* wait for crystal oscillator to complet its warmup */
+        while( ( MCR20Drv_DirectAccessSPIRead(PWR_MODES) & cPWR_MODES_XTAL_READY ) != cPWR_MODES_XTAL_READY);
+        /* wait for radio wakeup from hibernate interrupt */
+        while( ( MCR20Drv_DirectAccessSPIRead(IRQSTS2) & (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) ) != (cIRQSTS2_WAKE_IRQ | cIRQSTS2_TMRSTATUS) );
+
+        MCR20Drv_DirectAccessSPIWrite(IRQSTS2, cIRQSTS2_WAKE_IRQ);
+    }
+}
+
+/*
+ * \brief Function reads the energy level on the preselected channel.
+ *
+ * \return energy level
+ */
+static uint8_t rf_get_channel_energy(void)
+{
+    uint8_t ccaMode;
+
+    MCR20Drv_IRQ_Disable();
+    /* RX can start only from Idle state */
+    if( mPhySeqState != gIdle_c )
+    {
+        MCR20Drv_IRQ_Enable();
+        return 0;
+    }
+
+    /* Set XCVR power state in run mode */
+    rf_set_power_state(gXcvrRunState_d);
+
+    /* Switch to ED mode */
+    ccaMode = (mStatusAndControlRegs[PHY_CTRL4] >> cPHY_CTRL4_CCATYPE_Shift_c) & cPHY_CTRL4_CCATYPE;
+    if( ccaMode != gCcaED_c )
+    {
+        mStatusAndControlRegs[PHY_CTRL4] &= ~(cPHY_CTRL4_CCATYPE << cPHY_CTRL4_CCATYPE_Shift_c);
+        mStatusAndControlRegs[PHY_CTRL4] |= gCcaED_c << cPHY_CTRL4_CCATYPE_Shift_c;
+        MCR20Drv_DirectAccessSPIWrite(PHY_CTRL4, mStatusAndControlRegs[PHY_CTRL4]);
+    }
+    
+    /* Start ED sequence */
+    mStatusAndControlRegs[PHY_CTRL1] |= gCCA_c;
+    MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ);
+    MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
+    /* Wait for sequence to finish */
+    while ( !(MCR20Drv_DirectAccessSPIRead(IRQSTS1) & cIRQSTS1_SEQIRQ));
+    /* Set XCVR to Idle */
+    mStatusAndControlRegs[PHY_CTRL1] &= ~(cPHY_CTRL1_XCVSEQ);
+    MCR20Drv_DirectAccessSPIWrite(PHY_CTRL1, mStatusAndControlRegs[PHY_CTRL1]);
+    MCR20Drv_DirectAccessSPIWrite(IRQSTS1, cIRQSTS1_CCAIRQ | cIRQSTS1_SEQIRQ);
+    
+    MCR20Drv_IRQ_Enable();
+    
+    return rf_convert_energy_level(MCR20Drv_DirectAccessSPIRead(CCA1_ED_FNL));
+}
+
+/*
+ * \brief Function converts the energy level from dBm to a 0-255 value.
+ *
+ * \param energyLevel in dBm
+ *
+ * \return energy level (0-255)
+ */
+static uint8_t rf_convert_energy_level(uint8_t energyLevel)
+{
+    if(energyLevel >= 90)
+    {
+        /* ED value is below minimum. Return 0x00. */
+        energyLevel = 0x00;
+    }
+    else if(energyLevel <= 26)
+    {
+        /* ED value is above maximum. Return 0xFF. */
+        energyLevel = 0xFF;
+    }
+    else
+    {
+        /* Energy level (-90 dBm to -26 dBm ) --> varies form 0 to 64 */
+        energyLevel = (90 - energyLevel);
+        /* Rescale the energy level values to the 0x00-0xff range (0 to 64 translates in 0 to 255) */
+        /* energyLevel * 3.9844 ~= 4 */
+        /* Multiply with 4=2^2 by shifting left.
+        The multiplication will not overflow beacause energyLevel has values between 0 and 63 */
+        energyLevel <<= 2;
+    }
+
+    return energyLevel;
+}
+
+static uint8_t rf_scale_lqi(int8_t rssi)
+{
+    uint8_t scaled_lqi;
+    /*Worst case sensitivity*/
+    const int8_t rf_sensitivity = -98;
+
+    /*rssi < RF sensitivity*/
+    if(rssi < rf_sensitivity)
+        scaled_lqi=0;
+    /*-91 dBm < rssi < -81 dBm (AT86RF233 XPro)*/
+    /*-90 dBm < rssi < -80 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 10))
+        scaled_lqi=31;
+    /*-81 dBm < rssi < -71 dBm (AT86RF233 XPro)*/
+    /*-80 dBm < rssi < -70 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 20))
+        scaled_lqi=207;
+    /*-71 dBm < rssi < -61 dBm (AT86RF233 XPro)*/
+    /*-70 dBm < rssi < -60 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 30))
+        scaled_lqi=255;
+    /*-61 dBm < rssi < -51 dBm (AT86RF233 XPro)*/
+    /*-60 dBm < rssi < -50 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 40))
+        scaled_lqi=255;
+    /*-51 dBm < rssi < -41 dBm (AT86RF233 XPro)*/
+    /*-50 dBm < rssi < -40 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 50))
+        scaled_lqi=255;
+    /*-41 dBm < rssi < -31 dBm (AT86RF233 XPro)*/
+    /*-40 dBm < rssi < -30 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 60))
+        scaled_lqi=255;
+    /*-31 dBm < rssi < -21 dBm (AT86RF233 XPro)*/
+    /*-30 dBm < rssi < -20 dBm (AT86RF212B XPro)*/
+    else if(rssi < (rf_sensitivity + 70))
+        scaled_lqi=255;
+    /*rssi > RF saturation*/
+    else if(rssi > (rf_sensitivity + 80))
+        scaled_lqi=111;
+    /*-21 dBm < rssi < -11 dBm (AT86RF233 XPro)*/
+    /*-20 dBm < rssi < -10 dBm (AT86RF212B XPro)*/
+    else
+        scaled_lqi=255;
+
+    return scaled_lqi;
+}
+
+
+/*****************************************************************************/
+/*              Layer porting to the Freescale driver                        */
+/*****************************************************************************/
+extern "C" void xcvr_spi_init(uint32_t instance)
+{
+    (void)instance;
+}
+
+extern "C" void RF_IRQ_Init(void) {
+    MBED_ASSERT(irq != NULL);
+    irq->mode(PullUp);
+    irq->fall(&PHY_InterruptHandler);
+}
+
+extern "C" void RF_IRQ_Enable(void) {
+    MBED_ASSERT(irq != NULL);
+    irq->enable_irq();
+}
+
+extern "C" void RF_IRQ_Disable(void) {
+    MBED_ASSERT(irq != NULL);
+    irq->disable_irq();
+}
+
+extern "C" uint8_t RF_isIRQ_Pending(void) {
+    MBED_ASSERT(rf != NULL);
+    return !irq_pin->read();
+}
+
+extern "C" void RF_RST_Set(int state) {
+    MBED_ASSERT(rst != NULL);
+    *rst = state;
+}
+
+extern "C" void gXcvrAssertCS_d(void)
+{
+    MBED_ASSERT(cs != NULL);
+    *cs = 0;
+}
+
+extern "C" void gXcvrDeassertCS_d(void)
+{
+    MBED_ASSERT(cs != NULL);
+    *cs = 1;
+}
+
+extern "C" void xcvr_spi_configure_speed(uint32_t instance, uint32_t freq)
+{
+    MBED_ASSERT(spi != NULL);
+    (void)instance;
+    spi->frequency(freq);
+}
+
+extern "C" void xcvr_spi_transfer(uint32_t instance,
+                         uint8_t * sendBuffer,
+                         uint8_t * receiveBuffer,
+                         size_t transferByteCount)
+{
+    MBED_ASSERT(spi != NULL);
+    (void)instance;
+    volatile uint8_t dummy;
+
+    if( !transferByteCount )
+        return;
+
+    if( !sendBuffer && !receiveBuffer )
+        return;
+
+    while( transferByteCount-- )
+    {
+        if( sendBuffer )
+        {
+            dummy = *sendBuffer;
+            sendBuffer++;
+        }
+        else
+        {
+            dummy = 0xFF;
+        }
+
+        dummy = spi->write(dummy);
+
+        if( receiveBuffer )
+        {
+            *receiveBuffer = dummy;
+            receiveBuffer++;
+        }
+    }
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+
+static void rf_if_lock(void)
+{
+    platform_enter_critical();
+}
+
+static void rf_if_unlock(void)
+{
+    platform_exit_critical();
+}
+
+NanostackRfPhyMcr20a::NanostackRfPhyMcr20a(PinName spi_mosi, PinName spi_miso,
+        PinName spi_sclk, PinName spi_cs,  PinName spi_rst, PinName spi_irq)
+    : _spi(spi_mosi, spi_miso, spi_sclk), _rf_cs(spi_cs), _rf_rst(spi_rst),
+      _rf_irq(spi_irq), _rf_irq_pin(spi_irq)
+{
+    // Do nothing
+}
+
+NanostackRfPhyMcr20a::~NanostackRfPhyMcr20a()
+{
+    // Do nothing
+}
+
+int8_t NanostackRfPhyMcr20a::rf_register()
+{
+
+    rf_if_lock();
+
+    if (rf != NULL) {
+        rf_if_unlock();
+        error("Multiple registrations of NanostackRfPhyMcr20a not supported");
+        return -1;
+    }
+
+    _pins_set();
+    int8_t radio_id = rf_device_register();
+    if (radio_id < 0) {
+        _pins_clear();
+        rf = NULL;
+    }
+
+    rf_if_unlock();
+    return radio_id;
+}
+
+void NanostackRfPhyMcr20a::rf_unregister()
+{
+    rf_if_lock();
+
+    if (rf != this) {
+        rf_if_unlock();
+        return;
+    }
+
+    rf_device_unregister();
+    rf = NULL;
+    _pins_clear();
+
+    rf_if_unlock();
+}
+
+void NanostackRfPhyMcr20a::get_mac_address(uint8_t *mac)
+{
+    rf_if_lock();
+
+    memcpy((void*)mac, (void*)MAC_address, sizeof(MAC_address));
+
+    rf_if_unlock();
+}
+
+void NanostackRfPhyMcr20a::set_mac_address(uint8_t *mac)
+{
+    rf_if_lock();
+
+    if (NULL != rf) {
+        error("NanostackRfPhyAtmel cannot change mac address when running");
+        rf_if_unlock();
+        return;
+    }
+    memcpy((void*)MAC_address, (void*)mac, sizeof(MAC_address));
+
+    rf_if_unlock();
+}
+
+void NanostackRfPhyMcr20a::_pins_set()
+{
+    spi = &_spi;
+    cs = &_rf_cs;
+    rst = &_rf_rst;
+    irq = &_rf_irq;
+    irq_pin = &_rf_irq_pin;
+}
+
+void NanostackRfPhyMcr20a::_pins_clear()
+{
+    spi = NULL;
+    cs = NULL;
+    rst = NULL;
+    irq = NULL;
+    irq_pin = NULL;
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/mcr20a-rf-driver/source/XcvrSpi.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/mcr20a-rf-driver/source/XcvrSpi.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,89 @@
+/*!
+* Copyright (c) 2015, Freescale Semiconductor, Inc.
+* All rights reserved.
+*
+* \file XcvrSpi.h
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*
+* o Redistributions of source code must retain the above copyright notice, this list
+*   of conditions and the following disclaimer.
+*
+* o Redistributions in binary form must reproduce the above copyright notice, this
+*   list of conditions and the following disclaimer in the documentation and/or
+*   other materials provided with the distribution.
+*
+* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+*   contributors may be used to endorse or promote products derived from this
+*   software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __XCVR_SPI_H__
+#define __XCVR_SPI_H__
+
+
+/*****************************************************************************
+ *                               INCLUDED HEADERS                            *
+ *---------------------------------------------------------------------------*
+ * Add to this section all the headers that this module needs to include.    *
+ * Note that it is not a good practice to include header files into header   *
+ * files, so use this section only if there is no other better solution.     *
+ *---------------------------------------------------------------------------*
+ *****************************************************************************/
+ 
+
+/*****************************************************************************
+ *                             PUBLIC MACROS                                 *
+ *---------------------------------------------------------------------------*
+ * Add to this section all the access macros, registers mappings, bit access *
+ * macros, masks, flags etc ...
+ *---------------------------------------------------------------------------*
+ *****************************************************************************/
+#define gXcvrSpiInstance_c              0
+
+/*****************************************************************************
+ *                            PUBLIC FUNCTIONS                               *
+ *---------------------------------------------------------------------------*
+ * Add to this section all the global functions prototype preceded (as a     *
+ * good practice) by the keyword 'extern'                                    *
+ *---------------------------------------------------------------------------*
+ *****************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+
+void RF_RST_Set(int state);
+void RF_CS_Set(int state);
+void RF_IRQ_Init(void);
+void RF_IRQ_Disable(void);
+void RF_IRQ_Enable(void);
+uint8_t RF_isIRQ_Pending(void);
+
+void gXcvrAssertCS_d(void);
+void gXcvrDeassertCS_d(void);
+
+void xcvr_spi_init(uint32_t instance);
+void xcvr_spi_configure_speed(uint32_t instance, uint32_t freq);
+void xcvr_spi_transfer(uint32_t instance,
+                         uint8_t * sendBuffer,
+                         uint8_t * receiveBuffer,
+                         uint32_t transferByteCount);
+                         
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+
+#endif /* __XCVR_SPI_H__ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/stm-spirit1-rf-driver/#bbde15ee85d0c3b83864099c2659ad701a0325e7
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/FETCH_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/FETCH_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+bbde15ee85d0c3b83864099c2659ad701a0325e7		branch 'master' of https://github.com/ARMmbed/stm-spirit1-rf-driver
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/ORIG_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/ORIG_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+bbde15ee85d0c3b83864099c2659ad701a0325e7
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/config
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/config	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/stm-spirit1-rf-driver/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/description
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/description	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/hooks/applypatch-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/applypatch-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/hooks/commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/hooks/post-update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/post-update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-applypatch.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-applypatch.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-commit.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-commit.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-rebase.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-rebase.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/hooks/prepare-commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/prepare-commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/hooks/update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/index
Binary file easy-connect/stm-spirit1-rf-driver/.git/index has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/info/exclude
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/info/exclude	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,25 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/logs/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/logs/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 bbde15ee85d0c3b83864099c2659ad701a0325e7 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036529 +0000	clone: from https://github.com/ARMmbed/stm-spirit1-rf-driver/
+bbde15ee85d0c3b83864099c2659ad701a0325e7 bbde15ee85d0c3b83864099c2659ad701a0325e7 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036530 +0000	checkout: moving from master to bbde15ee85d0c3b83864099c2659ad701a0325e7
+bbde15ee85d0c3b83864099c2659ad701a0325e7 bbde15ee85d0c3b83864099c2659ad701a0325e7 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036530 +0000	checkout: moving from bbde15ee85d0c3b83864099c2659ad701a0325e7 to master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/logs/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/logs/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 bbde15ee85d0c3b83864099c2659ad701a0325e7 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036529 +0000	clone: from https://github.com/ARMmbed/stm-spirit1-rf-driver/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/logs/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/logs/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 bbde15ee85d0c3b83864099c2659ad701a0325e7 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036529 +0000	clone: from https://github.com/ARMmbed/stm-spirit1-rf-driver/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-54cd72b06384ef3c69fe7a53d28e1b53ffe0b4ce.idx
Binary file easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-54cd72b06384ef3c69fe7a53d28e1b53ffe0b4ce.idx has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-54cd72b06384ef3c69fe7a53d28e1b53ffe0b4ce.pack
Binary file easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-54cd72b06384ef3c69fe7a53d28e1b53ffe0b4ce.pack has changed
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/packed-refs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/packed-refs	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,2 @@
+# pack-refs with: peeled 
+bbde15ee85d0c3b83864099c2659ad701a0325e7 refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+bbde15ee85d0c3b83864099c2659ad701a0325e7
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.git/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.git/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.gitignore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.gitignore	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,6 @@
+BUILD
+.mbed
+projectfiles
+*.py*
+RCS
+atmel-rf-driver
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/.meta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/.meta	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,12 @@
+# Prototype RF Driver for STM Sub-1 GHz RF Expansion Boards based on the SPSGRF-868 Module for STM32 Nucleo #
+
+Currently supported boards:
+ * [X-NUCLEO-IDS01A4](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-connect-hw/x-nucleo-ids01a4.html)
+
+**Note**, in order to use expansion board `X-NUCLEO-IDS01A4` in mbed you need to perform the following HW modifications on the board:
+ * **Un**mount resistor `R4`
+ * **Mount** resistor `R7`
+ 
+Furthermore, on some Nucleo development boards (e.g. the [NUCLEO_F429ZI](https://developer.mbed.org/platforms/ST-Nucleo-F429ZI/)), in order to be able to use Ethernet together with these Sub-1 GHz RF expansion boards, you need to compile this driver with macro `SPIRIT1_SPI_MOSI=PB_5` defined, while the development board typically requires some HW modification as e.g. described [here](https://github.com/ARMmbed/sal-nanostack-driver-stm32-eth)! 
+
+This driver is used with 6LoWPAN stack.
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/mbed_lib.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/mbed_lib.json	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,7 @@
+{
+    "name": "spirit1",
+    "config": {
+	"mac-address": "{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}"
+    },
+    "macros": ["USE_STM32F4XX_NUCLEO", "X_NUCLEO_IDS01A4", "SPIRIT_USE_FULL_ASSERT"]
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/NanostackRfPhySpirit1.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/NanostackRfPhySpirit1.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,802 @@
+#include "NanostackRfPhySpirit1.h"
+#include "SimpleSpirit1.h"
+#include "nanostack/platform/arm_hal_phy.h"
+#include "platform/arm_hal_interrupt.h"
+
+#include "mbed_trace.h"
+#define TRACE_GROUP  "SPIRIT"
+
+/* Define beyond macro if you want to perform heavy debug tracing also in IRQ context */
+// #define HEAVY_TRACING
+
+static phy_device_driver_s device_driver;
+static int8_t rf_radio_driver_id = -1;
+
+const phy_rf_channel_configuration_s phy_subghz = {868000000, 1000000, 250000, 11, M_GFSK};
+
+static phy_device_channel_page_s phy_channel_pages[] = {
+    {CHANNEL_PAGE_2, &phy_subghz},
+    {CHANNEL_PAGE_0, NULL}
+};
+
+static uint8_t tx_sequence = 0xff;
+static uint8_t mac_tx_handle = 0;
+
+static SimpleSpirit1 *rf_device = NULL;
+static uint8_t rf_rx_buf[MAX_PACKET_LEN];
+
+static uint16_t stored_short_adr;
+static uint16_t stored_pan_id;
+static uint8_t stored_mac_address[8] = MBED_CONF_SPIRIT1_MAC_ADDRESS;
+
+#define RF_SIG_ACK_NEEDED (1<<0)
+#define RF_SIG_CB_TX_DONE (1<<1)
+#define RF_SIG_CB_RX_RCVD (1<<2)
+static Thread rf_ack_sender(osPriorityRealtime);
+static volatile uint8_t rf_rx_sequence;
+static volatile bool rf_ack_sent = false;
+
+/* MAC frame helper macros */
+#define MAC_FCF_FRAME_TYPE_MASK         0x0007
+#define MAC_FCF_FRAME_TYPE_SHIFT        0
+#define MAC_FCF_SECURITY_BIT_MASK       0x0008
+#define MAC_FCF_SECURITY_BIT_SHIFT      3
+#define MAC_FCF_PENDING_BIT_MASK        0x0010
+#define MAC_FCF_PENDING_BIT_SHIFT       4
+#define MAC_FCF_ACK_REQ_BIT_MASK        0x0020
+#define MAC_FCF_ACK_REQ_BIT_SHIFT       5
+#define MAC_FCF_INTRA_PANID_MASK        0x0040
+#define MAC_FCF_INTRA_PANID_SHIFT       6
+#define MAC_FCF_DST_ADDR_MASK           0x0c00
+#define MAC_FCF_DST_ADDR_SHIFT          10
+#define MAC_FCF_VERSION_MASK            0x3000
+#define MAC_FCF_VERSION_SHIFT           12
+#define MAC_FCF_SRC_ADDR_MASK           0xc000
+#define MAC_FCF_SRC_ADDR_SHIFT          14
+
+/* MAC supported frame types */
+#define FC_BEACON_FRAME         0x00
+#define FC_DATA_FRAME           0x01
+#define FC_ACK_FRAME            0x02
+#define FC_CMD_FRAME            0x03
+
+static void rf_if_lock(void)
+{
+    platform_enter_critical();
+}
+
+static void rf_if_unlock(void)
+{
+    platform_exit_critical();
+}
+
+static inline uint16_t rf_read_16_bit(uint8_t *data_ptr) { // little-endian
+    uint16_t ret;
+
+    ret = ((uint16_t)data_ptr[0]) + (((uint16_t)data_ptr[1]) << 8);
+    return ret;
+}
+
+static int8_t rf_trigger_send(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol)
+{
+#ifndef NDEBUG
+    debug_if(!(data_length >= 3), "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+    /* Give 'rf_ack_sender' a better chance to run */
+    Thread::yield();
+
+    /* Get Lock */
+    rf_if_lock();
+
+    /*Check if transmitter is busy*/
+    if(rf_device->is_receiving()) { /* betzw - WAS: (rf_device->channel_clear() != 0)), do NOT use this but rather study and enable automatic CCA */
+	tr_debug("%s (%d)", __func__, __LINE__);
+
+	/* Release Lock */
+	rf_if_unlock();
+
+	/*Return busy*/
+	return -1;
+    } else {
+#ifdef HEAVY_TRACING
+	uint16_t fcf = rf_read_16_bit(data_ptr);
+	uint16_t need_ack;
+
+	/*Check if transmitted data needs to be acked*/
+	if((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT)
+	    need_ack = 1;
+	else
+	    need_ack = 0;
+#endif
+
+	/*Store the sequence number for ACK handling*/
+	tx_sequence = *(data_ptr + 2);
+
+	/*Store TX handle*/
+	mac_tx_handle = tx_handle;
+
+#ifdef HEAVY_TRACING
+	tr_info("%s (%d), len=%d, tx_handle=%x, tx_seq=%x, need_ack=%d (%x:%x, %x:%x, %x:%x, %x:%x)", __func__, __LINE__,
+		data_length, tx_handle, tx_sequence, need_ack,
+		data_ptr[3], data_ptr[4], data_ptr[5], data_ptr[6],
+		data_ptr[7], data_ptr[8], data_ptr[9], data_ptr[10]);
+#endif
+
+	/*Send the packet*/
+	rf_device->send(data_ptr, data_length);
+
+	/* Release Lock */
+	rf_if_unlock();
+    }
+
+    /*Return success*/
+    return 0;
+}
+
+static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
+{
+    int8_t ret_val = 0;
+    switch (new_state)
+    {
+	/*Reset PHY driver and set to idle*/
+    case PHY_INTERFACE_RESET:
+	tr_debug("%s (%d)", __func__, __LINE__);
+	rf_device->reset_board();
+	break;
+	/*Disable PHY Interface driver*/
+    case PHY_INTERFACE_DOWN:
+	tr_debug("%s (%d)", __func__, __LINE__);
+	ret_val = rf_device->off();
+	if(ret_val != 0) ret_val = -1;
+	break;
+	/*Enable PHY Interface driver*/
+    case PHY_INTERFACE_UP:
+	ret_val = rf_device->on();
+	if(ret_val != 0) {
+	    tr_debug("%s (%d)", __func__, __LINE__);
+	    ret_val = -1;
+	    break;
+	}
+	tr_debug("%s (%d) - channel: %d", __func__, __LINE__, (int)rf_channel);
+	rf_device->set_channel(rf_channel);
+	break;
+	/*Enable wireless interface ED scan mode*/
+    case PHY_INTERFACE_RX_ENERGY_STATE:
+	tr_debug("%s (%d)", __func__, __LINE__);
+	break;
+	/*Enable Sniffer state*/
+    case PHY_INTERFACE_SNIFFER_STATE:
+	// TODO - if we really need this - WAS: rf_setup_sniffer(rf_channel);
+	tr_debug("%s (%d)", __func__, __LINE__);
+	ret_val = -1;
+	break;
+    default:
+	tr_debug("%s (%d)", __func__, __LINE__);
+	break;
+    }
+    return ret_val;
+}
+
+static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
+{
+    switch (extension_type)
+    {
+	/*Control MAC pending bit for Indirect data transmission*/
+    case PHY_EXTENSION_CTRL_PENDING_BIT:
+	tr_debug("%s (%d)", __func__, __LINE__);
+	break;
+
+	/*Return frame pending status*/
+    case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
+	tr_debug("%s (%d)", __func__, __LINE__);
+	*data_ptr = 0;
+	break;
+
+	/*Set channel, used for setting channel for energy scan*/
+    case PHY_EXTENSION_SET_CHANNEL:
+	tr_debug("%s (%d)", __func__, __LINE__);
+	break;
+
+	/*Read energy on the channel*/
+    case PHY_EXTENSION_READ_CHANNEL_ENERGY:
+	// TODO: *data_ptr = rf_get_channel_energy();
+	tr_debug("%s (%d)", __func__, __LINE__);
+	*data_ptr = (int8_t)rf_device->get_last_rssi_dbm();
+	break;
+
+	/*Read status of the link*/
+    case PHY_EXTENSION_READ_LINK_STATUS:
+	// TODO: *data_ptr = rf_get_link_status();
+	tr_debug("%s (%d)", __func__, __LINE__);
+	*data_ptr = rf_device->get_last_sqi(); // use SQI as link quality
+	break;
+
+    default:
+	tr_debug("%s (%d)", __func__, __LINE__);
+	break;
+    }
+    return 0;
+}
+
+static inline void rf_set_mac_address(uint8_t *ptr) {
+    tr_debug("%s (%d), adr0=%x, adr1=%x, adr2=%x, adr3=%x, adr4=%x, adr5=%x, adr6=%x, adr7=%x",
+	     __func__, __LINE__,
+	     ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
+    for(int i = 0; i < 8; i++) {
+	stored_mac_address[i] = ptr[i];
+    }
+}
+
+static inline void rf_get_mac_address(uint8_t *ptr) {
+    for(int i = 0; i < 8; i++) {
+	ptr[i] = stored_mac_address[i];
+    }
+    tr_debug("%s (%d), adr0=%x, adr1=%x, adr2=%x, adr3=%x, adr4=%x, adr5=%x, adr6=%x, adr7=%x",
+	     __func__, __LINE__,
+	     ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
+}
+
+static inline void rf_set_short_adr(uint8_t *ptr) {
+    stored_short_adr = (ptr[0] << 8) + ptr[1]; // big-endian
+    tr_debug("%s (%d), adr0=%x, adr1=%x, val=%d",
+	     __func__, __LINE__,
+	     ptr[0], ptr[1], stored_short_adr);
+}
+
+static inline void rf_set_pan_id(uint8_t *ptr) {
+    stored_pan_id = (ptr[0] << 8) + ptr[1]; // big-endian
+    tr_debug("%s (%d), adr0=%x, adr1=%x, val=%d",
+	     __func__, __LINE__,
+	     ptr[0], ptr[1], stored_pan_id);
+}
+
+static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
+{
+    switch (address_type)
+    {
+	/*Set 48-bit address*/
+    case PHY_MAC_48BIT:
+	/* Not used in this example */
+	// betzw - WAS: rf_set_mac_48bit(address_ptr);
+	break;
+	/*Set 64-bit address*/
+    case PHY_MAC_64BIT:
+	rf_set_mac_address(address_ptr);
+	break;
+	/*Set 16-bit address*/
+    case PHY_MAC_16BIT:
+	rf_set_short_adr(address_ptr);
+	break;
+	/*Set PAN Id*/
+    case PHY_MAC_PANID:
+	rf_set_pan_id(address_ptr);
+	break;
+    }
+
+    return 0;
+}
+
+/* Note: we are in IRQ context */
+static inline void rf_send_signal(int32_t signal) {
+#ifdef HEAVY_TRACING
+	tr_info("%s (%d): %d", __func__, __LINE__, signal);
+#endif
+    rf_ack_sender.signal_set(signal);
+}
+
+static phy_link_tx_status_e phy_status;
+/* Note: we are in IRQ context */
+static void rf_handle_ack(uint8_t seq_number)
+{
+    /*Received ACK sequence must be equal with transmitted packet sequence*/
+    if(tx_sequence == seq_number)
+    {
+#ifdef HEAVY_TRACING
+	tr_info("%s (%d)", __func__, __LINE__);
+#endif
+
+	/*Call PHY TX Done API*/
+	if(device_driver.phy_tx_done_cb){
+	    phy_status = PHY_LINK_TX_DONE;
+	    rf_send_signal(RF_SIG_CB_TX_DONE);
+	}
+    } else {
+#ifdef HEAVY_TRACING
+	tr_info("%s (%d)", __func__, __LINE__);
+#endif
+    }
+}
+
+/* Note: we are in IRQ context */
+static inline bool rf_check_mac_address(uint8_t *dest) {
+    for(int i = 0; i < 8; i++) {
+	if(dest[i] != stored_mac_address[7-i]) return false;
+    }
+    return true;
+}
+
+/* Note: we are in IRQ context */
+/* Returns true if packet should be accepted */
+static bool rf_check_destination(int len, uint8_t *ack_requested) {
+    uint8_t frame_type;
+    uint16_t dst_pan_id;
+    uint16_t dst_short_adr;
+    uint8_t dst_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
+    uint8_t src_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
+    uint8_t min_size = 3; // FCF & SeqNr
+    bool ret = false;
+#if defined(HEAVY_TRACING)
+    bool panid_compr = false;
+#endif
+
+    if(len < 3) {
+	tr_debug("%s (%d)", __func__, __LINE__);
+	return false;
+    }
+
+    uint16_t fcf = rf_read_16_bit(rf_rx_buf);
+    frame_type = ((fcf & MAC_FCF_FRAME_TYPE_MASK) >> MAC_FCF_FRAME_TYPE_SHIFT);
+    (*ack_requested) = ((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT);
+    dst_addr_mode = ((fcf & MAC_FCF_DST_ADDR_MASK) >> MAC_FCF_DST_ADDR_SHIFT);
+    src_addr_mode = ((fcf & MAC_FCF_SRC_ADDR_MASK) >> MAC_FCF_SRC_ADDR_SHIFT);
+#if defined(HEAVY_TRACING)
+    panid_compr = ((fcf & MAC_FCF_INTRA_PANID_MASK) >> MAC_FCF_INTRA_PANID_SHIFT);
+#endif
+
+#ifdef HEAVY_TRACING
+    tr_info("%s (%d): len=%d, ftype=%x, snr=%x, ack=%d, dst=%x, src=%x, intra=%d", __func__, __LINE__, len, frame_type,
+	    rf_rx_buf[2], (*ack_requested), dst_addr_mode, src_addr_mode, panid_compr);
+#endif
+
+    if(frame_type == FC_ACK_FRAME) { // betzw: we support up to two different forms of ACK frames!
+	if((len == 3) && (dst_addr_mode == 0x0) && (src_addr_mode == 0x0)) {
+	    ret = true;
+	}
+
+#ifdef HEAVY_TRACING
+	tr_info("%s (%d): ret=%d", __func__, __LINE__, ret);
+#endif
+	(*ack_requested) = 0;  // Never acknowledge ACK frames
+	return ret;
+    }
+
+    switch(dst_addr_mode) {
+    case 0x00:
+	ret = true; // no check possible;
+	break;
+    case 0x02:
+	min_size += 4; // pan id + short dest adr
+
+	if(len < 5) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    return false;
+	}
+
+	dst_pan_id = rf_read_16_bit(&rf_rx_buf[3]);
+	if(dst_pan_id == 0xFFFF) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    ret = true;
+	    break;
+	}
+
+	if(dst_pan_id == stored_pan_id) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    ret = true;
+	    break;
+	} else {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d): %d!=%d", __func__, __LINE__, dst_pan_id, stored_pan_id);
+#endif
+	}
+
+	if(len < 7) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    return false;
+	}
+
+	dst_short_adr = rf_read_16_bit(&rf_rx_buf[5]);
+	if(dst_short_adr == stored_short_adr) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    ret = true;
+	    break;
+	} else {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d): %d!=%d", __func__, __LINE__, dst_short_adr, stored_short_adr);
+#endif
+	}
+	break;
+    case 0x03:
+	min_size += 10; // pan id + dest mac addr
+
+	if(len < 5) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    return false;
+	}
+
+	dst_pan_id = rf_read_16_bit(&rf_rx_buf[3]);
+	if(dst_pan_id == 0xFFFF) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    ret = true;
+	    break;
+	}
+
+	if(dst_pan_id == stored_pan_id) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    ret = true;
+	    break;
+	}
+
+	if(len < 13) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    return false;
+	}
+
+	ret = rf_check_mac_address(&rf_rx_buf[5]);
+	break;
+    default:
+	/* not supported */
+#ifdef HEAVY_TRACING
+	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	return false;
+    }
+
+    if(ret && (*ack_requested)) {
+	rf_rx_sequence = rf_rx_buf[2];
+    }
+
+#ifdef HEAVY_TRACING
+    tr_info("%s (%d), ret=%d, ack=%d", __func__, __LINE__, ret, (*ack_requested));
+#endif
+    return ret;
+}
+
+static uint16_t rf_buffer_len = 0;
+static uint8_t rf_sqi;
+static int8_t rf_rssi;
+/* Note: we are in IRQ context */
+static inline void rf_handle_rx_end(void)
+{
+    uint8_t ack_requested = 0;
+
+    /* Get received data */
+    rf_buffer_len = rf_device->read(rf_rx_buf, MAX_PACKET_LEN);
+    if(!rf_buffer_len)
+	return;
+
+#ifdef HEAVY_TRACING
+    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+
+    /* Check if packet should be accepted */
+    if(!rf_check_destination(rf_buffer_len, &ack_requested)) {
+#ifdef HEAVY_TRACING
+	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	return;
+    }
+
+    /* If waiting for ACK, check here if the packet is an ACK to a message previously sent */
+    uint16_t fcf = rf_read_16_bit(rf_rx_buf);
+    if(((fcf & MAC_FCF_FRAME_TYPE_MASK) >> MAC_FCF_FRAME_TYPE_SHIFT) == FC_ACK_FRAME) {
+	/*Send sequence number in ACK handler*/
+#ifdef HEAVY_TRACING
+	tr_debug("%s (%d), len=%u", __func__, __LINE__, (unsigned int)rf_buffer_len);
+#endif
+	rf_handle_ack(rf_rx_buf[2]);
+	return;
+    }
+
+    /* Kick off ACK sending */
+    if(ack_requested) {
+#ifdef HEAVY_TRACING
+	tr_debug("%s (%d), len=%u", __func__, __LINE__, (unsigned int)rf_buffer_len);
+#endif
+	rf_send_signal(RF_SIG_ACK_NEEDED);
+    }
+
+    /* Get link information */
+    rf_rssi = (int8_t)rf_device->get_last_rssi_dbm();
+    rf_sqi = (uint8_t)rf_device->get_last_sqi(); // use SQI as link quality
+
+    /* Note: Checksum of the packet must be checked and removed before entering here */
+    /* TODO - betzw: what to do? */
+
+#ifdef HEAVY_TRACING
+    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+
+    /* Send received data and link information to the network stack */
+    if( device_driver.phy_rx_cb ){
+	rf_send_signal(RF_SIG_CB_RX_RCVD);
+    }
+}
+
+/* Note: we are in IRQ context */
+static inline void rf_handle_tx_end(void)
+{
+    /* Check if this is an ACK sending which is still pending */
+    if(rf_ack_sent) {
+	rf_ack_sent = false;
+#ifdef HEAVY_TRACING
+	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	return; // no need to inform stack
+    }
+
+    /*Call PHY TX Done API*/
+    if(device_driver.phy_tx_done_cb){
+	phy_status = PHY_LINK_TX_SUCCESS;
+	rf_send_signal(RF_SIG_CB_TX_DONE);
+    }
+}
+
+/* Note: we are in IRQ context */
+static inline void rf_handle_tx_err(void) {
+    /*Call PHY TX Done API*/
+    if(device_driver.phy_tx_done_cb){
+	phy_status = PHY_LINK_TX_FAIL;
+	rf_send_signal(RF_SIG_CB_TX_DONE);
+    }
+}
+
+/* Note: we are in IRQ context */
+static void rf_callback_func(int event) {
+    switch(event) {
+    case SimpleSpirit1::RX_DONE:
+	rf_handle_rx_end();
+	break;
+    case SimpleSpirit1::TX_DONE:
+	rf_handle_tx_end();
+	break;
+    case SimpleSpirit1::TX_ERR:
+#ifdef HEAVY_TRACING
+	tr_debug("%s (%d): TX_ERR!!!", __func__, __LINE__);
+#endif
+	rf_handle_tx_err();
+	break;
+    }
+}
+
+static void rf_ack_loop(void) {
+    static uint16_t buffer[2] = {
+	(FC_ACK_FRAME << MAC_FCF_FRAME_TYPE_SHIFT),
+	0x0
+    };
+
+    tr_debug("%s (%d)", __func__, __LINE__);
+
+    do {
+	/* Wait for signal */
+	osEvent event = rf_ack_sender.signal_wait(0);
+
+	if(event.status != osEventSignal) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	    continue;
+	}
+
+	int32_t signals = event.value.signals;
+
+#ifdef HEAVY_TRACING
+    	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+
+    	/* Get Lock */
+	rf_if_lock();
+
+	if(signals & RF_SIG_ACK_NEEDED) {
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+
+	    /* Prepare payload */
+	    uint8_t *ptr = (uint8_t*)&buffer[1];
+	    ptr[0] = rf_rx_sequence;   // Sequence number
+
+	    /* Wait for device not receiving */
+	    while(rf_device->is_receiving()) {
+#ifdef HEAVY_TRACING
+		tr_info("%s (%d)", __func__, __LINE__);
+#endif
+		wait_us(10);
+	    }
+
+#ifdef HEAVY_TRACING
+	    tr_debug("%s (%d), hdr=%x, nr=%x", __func__, __LINE__, buffer[0], ptr[0]);
+#endif
+
+	    /* Set information that we have sent an ACK */
+	    rf_ack_sent = true;
+
+	    /*Send the packet*/
+	    rf_device->send((uint8_t*)buffer, 3);
+
+	    tr_debug("%s (%d), hdr=%x, nr=%x", __func__, __LINE__, buffer[0], ptr[0]);
+	}
+
+	if(signals & RF_SIG_CB_TX_DONE) {
+	    device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, phy_status, 0, 0);
+#ifdef HEAVY_TRACING
+    	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	}
+
+	if(signals & RF_SIG_CB_RX_RCVD) {
+	    device_driver.phy_rx_cb(rf_rx_buf, rf_buffer_len, rf_sqi, rf_rssi, rf_radio_driver_id);
+#ifdef HEAVY_TRACING
+    	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+	}
+
+	/* Release Lock */
+	rf_if_unlock();
+
+#ifdef HEAVY_TRACING
+	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+    } while(true);
+}
+
+void NanostackRfPhySpirit1::rf_init(void) {
+#ifndef NDEBUG
+    osStatus ret;
+#endif
+
+    if(rf_device == NULL) {
+	rf_device = &SimpleSpirit1::CreateInstance(_spi_mosi, _spi_miso, _spi_sclk, _dev_irq, _dev_cs, _dev_sdn, _brd_led);
+	rf_device->attach_irq_callback(rf_callback_func);
+
+#ifndef NDEBUG
+	ret =
+#endif
+	    rf_ack_sender.start(rf_ack_loop);
+
+#ifndef NDEBUG
+	debug_if(!(ret == osOK), "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+    }
+}
+
+NanostackRfPhySpirit1::NanostackRfPhySpirit1(PinName spi_mosi, PinName spi_miso, PinName spi_sclk,
+					     PinName dev_irq,  PinName dev_cs, PinName dev_sdn, PinName brd_led) :
+    _spi_mosi(spi_mosi),
+    _spi_miso(spi_miso),
+    _spi_sclk(spi_sclk),
+    _dev_irq(dev_irq),
+    _dev_cs(dev_cs),
+    _dev_sdn(dev_sdn),
+    _brd_led(brd_led)
+{
+    /* Nothing to do */
+    tr_debug("%s (%d)", __func__, __LINE__);
+}
+
+NanostackRfPhySpirit1::~NanostackRfPhySpirit1()
+{
+    /* Nothing to do */
+    tr_debug("%s (%d)", __func__, __LINE__);
+}
+
+int8_t NanostackRfPhySpirit1::rf_register()
+{
+    tr_debug("%s (%d)", __func__, __LINE__);
+
+    /* Get Lock */
+    rf_if_lock();
+
+    /* Do some initialization */
+    rf_init();
+
+    /* Set pointer to MAC address */
+    device_driver.PHY_MAC = stored_mac_address;
+
+    /* Set driver Name */
+    device_driver.driver_description = (char*)"Spirit1 Sub-GHz RF";
+
+    /*Type of RF PHY is SubGHz*/
+    device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
+
+    /*Maximum size of payload*/
+    device_driver.phy_MTU = MAX_PACKET_LEN;
+
+    /*No header in PHY*/
+    device_driver.phy_header_length = 0;
+
+    /*No tail in PHY*/
+    device_driver.phy_tail_length = 0;
+
+    /*Set up driver functions*/
+    device_driver.address_write = &rf_address_write;
+    device_driver.extension = &rf_extension;
+    device_driver.state_control = &rf_interface_state_control;
+    device_driver.tx = &rf_trigger_send;
+
+    /*Set supported channel pages*/
+    device_driver.phy_channel_pages = phy_channel_pages;
+
+    //Nullify rx/tx callbacks
+    device_driver.phy_rx_cb = NULL;
+    device_driver.phy_tx_done_cb = NULL;
+    device_driver.arm_net_virtual_rx_cb = NULL;
+    device_driver.arm_net_virtual_tx_cb = NULL;
+
+    /*Register device driver*/
+    rf_radio_driver_id = arm_net_phy_register(&device_driver);
+
+    /* Release Lock */
+    rf_if_unlock();
+
+    tr_debug("%s (%d)", __func__, __LINE__);
+    return rf_radio_driver_id;
+}
+
+void NanostackRfPhySpirit1::rf_unregister()
+{
+    tr_debug("%s (%d)", __func__, __LINE__);
+
+    /* Get Lock */
+    rf_if_lock();
+
+    if (rf_radio_driver_id >= 0) {
+        arm_net_phy_unregister(rf_radio_driver_id);
+        rf_radio_driver_id = -1;
+    }
+
+    /* Release Lock */
+    rf_if_unlock();
+}
+
+void NanostackRfPhySpirit1::get_mac_address(uint8_t *mac)
+{
+    tr_debug("%s (%d)", __func__, __LINE__);
+
+    /* Get Lock */
+    rf_if_lock();
+
+    if(rf_radio_driver_id >= 0) {
+	rf_get_mac_address(mac);
+    } else {
+        error("NanostackRfPhySpirit1 must be registered to read mac address");
+    }
+
+    /* Release Lock */
+    rf_if_unlock();
+}
+
+void NanostackRfPhySpirit1::set_mac_address(uint8_t *mac)
+{
+    tr_debug("%s (%d)", __func__, __LINE__);
+
+    /* Get Lock */
+    rf_if_lock();
+
+    if(rf_radio_driver_id < 0) {
+	rf_set_mac_address(mac);
+    } else {
+        error("NanostackRfPhySpirit1 cannot change mac address when running");
+    }
+
+    /* Release Lock */
+    rf_if_unlock();
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/SimpleSpirit1.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/SimpleSpirit1.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,615 @@
+/*** Mbed Includes ***/
+#include "SimpleSpirit1.h"
+#include "radio_spi.h"
+
+#define SPIRIT_GPIO_IRQ			(SPIRIT_GPIO_3)
+
+static uint16_t last_state;
+#define SPIRIT1_STATUS()		((last_state = (uint16_t)refresh_state()) & SPIRIT1_STATE_STATEBITS)
+
+#define XO_ON                   (0x1)
+
+#define BUSYWAIT_UNTIL(cond, millisecs)                                        					\
+		do {                                                                 					 		\
+			uint32_t start = us_ticker_read();                         							\
+			while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U));	\
+		} while(0)
+
+#define st_lib_spirit_irqs		SpiritIrqs
+
+#define STATE_TIMEOUT           (100)
+
+// betzw: switching force & back from standby is on some devices quite unstable
+#define USE_STANDBY_STATE
+
+/*** Class Implementation ***/
+/** Static Class Variables **/
+SimpleSpirit1 *SimpleSpirit1::_singleton = NULL;
+
+/** Constructor **/
+SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
+		PinName irq, PinName cs, PinName sdn,
+		PinName led) :
+    		_spi(mosi, miso, sclk),
+			_irq(irq),
+			_chip_select(cs),
+			_shut_down(sdn),
+			_led(led),
+			_current_irq_callback(),
+			_rx_receiving_timeout()
+{
+}
+
+/** Init Function **/
+void SimpleSpirit1::init() {
+	/* reset irq disable counter and irq callback & disable irq */
+	_nr_of_irq_disables = 0;
+	disable_spirit_irq();
+
+	/* unselect chip */
+	chip_unselect();
+
+	/* configure spi */
+	_spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
+	_spi.frequency(1000000); // 1MHz // betzw: heuristic value // betzw - NOTE: high frequencies lead to instability of Spirit1
+
+	/* install irq handler */
+	_irq.mode(PullUp);
+	_irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler));
+
+	/* init cube vars */
+	spirit_on = OFF;
+	last_rssi = 0 ; //MGR
+	last_sqi = 0 ;  //MGR
+
+	/* set frequencies */
+	radio_set_xtal_freq(XTAL_FREQUENCY);
+	mgmt_set_freq_base((uint32_t)BASE_FREQUENCY);
+
+	/* restart board */
+	enter_shutdown();
+	exit_shutdown();
+
+	/* soft core reset */
+	cmd_strobe(SPIRIT1_STROBE_SRES);
+
+	/* Configures the SPIRIT1 radio part */
+	SRadioInit x_radio_init = {
+			XTAL_OFFSET_PPM,
+			(uint32_t)BASE_FREQUENCY,
+			(uint32_t)CHANNEL_SPACE,
+			CHANNEL_NUMBER,
+			MODULATION_SELECT,
+			DATARATE,
+			(uint32_t)FREQ_DEVIATION,
+			(uint32_t)BANDWIDTH
+	};
+	radio_init(&x_radio_init);
+	radio_set_pa_level_dbm(0,POWER_DBM);
+	radio_set_pa_level_max_index(0);
+
+	/* Configures the SPIRIT1 packet handler part*/
+	PktBasicInit x_basic_init = {
+			PREAMBLE_LENGTH,
+			SYNC_LENGTH,
+			SYNC_WORD,
+			LENGTH_TYPE,
+			LENGTH_WIDTH,
+			CRC_MODE,
+			CONTROL_LENGTH,
+			EN_ADDRESS,
+			EN_FEC,
+			EN_WHITENING
+	};
+	pkt_basic_init(&x_basic_init);
+
+	/* Enable the following interrupt sources, routed to GPIO */
+	irq_de_init(NULL);
+	irq_clear_status();
+	irq_set_status(TX_DATA_SENT, S_ENABLE);
+	irq_set_status(RX_DATA_READY,S_ENABLE);
+	irq_set_status(RX_DATA_DISC, S_ENABLE);
+	irq_set_status(VALID_SYNC, S_ENABLE);
+	irq_set_status(TX_FIFO_ERROR, S_ENABLE);
+	irq_set_status(RX_FIFO_ERROR, S_ENABLE);
+#ifndef RX_FIFO_THR_WA
+	irq_set_status(TX_FIFO_ALMOST_EMPTY, S_ENABLE);
+	irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE);
+#endif // !RX_FIFO_THR_WA
+
+	/* Configure Spirit1 */
+	radio_persistent_rx(S_ENABLE);
+	qi_set_sqi_threshold(SQI_TH_0);
+	qi_sqi_check(S_ENABLE);
+	qi_set_rssi_threshold_dbm(CCA_THRESHOLD);
+	timer_set_rx_timeout_stop_condition(SQI_ABOVE_THRESHOLD);
+	timer_set_infinite_rx_timeout();
+	radio_afc_freeze_on_sync(S_ENABLE);
+	calibration_rco(S_ENABLE);
+
+	spirit_on = OFF;
+	CLEAR_TXBUF();
+	CLEAR_RXBUF();
+	_spirit_tx_started = false;
+	_is_receiving = false;
+
+	/* Configure the radio to route the IRQ signal to its GPIO 3 */
+	SGpioInit x_gpio_init = {
+			SPIRIT_GPIO_IRQ,
+			SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
+			SPIRIT_GPIO_DIG_OUT_IRQ
+	};
+	spirit_gpio_init(&x_gpio_init);
+
+	/* Setup CSMA/CA */
+	CsmaInit x_csma_init = {
+			S_ENABLE,         // enable persistent mode
+			TBIT_TIME_64,     // Tcca time
+			TCCA_TIME_3,      // Lcca length
+			3,                // max nr of backoffs (<8)
+			1,                // BU counter seed
+			8                 // BU prescaler
+	};
+	csma_ca_init(&x_csma_init);
+
+#ifdef USE_STANDBY_STATE
+	/* Puts the SPIRIT1 in STANDBY mode (125us -> rx/tx) */
+	cmd_strobe(SPIRIT1_STROBE_STANDBY);
+#endif // USE_STANDBY_STATE
+}
+
+static volatile int tx_fifo_remaining = 0;     // to be used in irq handler
+static volatile int tx_buffer_pos = 0;         // to be used in irq handler
+const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
+int SimpleSpirit1::send(const void *payload, unsigned int payload_len) {
+	/* Checks if the payload length is supported */
+	if(payload_len > MAX_PACKET_LEN) {
+		return RADIO_TX_ERR;
+	}
+
+	disable_spirit_irq();
+
+	BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+#ifndef NDEBUG
+	if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+		debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+	}
+#endif
+
+	/* Reset State to Ready */
+	set_ready_state();
+
+	cmd_strobe(SPIRIT1_STROBE_FTX); // flush TX FIFO buffer
+
+#ifndef NDEBUG
+	debug_if(!(linear_fifo_read_num_elements_tx_fifo() == 0), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+	pkt_basic_set_payload_length(payload_len); // set desired payload len
+
+	csma_ca_state(S_ENABLE); // enable CSMA/CA
+
+	/* Init buffer & number of bytes to be send */
+	tx_fifo_remaining = payload_len;
+	tx_fifo_buffer = (const uint8_t*)payload;
+
+	int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
+	int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
+
+	tx_fifo_remaining -= to_send;
+
+	/* Fill FIFO Buffer */
+	if(to_send > 0) {
+		spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
+	}
+
+	tx_buffer_pos = to_send;
+	_spirit_tx_started = true;
+
+	enable_spirit_irq();
+
+	/* Start transmitting */
+	cmd_strobe(SPIRIT1_STROBE_TX);
+
+	while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
+
+	BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
+#ifdef HEAVY_DEBUG
+	debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
+#endif
+
+	_spirit_tx_started = false; // in case of state timeout
+
+	csma_ca_state(S_DISABLE); // disable CSMA/CA
+
+	cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state
+
+	return RADIO_TX_OK;
+}
+
+/** Set Ready State **/
+void SimpleSpirit1::set_ready_state(void) {
+	uint16_t state;
+
+	disable_spirit_irq();
+
+	_spirit_tx_started = false;
+	_is_receiving = false;
+	stop_rx_timeout();
+
+	cmd_strobe(SPIRIT1_STROBE_FRX);
+	CLEAR_RXBUF();
+	CLEAR_TXBUF();
+
+	state = SPIRIT1_STATUS();
+	if(state == SPIRIT1_STATE_STANDBY) {
+		cmd_strobe(SPIRIT1_STROBE_READY);
+	} else if(state == SPIRIT1_STATE_RX) {
+		cmd_strobe(SPIRIT1_STROBE_SABORT);
+	} else if(state != SPIRIT1_STATE_READY) {
+#ifndef NDEBUG
+		debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, state>>1);
+#endif
+	}
+
+	BUSYWAIT_UNTIL((SPIRIT1_STATUS() == SPIRIT1_STATE_READY) && ((last_state & XO_ON) == XO_ON), STATE_TIMEOUT);
+	if(last_state != (SPIRIT1_STATE_READY | XO_ON)) {
+		error("\n\rSpirit1: failed to become ready (%x) => pls. reset!\n\r", last_state);
+		enable_spirit_irq();
+		return;
+	}
+
+	irq_clear_status();
+
+	enable_spirit_irq();
+}
+
+int SimpleSpirit1::off(void) {
+	if(spirit_on == ON) {
+		/* Disables the mcu to get IRQ from the SPIRIT1 */
+		disable_spirit_irq();
+
+		/* first stop rx/tx */
+		set_ready_state();
+
+#ifdef USE_STANDBY_STATE
+		/* Puts the SPIRIT1 in STANDBY */
+		cmd_strobe(SPIRIT1_STROBE_STANDBY);
+		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY, STATE_TIMEOUT);
+		if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_STANDBY) {
+			error("\n\rSpirit1: failed to enter standby (%x)\n\r", last_state>>1);
+			return 1;
+		}
+#endif // USE_STANDBY_STATE
+
+		spirit_on = OFF;
+		_nr_of_irq_disables = 1;
+	}
+	return 0;
+}
+
+int SimpleSpirit1::on(void) {
+	if(spirit_on == OFF) {
+		set_ready_state();
+
+		/* now we go to Rx */
+		cmd_strobe(SPIRIT1_STROBE_RX);
+
+		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+		if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+			error("\n\rSpirit1: failed to enter rx (%x) => retry\n\r", last_state>>1);
+		}
+
+		/* Enables the mcu to get IRQ from the SPIRIT1 */
+		spirit_on = ON;
+#ifndef NDEBUG
+		debug_if(!(_nr_of_irq_disables == 1), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+		enable_spirit_irq();
+	}
+
+#ifndef NDEBUG
+	if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+		debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+	}
+#endif
+
+	return 0;
+}
+
+uint8_t SimpleSpirit1::refresh_state(void) {
+	uint8_t mcstate;
+
+	SpiritSpiReadRegisters(MC_STATE0_BASE, 1, &mcstate);
+
+	return mcstate;
+}
+
+int SimpleSpirit1::read(void *buf, unsigned int bufsize)
+{
+	disable_spirit_irq();
+
+	/* Checks if the RX buffer is empty */
+	if(IS_RXBUF_EMPTY()) {
+#ifndef NDEBUG
+		debug("\n\rBuffer is empty\n\r");
+#endif
+		set_ready_state();
+
+		cmd_strobe(SPIRIT1_STROBE_RX);
+		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+		enable_spirit_irq();
+		return 0;
+	}
+
+	if(bufsize < spirit_rx_len) {
+		enable_spirit_irq();
+
+		/* If buf has the correct size */
+#ifndef NDEBUG
+		debug("\n\rTOO SMALL BUF\n\r");
+#endif
+		return 0;
+	} else {
+		/* Copies the packet received */
+		memcpy(buf, spirit_rx_buf, spirit_rx_len);
+
+		bufsize = spirit_rx_len;
+		CLEAR_RXBUF();
+
+		enable_spirit_irq();
+
+		return bufsize;
+	}
+
+}
+
+int SimpleSpirit1::channel_clear(void)
+{
+	float rssi_value;
+	/* Local variable used to memorize the SPIRIT1 state */
+	uint8_t spirit_state = ON;
+
+	if(spirit_on == OFF) {
+		/* Wakes up the SPIRIT1 */
+		on();
+		spirit_state = OFF;
+	}
+
+#ifndef NDEBUG
+	if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+		debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+	}
+#endif
+
+	disable_spirit_irq();
+
+	/* Reset State to Ready */
+	set_ready_state();
+
+	/* Stores the RSSI value */
+	rssi_value = qi_get_rssi_dbm();
+
+	enable_spirit_irq();
+
+	/* Puts the SPIRIT1 in its previous state */
+	if(spirit_state==OFF) {
+		off();
+#ifndef NDEBUG
+#ifdef USE_STANDBY_STATE
+		if(SPIRIT1_STATUS() != SPIRIT1_STATE_STANDBY) {
+#else
+		if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) {
+#endif
+			debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+		}
+#endif
+	} else {
+		disable_spirit_irq();
+
+        set_ready_state();
+
+		cmd_strobe(SPIRIT1_STROBE_RX);
+		BUSYWAIT_UNTIL(SPIRIT1_STATUS() == SPIRIT1_STATE_RX, STATE_TIMEOUT);
+		if((last_state & SPIRIT1_STATE_STATEBITS) != SPIRIT1_STATE_RX) {
+			error("\n\rSpirit1: (#2) failed to enter rx (%x) => retry\n\r", last_state>>1);
+		}
+
+		enable_spirit_irq();
+
+#ifndef NDEBUG
+		if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) {
+			debug("\n\rAssert failed in: %s (%d): state=%x\n\r", __func__, __LINE__, last_state>>1);
+		}
+#endif
+	}
+
+	/* Checks the RSSI value with the threshold */
+	if(rssi_value<CCA_THRESHOLD) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+int SimpleSpirit1::get_pending_packet(void)
+{
+	return !IS_RXBUF_EMPTY();
+}
+
+/** Spirit Irq Callback **/
+void SimpleSpirit1::IrqHandler() {
+	st_lib_spirit_irqs x_irq_status;
+
+	/* get interrupt source from radio */
+	irq_get_status(&x_irq_status);
+
+	/* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
+	if(x_irq_status.IRQ_TX_DATA_SENT) {
+#ifdef DEBUG_IRQ
+		uint32_t *tmp = (uint32_t*)&x_irq_status;
+		debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+		debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+		debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+		tx_fifo_buffer = NULL;
+		_spirit_tx_started = false;
+
+		/* call user callback */
+		if(_current_irq_callback) {
+			_current_irq_callback(TX_DONE);
+		}
+
+		/* Disable handling of other TX flags */
+		x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = S_RESET;
+	}
+
+#ifndef RX_FIFO_THR_WA
+	/* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
+	if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
+#ifdef DEBUG_IRQ
+		uint32_t *tmp = (uint32_t*)&x_irq_status;
+		debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+		debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+		debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+		int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
+		int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
+
+		tx_fifo_remaining -= to_send;
+
+		/* Fill FIFO Buffer */
+		if(to_send > 0) {
+			spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
+		}
+		tx_buffer_pos += to_send;
+	}
+#endif // !RX_FIFO_THR_WA
+
+	/* Transmission error */
+	if(x_irq_status.IRQ_TX_FIFO_ERROR) {
+#ifdef DEBUG_IRQ
+		uint32_t *tmp = (uint32_t*)&x_irq_status;
+		debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+		debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+		if(_spirit_tx_started) {
+			_spirit_tx_started = false;
+			/* call user callback */
+			if(_current_irq_callback) {
+				_current_irq_callback(TX_ERR);
+			}
+		}
+
+		/* reset data still to be sent */
+		tx_fifo_remaining = 0;
+	}
+
+	/* The IRQ_RX_DATA_READY notifies a new packet arrived */
+	if(x_irq_status.IRQ_RX_DATA_READY) {
+#ifdef DEBUG_IRQ
+		uint32_t *tmp = (uint32_t*)&x_irq_status;
+		debug_if(!((*tmp) & IRQ_RX_DATA_READY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+		if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!)
+#ifdef HEAVY_DEBUG
+			debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+		} else {
+			_is_receiving = false; // Finished receiving
+			stop_rx_timeout();
+
+			spirit_rx_len = pkt_basic_get_received_pkt_length();
+
+#ifdef DEBUG_IRQ
+			debug_if(!(spirit_rx_len <= MAX_PACKET_LEN), "\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+
+			if(spirit_rx_len <= MAX_PACKET_LEN) {
+				uint8_t to_receive = spirit_rx_len - _spirit_rx_pos;
+				if(to_receive > 0) {
+					spi_read_linear_fifo(to_receive, &spirit_rx_buf[_spirit_rx_pos]);
+					_spirit_rx_pos += to_receive;
+				}
+			}
+
+			cmd_strobe(SPIRIT1_STROBE_FRX);
+
+			last_rssi = qi_get_rssi(); //MGR
+			last_sqi  = qi_get_sqi();  //MGR
+
+			/* call user callback */
+			if((_spirit_rx_pos == spirit_rx_len) && _current_irq_callback) {
+				_current_irq_callback(RX_DONE);
+			}
+
+			/* Disable handling of other RX flags */
+			x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
+		}
+	}
+
+#ifndef RX_FIFO_THR_WA
+	/* RX FIFO almost full */
+	if(x_irq_status.IRQ_RX_FIFO_ALMOST_FULL) {
+#ifdef DEBUG_IRQ
+		uint32_t *tmp = (uint32_t*)&x_irq_status;
+		debug_if(!((*tmp) & IRQ_RX_FIFO_ALMOST_FULL_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+		if(!_is_receiving) { // spurious irq?!?
+#ifdef DEBUG_IRQ
+			debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+		} else {
+			uint8_t fifo_available = linear_fifo_read_num_elements_rx_fifo();
+			if((fifo_available + _spirit_rx_pos) <= MAX_PACKET_LEN) {
+				spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
+				_spirit_rx_pos += fifo_available;
+			} else {
+#ifdef DEBUG_IRQ
+				debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+			}
+		}
+	}
+#endif // !RX_FIFO_THR_WA
+
+	/* Reception errors */
+	if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
+#ifdef DEBUG_IRQ
+		uint32_t *tmp = (uint32_t*)&x_irq_status;
+		debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+		debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+		rx_timeout_handler();
+		if(_spirit_tx_started) {
+			_spirit_tx_started = false;
+			/* call user callback */
+			if(_current_irq_callback) {
+				_current_irq_callback(TX_ERR);
+			}
+		}
+	}
+
+	/* The IRQ_VALID_SYNC is used to notify a new packet is coming */
+	if(x_irq_status.IRQ_VALID_SYNC) {
+#ifdef DEBUG_IRQ
+		uint32_t *tmp = (uint32_t*)&x_irq_status;
+		debug_if(!((*tmp) & IRQ_VALID_SYNC_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+		/* betzw - NOTE: there is a race condition between Spirit1 receiving packets and
+		 *               the MCU trying to send a packet, which gets resolved in favor of
+		 *               sending.
+		 */
+		if(_spirit_tx_started) {
+#ifdef DEBUG_IRQ
+			debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+#endif
+		} else {
+			_is_receiving = true;
+			start_rx_timeout();
+		}
+	}
+}
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,155 @@
+Getting Started with Contiki for STM32 Nucleo equipped with sub-1GHz SPIRIT1 expansion boards
+=============================================================================================
+
+This guide explains how to get started with the STM32 Nucleo and expansion boards port to Contiki.
+
+Port Feature
+============
+
+The port supports the following boards from ST:
+-    NUCLEO-L152RE board, based on the STM32L152RET6 ultra-low power microcontroller
+-	X-NUCLEO-IDS01A4 based on sub-1GHz SPSGRF-868 SPIRIT1 module (operating at 868 MHz)
+-	X-NUCLEO-IDS01A5 based on sub-1GHz SPSGRF-915 SPIRIT1 module (operating at 915 MHz)
+-   X-NUCLEO-IKS01A1 featuring motion MEMS and environmental sensors (optional)
+
+The following drivers are included:
+- LEDs and buttons (user, reset)
+- USB
+- SPIRIT1 sub-1GHz transceiver  
+- HTS221, LIS3MDL, LPS25HB, LSM6DS0 sensors
+
+
+Hardware Requirements
+=====================
+
+* NUCLEO-L152RE development board
+
+ >The NUCLEO-L152RE board belongs to the STM32 Nucleo family.
+It features an STM32L152RET6 ultra-low power microcontroller based on ARM Cortex M3 MCU.
+Detailed information on the NUCLEO-L152RE development board can be found at:
+http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260002
+
+
+* X-NUCLEO-IDS01Ax sub-1GHz expansion board
+
+ >The X-NUCLEO-IDS01A4 and X-NUCLEO-IDS01A5 are STM32 Nucleo expansion boards that use 
+the module SPSGRF-868 or SPSGRF-915 based on SPIRIT1 low data rate, low power sub-1 GHz transceiver.
+
+ >The user can select the X-NUCLEO-IDS01A4 board to operate the SPIRIT1 transceiver at 868MHz or the X-NUCLEO-IDS01A5 board to operate the SPIRIT1 transceiver at 915MHz.
+
+ >Detailed information on the X-NUCLEO-IDS01A4 expansion board can be found at:
+http://www.st.com/web/catalog/tools/FM146/CL2167/SC2006/PF261982
+
+ >Detailed information on the X-NUCLEO-IDS01A5 expansion board can be found at:
+http://www.st.com/web/catalog/tools/FM146/CL2167/SC2006/PF261983 
+
+ >Detailed information on the SPIRIT1 sub-1GHz transceiver can be found at:
+http://www.st.com/web/catalog/sense_power/FM2185/SC1845/PF253167
+
+* X-NUCLEO-IKS01A1, motion MEMS and environmental sensors expansion board (OPTIONAL)
+
+ >The X-NUCLEO-IKS01A1 is a motion MEMS and environmental sensor evaluation board.
+The use of this board is optional in the stm32nucleo-spirit1 Contiki platform. 
+
+ >Detailed information on the X-NUCLEO-IKS01A1 expansion board can be found at:
+http://www.st.com/web/catalog/tools/FM146/CL2167/SC2006/PF261191
+
+
+* USB type A to Mini-B USB cable, to connect the STM32 Nucleo board to the PC
+
+Software Requirements
+=====================
+
+The following software are needed:
+
+* ST port of Contiki for STM32 Nucleo and expansion boards. 
+ 
+ >The port is automatically installed when both the Contiki and the submodule repository are cloned: the former hosts the Contiki distribution and the ST platform interface, the latter hosts the actual library. The following commands are needed to download the full porting: 
+
+	git clone https://github.com/STclab/contiki.git
+	cd contiki/
+	git checkout stm32nucleo-spirit1
+	git submodule init
+	git submodule update
+
+
+Note: the first and third steps are required only if using the STclab GitHub repository, they won't be needed any more once the Pull Request is accepted.
+
+The platform name is: stm32nucleo-spirit1
+
+* A toolchain to build the firmware: The port has been developed and tested with GNU Tools 
+for ARM Embedded Processors.
+ >The toolchain can be found at: https://launchpad.net/gcc-arm-embedded
+The port was developed and tested using this version: gcc-arm-none-eabi v4.8.3
+
+
+Examples
+========
+
+The following examples have been successfully tested:
+
+* examples/stm32nucleo-spirit1/sensor-demo
+* examples/ipv6/simple-udp-rpl (multicast, rpl-border-router, simple-udp-rpl)
+
+
+Build an example
+================
+In order to build an example go to the selected example directory (see a list of tested
+examples in the previous section).
+
+For example, go to examples/ipv6/simple-udp-rpl directory.
+
+	
+If the X-NUCLEO-IDS01A4 sub-1GHz RF expansion board is used, the following must be run:
+
+	make TARGET=stm32nucleo-spirit1 USE_SUBGHZ_BOARD=IDS01A4 clean
+	make TARGET=stm32nucleo-spirit1 USE_SUBGHZ_BOARD=IDS01A4
+
+If the X-NUCLEO-IDS01A5 sub-1GHz RF expansion board is used, the following must be run:
+
+	make TARGET=stm32nucleo-spirit1 USE_SUBGHZ_BOARD=IDS01A5 clean
+	make TARGET=stm32nucleo-spirit1 USE_SUBGHZ_BOARD=IDS01A5
+	
+	
+This will create executables for UDP sender and receiver nodes.
+
+In order to generate binary files that can be flashed on the STM32 Nucleo the following command must be run:
+
+	arm-none-eabi-objcopy -O binary unicast-sender.stm32nucleo-spirit1 unicast-sender.bin
+	arm-none-eabi-objcopy -O binary unicast-receiver.stm32nucleo-spirit1 unicast-receiver.bin
+
+These executables can be programmed on the nodes using the procedure described hereafter.
+
+
+In case you need to build an example that uses the additional sensors expansion board 
+(for example, considering a system made of NUCLEO-L152RE, X-NUCLEO-IDS01A4 and X-NUCLEO-IKS01A1)
+then the command to be run would be:
+
+	make TARGET=stm32nucleo-spirit1 USE_SUBGHZ_BOARD=IDS01A4 USE_SENSOR_BOARD=1
+
+System setup
+============ 
+
+1. Check that the jumper on the J1 connector on the X-NUCLEO-IDS01Ax expansion board is connected. 
+This jumper provides the required voltage to the devices on the board.
+
+2. Connect the X-NUCLEO-IDS01Ax board to the STM32 Nucleo board (NUCLEO-L152RE) from the top.
+
+3. If the optional X-NUCLEO-IKS01A1 board is used, connect it on top of the X-NUCLEO-IDS01Ax board.
+
+4. Power the STM32 Nucleo board using the Mini-B USB cable connected to the PC.
+
+5. Program the firmware on the STM32 Nucleo board. 
+This can be done by copying the binary file on the USB mass storage that is 
+automatically created when plugging the STM32 Nucleo board to the PC.
+
+6. Reset the MCU by using the reset button on the STM32 Nucleo board
+
+
+
+
+
+
+
+
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/contiki-conf.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/contiki-conf.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,155 @@
+/**
+******************************************************************************
+* @file    platform/stm32nucleo-spirit1/contiki-conf.h
+* @author  System LAB 
+* @version V1.0.0
+* @date    17-May-2015
+* @brief   Contiki configuration parameters
+******************************************************************************
+* @attention
+*
+* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice,
+*      this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation
+*      and/or other materials provided with the distribution.
+*   3. Neither the name of STMicroelectronics nor the names of its contributors
+*      may be used to endorse or promote products derived from this software
+*      without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+******************************************************************************
+*/
+/*---------------------------------------------------------------------------*/
+#ifndef __CONTIKI_CONF_H__
+#define __CONTIKI_CONF_H__
+/*---------------------------------------------------------------------------*/
+#include "platform-conf.h"
+//#include "project-conf.h"
+/*---------------------------------------------------------------------------*/
+#define SLIP_BRIDGE_CONF_NO_PUTCHAR 1
+
+#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8
+#define NULLRDC_CONF_802154_AUTOACK 0
+#define NETSTACK_CONF_FRAMER  framer_802154
+#define NETSTACK_CONF_NETWORK sicslowpan_driver
+
+#undef NETSTACK_CONF_RDC
+#define NETSTACK_CONF_RDC     nullrdc_driver
+#define NETSTACK_RDC_HEADER_LEN 0
+
+#undef NETSTACK_CONF_MAC
+#define NETSTACK_CONF_MAC csma_driver
+#define NETSTACK_MAC_HEADER_LEN 0
+
+#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD \
+  (NETSTACK_RADIO_MAX_PAYLOAD_LEN - NETSTACK_MAC_HEADER_LEN - \
+   NETSTACK_RDC_HEADER_LEN )
+
+#define RIMESTATS_CONF_ENABLED                 0
+#define RIMESTATS_CONF_ON                      0
+
+
+/* Network setup for IPv6 */
+
+#define CXMAC_CONF_ANNOUNCEMENTS         0
+
+
+/* A trick to resolve a compilation error with IAR. */
+#ifdef __ICCARM__
+#define UIP_CONF_DS6_AADDR_NBU              1
+#endif
+
+/* radio driver blocks until ACK is received */
+#define NULLRDC_CONF_ACK_WAIT_TIME          (0)
+#define CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT 0
+#define IEEE802154_CONF_PANID       0xABCD
+
+#define AODV_COMPLIANCE
+
+#define WITH_ASCII 1
+
+#define PROCESS_CONF_NUMEVENTS 8
+#define PROCESS_CONF_STATS 1
+/*#define PROCESS_CONF_FASTPOLL    4*/
+
+
+#define LINKADDR_CONF_SIZE              8
+
+#define UIP_CONF_LL_802154              1
+#define UIP_CONF_LLH_LEN                0
+
+#define UIP_CONF_ROUTER                 1
+
+/* configure number of neighbors and routes */
+#ifndef UIP_CONF_DS6_ROUTE_NBU
+#define UIP_CONF_DS6_ROUTE_NBU   30
+#endif /* UIP_CONF_DS6_ROUTE_NBU */
+
+#ifndef UIP_CONF_ND6_SEND_RA
+#define UIP_CONF_ND6_SEND_RA    0
+#endif
+#define UIP_CONF_ND6_REACHABLE_TIME    600000 //90000// 600000 
+#define UIP_CONF_ND6_RETRANS_TIMER      10000
+
+
+#define UIP_CONF_IPV6                   1
+#ifndef UIP_CONF_IPV6_QUEUE_PKT
+#define UIP_CONF_IPV6_QUEUE_PKT         0
+#endif /* UIP_CONF_IPV6_QUEUE_PKT */
+#define UIP_CONF_IP_FORWARD             0
+#ifndef UIP_CONF_BUFFER_SIZE
+//#define UIP_CONF_BUFFER_SIZE    280
+#define UIP_CONF_BUFFER_SIZE    600
+#endif
+
+#define SICSLOWPAN_CONF_MAXAGE                  4
+#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS       2
+
+
+#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS
+#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS   5
+#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */
+
+#define UIP_CONF_ICMP_DEST_UNREACH 1
+
+#define UIP_CONF_DHCP_LIGHT
+#define UIP_CONF_LLH_LEN         0
+#ifndef UIP_CONF_RECEIVE_WINDOW
+#define UIP_CONF_RECEIVE_WINDOW  150
+#endif
+#ifndef UIP_CONF_TCP_MSS
+#define UIP_CONF_TCP_MSS         UIP_CONF_RECEIVE_WINDOW
+#endif
+#define UIP_CONF_MAX_CONNECTIONS 4
+#define UIP_CONF_MAX_LISTENPORTS 8
+#define UIP_CONF_UDP_CONNS       12
+#define UIP_CONF_FWCACHE_SIZE    30
+#define UIP_CONF_BROADCAST       1
+#define UIP_ARCH_IPCHKSUM        0
+#define UIP_CONF_UDP             1
+#define UIP_CONF_UDP_CHECKSUMS   1
+#define UIP_CONF_TCP		 1
+/*---------------------------------------------------------------------------*/
+/* include the project config */
+/* PROJECT_CONF_H might be defined in the project Makefile */
+#ifdef PROJECT_CONF_H
+#include "project-conf.h"
+#endif /* PROJECT_CONF_H */
+/*---------------------------------------------------------------------------*/
+#endif /* CONTIKI_CONF_H */
+/*---------------------------------------------------------------------------*/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/hw-config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/hw-config.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,125 @@
+ /**
+  ******************************************************************************
+  * @file    hw-config.h
+  * @author  System LAB 
+ * @version V1.0.0
+ * @date    17-May-2015
+  * @brief   Header file for Hardware Configuration & Setup
+  ******************************************************************************
+  * @attention
+  *
+ * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+  *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of STMicroelectronics nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+  *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+/*---------------------------------------------------------------------------*/
+#ifndef __HW_CONFIG_H
+#define __HW_CONFIG_H
+/*---------------------------------------------------------------------------*/
+#include "stm32l-spirit1-config.h"
+/*---------------------------------------------------------------------------*/
+#define UART_RxBufferSize    512
+/*---------------------------------------------------------------------------*/    
+#define I2Cx                            I2C1
+#define I2Cx_CLK_ENABLE()               __I2C1_CLK_ENABLE()
+#define I2Cx_SDA_GPIO_CLK_ENABLE()      __GPIOB_CLK_ENABLE()
+#define I2Cx_SCL_GPIO_CLK_ENABLE()      __GPIOB_CLK_ENABLE() 
+/*---------------------------------------------------------------------------*/
+#define I2Cx_FORCE_RESET()              __I2C1_FORCE_RESET()
+#define I2Cx_RELEASE_RESET()            __I2C1_RELEASE_RESET()
+/*---------------------------------------------------------------------------*/
+/* Definition for I2Cx Pins */
+#define I2Cx_SCL_PIN                    GPIO_PIN_8
+#define I2Cx_SCL_GPIO_PORT              GPIOB
+#define I2Cx_SDA_PIN                    GPIO_PIN_9
+#define I2Cx_SDA_GPIO_PORT              GPIOB
+#define I2Cx_SCL_SDA_AF                 GPIO_AF4_I2C1
+
+/* Definition for I2Cx's NVIC */
+#define I2Cx_EV_IRQn                    I2C1_EV_IRQn
+#define I2Cx_ER_IRQn                    I2C1_ER_IRQn
+#define I2Cx_EV_IRQHandler              I2C1_EV_IRQHandler
+#define I2Cx_ER_IRQHandler              I2C1_ER_IRQHandler
+
+  
+#define I2Cx                            I2C1
+#define I2Cx_CLK_ENABLE()               __I2C1_CLK_ENABLE()
+#define I2Cx_SDA_GPIO_CLK_ENABLE()      __GPIOB_CLK_ENABLE()
+#define I2Cx_SCL_GPIO_CLK_ENABLE()      __GPIOB_CLK_ENABLE() 
+
+#define I2Cx_FORCE_RESET()              __I2C1_FORCE_RESET()
+#define I2Cx_RELEASE_RESET()            __I2C1_RELEASE_RESET()
+
+/* Definition for I2Cx Pins */
+#define I2Cx_SCL_PIN                    GPIO_PIN_8
+#define I2Cx_SCL_GPIO_PORT              GPIOB
+#define I2Cx_SDA_PIN                    GPIO_PIN_9
+#define I2Cx_SDA_GPIO_PORT              GPIOB
+#define I2Cx_SCL_SDA_AF                 GPIO_AF4_I2C1
+
+/* Definition for I2Cx's NVIC */
+#define I2Cx_EV_IRQn                    I2C1_EV_IRQn
+#define I2Cx_ER_IRQn                    I2C1_ER_IRQn
+#define I2Cx_EV_IRQHandler              I2C1_EV_IRQHandler
+#define I2Cx_ER_IRQHandler              I2C1_ER_IRQHandler
+
+/* User can use this section to tailor USARTx/UARTx instance used and associated
+   resources */
+/* Definition for USARTx clock resources */
+#define USARTx                           USART2
+#define USARTx_CLK_ENABLE()              __USART2_CLK_ENABLE();
+#define DMAx_CLK_ENABLE()                __DMA1_CLK_ENABLE()
+#define USARTx_RX_GPIO_CLK_ENABLE()      __GPIOA_CLK_ENABLE()
+#define USARTx_TX_GPIO_CLK_ENABLE()      __GPIOA_CLK_ENABLE()
+
+#define USARTx_FORCE_RESET()             __USART2_FORCE_RESET()
+#define USARTx_RELEASE_RESET()           __USART2_RELEASE_RESET()
+
+/* Definition for USARTx Pins */
+#define USARTx_TX_PIN                    GPIO_PIN_2
+#define USARTx_TX_GPIO_PORT              GPIOA
+
+#define USARTx_RX_PIN                    GPIO_PIN_3
+#define USARTx_RX_GPIO_PORT              GPIOA
+
+     /* Definition for USARTx's NVIC */
+#define USARTx_IRQn                      USART2_IRQn
+#define USARTx_IRQHandler                USART2_IRQHandler
+
+#define USARTx_TX_AF                     GPIO_AF7_USART2 
+#define USARTx_RX_AF                     GPIO_AF7_USART2
+
+
+  /* Enable sensor mask */
+#define PRESSURE_SENSOR                         0x00000001
+#define TEMPERATURE_SENSOR                      0x00000002
+#define HUMIDITY_SENSOR                         0x00000004
+#define UV_SENSOR                               0x00000008  
+#define ACCELEROMETER_SENSOR                    0x00000010  
+#define GYROSCOPE_SENSOR                        0x00000020
+#define MAGNETIC_SENSOR                         0x00000040      
+/*---------------------------------------------------------------------------*/
+#endif  /*__HW_CONFIG_H*/
+/*---------------------------------------------------------------------------*/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/ip64-conf.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/ip64-conf.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef IP64_CONF_H
+#define IP64_CONF_H
+
+/*
+#include "ip64-tap-driver.h"
+#include "ip64-eth-interface.h"
+
+#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_eth_interface
+#define IP64_CONF_INPUT                  ip64_eth_interface_input
+
+#define IP64_CONF_ETH_DRIVER             ip64_tap_driver
+
+
+#undef UIP_FALLBACK_INTERFACE
+#define UIP_FALLBACK_INTERFACE ip64_uip_fallback_interface
+*/
+#ifdef MY_DRIVERS
+#include <my_wifi_interface.h>
+#include <my_wifi_driver.h>
+
+#define IP64_CONF_UIP_FALLBACK_INTERFACE_SLIP 0
+#define IP64_CONF_UIP_FALLBACK_INTERFACE my_wifi_interface
+#define IP64_CONF_INPUT                  my_wifi_interface_input
+#define IP64_CONF_ETH_DRIVER             my_wifi_driver
+
+#undef UIP_CONF_ND6_RA_RDNSS
+#define UIP_CONF_ND6_RA_RDNSS 1
+
+#undef UIP_CONF_ND6_SEND_RA
+#define UIP_CONF_ND6_SEND_RA  1
+
+#undef UIP_CONF_ROUTER
+#define UIP_CONF_ROUTER       1
+
+#ifndef QUEUEBUF_CONF_NUM
+#define QUEUEBUF_CONF_NUM          16
+#endif
+
+
+#else
+
+
+#include "net/ip64/ip64-slip-interface.h"
+#include "net/ip64/ip64-null-driver.h"
+
+#define IP64_CONF_UIP_FALLBACK_INTERFACE_SLIP 1
+#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_slip_interface
+#define IP64_CONF_INPUT                  ip64_slip_interface_input
+#define IP64_CONF_ETH_DRIVER             ip64_null_driver
+
+#undef UIP_CONF_ND6_RA_RDNSS
+#define UIP_CONF_ND6_RA_RDNSS 1
+
+#undef UIP_CONF_ND6_SEND_RA
+#define UIP_CONF_ND6_SEND_RA  1
+
+#undef UIP_CONF_ROUTER
+#define UIP_CONF_ROUTER       1
+
+#ifndef QUEUEBUF_CONF_NUM
+#define QUEUEBUF_CONF_NUM          16
+#endif
+
+#endif//MY_DRIVERS
+
+#endif /* IP64_CONF_H */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/platform-conf.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/platform-conf.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,197 @@
+/**
+******************************************************************************
+* @file    platform/stm32nucleo-spirit1/platform-conf.h
+* @author  System LAB 
+* @version V1.0.0
+* @date    17-May-2015
+* @brief   Configuration parameters
+******************************************************************************
+* @attention
+*
+* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice,
+*      this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation
+*      and/or other materials provided with the distribution.
+*   3. Neither the name of STMicroelectronics nor the names of its contributors
+*      may be used to endorse or promote products derived from this software
+*      without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+******************************************************************************
+*/
+/*---------------------------------------------------------------------------*/
+/**
+ * \addtogroup stm32nucleo-spirit1
+ * @{
+ *
+ * \defgroup stm32nucleo-spirit1-peripherals User Button on STM32 Nucleo
+ *
+ * Defines some of the platforms capabilities
+ * @{
+ *
+ * \file
+ * Header file for the stm32nucleo-spirit1 platform configuration
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef __PLATFORM_CONF_H__
+#define __PLATFORM_CONF_H__
+/*---------------------------------------------------------------------------*/
+#ifdef USE_STM32L1XX_NUCLEO
+#include <inttypes.h>
+#include <string.h>
+/*---------------------------------------------------------------------------*/
+#define PLATFORM_HAS_LEDS 1
+#define PLATFORM_HAS_BUTTON 1
+#define PLATFORM_HAS_RADIO 1
+
+#define LEDS_GREEN  1 /*Nucleo LED*/
+#define LEDS_RED    2 /*SPIRIT1 LED*/
+
+#ifdef COMPILE_SENSORS
+#define LEDS_CONF_ALL 1 /*Can't use SPIRIT1 LED in this case*/
+#else
+#define LEDS_CONF_ALL 3 /*No sensors -> we can use SPIRIT1 LED in this case*/
+#endif /*COMPILE_SENSORS*/
+/*---------------------------------------------------------------------------*/
+#define F_CPU                   32000000ul
+#define RTIMER_ARCH_SECOND              32768   
+#define PRESCALER       ((F_CPU / (RTIMER_ARCH_SECOND*2)))
+
+#define UART1_CONF_TX_WITH_INTERRUPT        0
+#define WITH_SERIAL_LINE_INPUT              1
+#define TELNETD_CONF_NUMLINES               6
+#define NETSTACK_CONF_RADIO                 spirit_radio_driver
+#define NETSTACK_RADIO_MAX_PAYLOAD_LEN      96 /* spirit1-config.h */
+
+#if WITH_IP64
+#include "ip64-conf.h"
+#define WITH_SLIP 1
+#ifndef UIP_FALLBACK_INTERFACE
+#define UIP_FALLBACK_INTERFACE ip64_uip_fallback_interface
+#endif
+#endif /* WITH_IP64 */
+
+/*---------------------------------------------------------------------------*/
+/* define ticks/second for slow and fast clocks. Notice that these should be a
+  power of two, eg 64,128,256,512 etc, for efficiency as POT's can be optimized
+  well. */
+#define CLOCK_CONF_SECOND             128
+#define RELOAD_VALUE        ((F_CPU/CLOCK_CONF_SECOND) - 1)
+/* One tick: 62.5 ms */
+
+#define RTIMER_CLOCK_LT(a,b)     ((signed short)((a)-(b)) < 0)
+/*---------------------------------------------------------------------------*/
+typedef unsigned long clock_time_t;     
+typedef unsigned long long rtimer_clock_t; 
+/*---------------------------------------------------------------------------*/
+#define CC_CONF_REGISTER_ARGS          0
+#define CC_CONF_FUNCTION_POINTER_ARGS  1
+#define CC_CONF_FASTCALL
+#define CC_CONF_VA_ARGS                1
+#define CC_CONF_INLINE                 inline
+
+#define CCIF
+#define CLIF
+/*---------------------------------------------------------------------------*/
+typedef uint8_t         u8_t;
+typedef uint16_t        u16_t;
+typedef uint32_t        u32_t;
+typedef  int32_t        s32_t;
+typedef unsigned short  uip_stats_t;
+/*---------------------------------------------------------------------------*/
+#define MULTICHAN_CONF_SET_CHANNEL(x)
+#define MULTICHAN_CONF_READ_RSSI(x) 0
+/*---------------------------------------------------------------------------*/
+#endif//USE_STM32L1XX_NUCLEO
+
+#ifdef USE_STM32F4XX_NUCLEO
+#include <inttypes.h>
+#include <string.h>
+#include "main.h"
+/*---------------------------------------------------------------------------*/
+#define PLATFORM_HAS_LEDS 1
+#define PLATFORM_HAS_BUTTON 1
+#define PLATFORM_HAS_RADIO 1
+
+#define LEDS_GREEN  1 /*Nucleo LED*/
+#define LEDS_RED    2 /*SPIRIT1 LED*/
+
+#ifdef COMPILE_SENSORS
+#define LEDS_CONF_ALL 1 /*Can't use SPIRIT1 LED in this case*/
+#else
+#define LEDS_CONF_ALL 3 /*No sensors -> we can use SPIRIT1 LED in this case*/
+#endif /*COMPILE_SENSORS*/
+/*---------------------------------------------------------------------------*/
+#define F_CPU                   	84000000ul
+#define RTIMER_ARCH_SECOND          96000//32678
+//#define PRESCALER       			uwPrescalerValue
+
+#define UART1_CONF_TX_WITH_INTERRUPT        0
+#define WITH_SERIAL_LINE_INPUT              1
+#define TELNETD_CONF_NUMLINES               6
+#define NETSTACK_CONF_RADIO                 spirit_radio_driver
+#define NETSTACK_RADIO_MAX_PAYLOAD_LEN      96 /* spirit1-config.h */
+
+#if WITH_IP64
+#include "ip64-conf.h"
+#define WITH_SLIP 1
+#ifndef UIP_FALLBACK_INTERFACE
+#define UIP_FALLBACK_INTERFACE ip64_uip_fallback_interface
+#endif
+#endif /* WITH_IP64 */
+
+/*---------------------------------------------------------------------------*/
+/* define ticks/second for slow and fast clocks. Notice that these should be a
+  power of two, eg 64,128,256,512 etc, for efficiency as POT's can be optimized
+  well. */
+#define CLOCK_CONF_SECOND             512
+#define RELOAD_VALUE        ((F_CPU/CLOCK_CONF_SECOND) - 1)
+
+/* One tick: 62.5 ms */
+
+#define RTIMER_CLOCK_LT(a,b)     ((signed short)((a)-(b)) < 0)
+/*---------------------------------------------------------------------------*/
+typedef unsigned long clock_time_t;
+typedef unsigned long long rtimer_clock_t;
+/*---------------------------------------------------------------------------*/
+#define CC_CONF_REGISTER_ARGS          0
+#define CC_CONF_FUNCTION_POINTER_ARGS  1
+#define CC_CONF_FASTCALL
+#define CC_CONF_VA_ARGS                1
+#define CC_CONF_INLINE                 inline
+
+#define CCIF
+#define CLIF
+/*---------------------------------------------------------------------------*/
+typedef uint8_t         u8_t;
+typedef uint16_t        u16_t;
+typedef uint32_t        u32_t;
+typedef  int32_t        s32_t;
+typedef unsigned short  uip_stats_t;
+/*---------------------------------------------------------------------------*/
+#define MULTICHAN_CONF_SET_CHANNEL(x)
+#define MULTICHAN_CONF_READ_RSSI(x) 0
+/*---------------------------------------------------------------------------*/
+#endif//USE_STM32F4XX_NUCLEO
+
+#endif /* __PLATFORM_CONF_H__ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ * @}
+ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/radio.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/radio.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         Header file for the radio API
+ * \author
+ *         Adam Dunkels <adam@sics.se>
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ *         Nicolas Tsiftes <nvt@sics.se>
+ */
+
+/**
+ * \addtogroup dev
+ * @{
+ */
+
+/**
+ * \defgroup radio Radio API
+ *
+ * The radio API module defines a set of functions that a radio device
+ * driver must implement.
+ *
+ * @{
+ */
+
+#ifndef RADIO_H_
+#define RADIO_H_
+
+#include <stddef.h>
+
+/**
+ * Each radio has a set of parameters that designate the current
+ * configuration and state of the radio. Parameters can either have
+ * values of type radio_value_t, or, when this type is insufficient, a
+ * generic object that is specified by a memory pointer and the size
+ * of the object.
+ *
+ * The radio_value_t type is set to an integer type that can hold most
+ * values used to configure the radio, and is therefore the most
+ * common type used for a parameter. Certain parameters require
+ * objects of a considerably larger size than radio_value_t, however,
+ * and in these cases the documentation below for the parameter will
+ * indicate this.
+ *
+ * All radio parameters that can vary during runtime are prefixed by
+ * "RADIO_PARAM", whereas those "parameters" that are guaranteed to
+ * remain immutable are prefixed by "RADIO_CONST". Each mutable
+ * parameter has a set of valid parameter values. When attempting to
+ * set a parameter to an invalid value, the radio will return
+ * RADIO_RESULT_INVALID_VALUE.
+ *
+ * Some radios support only a subset of the defined radio parameters.
+ * When trying to set or get such an unsupported parameter, the radio
+ * will return RADIO_RESULT_NOT_SUPPORTED.
+ */
+
+typedef int radio_value_t;
+typedef unsigned radio_param_t;
+
+enum {
+
+  /* Radio power mode determines if the radio is on
+    (RADIO_POWER_MODE_ON) or off (RADIO_POWER_MODE_OFF). */
+  RADIO_PARAM_POWER_MODE,
+
+  /*
+   * Channel used for radio communication. The channel depends on the
+   * communication standard used by the radio. The values can range
+   * from RADIO_CONST_CHANNEL_MIN to RADIO_CONST_CHANNEL_MAX.
+   */
+  RADIO_PARAM_CHANNEL,
+
+  /* Personal area network identifier, which is used by the address filter. */
+  RADIO_PARAM_PAN_ID,
+
+  /* Short address (16 bits) for the radio, which is used by the address
+     filter. */
+  RADIO_PARAM_16BIT_ADDR,
+
+  /*
+   * Radio receiver mode determines if the radio has address filter
+   * (RADIO_RX_MODE_ADDRESS_FILTER) and auto-ACK (RADIO_RX_MODE_AUTOACK)
+   * enabled. This parameter is set as a bit mask.
+   */
+  RADIO_PARAM_RX_MODE,
+
+  /*
+   * Radio transmission mode determines if the radio has send on CCA
+   * (RADIO_TX_MODE_SEND_ON_CCA) enabled or not. This parameter is set
+   * as a bit mask.
+   */
+  RADIO_PARAM_TX_MODE,
+
+  /*
+   * Transmission power in dBm. The values can range from
+   * RADIO_CONST_TXPOWER_MIN to RADIO_CONST_TXPOWER_MAX.
+   *
+   * Some radios restrict the available values to a subset of this
+   * range.  If an unavailable TXPOWER value is requested to be set,
+   * the radio may select another TXPOWER close to the requested
+   * one. When getting the value of this parameter, the actual value
+   * used by the radio will be returned.
+   */
+  RADIO_PARAM_TXPOWER,
+
+  /*
+   * Clear channel assessment threshold in dBm. This threshold
+   * determines the minimum RSSI level at which the radio will assume
+   * that there is a packet in the air.
+   *
+   * The CCA threshold must be set to a level above the noise floor of
+   * the deployment. Otherwise mechanisms such as send-on-CCA and
+   * low-power-listening duty cycling protocols may not work
+   * correctly. Hence, the default value of the system may not be
+   * optimal for any given deployment.
+   */
+  RADIO_PARAM_CCA_THRESHOLD,
+
+  /* Received signal strength indicator in dBm. */
+  RADIO_PARAM_RSSI,
+
+  /*
+   * Long (64 bits) address for the radio, which is used by the address filter.
+   * The address is specified in network byte order.
+   *
+   * Because this parameter value is larger than what fits in radio_value_t,
+   * it needs to be used with radio.get_object()/set_object().
+   */
+  RADIO_PARAM_64BIT_ADDR,
+
+  /* Constants (read only) */
+
+  /* The lowest radio channel. */
+  RADIO_CONST_CHANNEL_MIN,
+  /* The highest radio channel. */
+  RADIO_CONST_CHANNEL_MAX,
+
+  /* The minimum transmission power in dBm. */
+  RADIO_CONST_TXPOWER_MIN,
+  /* The maximum transmission power in dBm. */
+  RADIO_CONST_TXPOWER_MAX
+};
+
+/* Radio power modes */
+enum {
+  RADIO_POWER_MODE_OFF,
+  RADIO_POWER_MODE_ON
+};
+
+/**
+ * The radio reception mode controls address filtering and automatic
+ * transmission of acknowledgements in the radio (if such operations
+ * are supported by the radio). A single parameter is used to allow
+ * setting these features simultaneously as an atomic operation.
+ *
+ * To enable both address filter and transmissions of automatic
+ * acknowledgments:
+ *
+ * NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE,
+ *       RADIO_RX_MODE_ADDRESS_FILTER | RADIO_RX_MODE_AUTOACK);
+ */
+#define RADIO_RX_MODE_ADDRESS_FILTER   (1 << 0)
+#define RADIO_RX_MODE_AUTOACK          (1 << 1)
+
+/**
+ * The radio transmission mode controls whether transmissions should
+ * be done using clear channel assessment (if supported by the
+ * radio). If send-on-CCA is enabled, the radio's send function will
+ * wait for a radio-specific time window for the channel to become
+ * clear. If this does not happen, the send function will return
+ * RADIO_TX_COLLISION.
+ */
+#define RADIO_TX_MODE_SEND_ON_CCA      (1 << 0)
+
+/* Radio return values when setting or getting radio parameters. */
+typedef enum {
+  RADIO_RESULT_OK,
+  RADIO_RESULT_NOT_SUPPORTED,
+  RADIO_RESULT_INVALID_VALUE,
+  RADIO_RESULT_ERROR
+} radio_result_t;
+
+/* Radio return values for transmissions. */
+enum {
+  RADIO_TX_OK,
+  RADIO_TX_ERR,
+  RADIO_TX_COLLISION,
+  RADIO_TX_NOACK,
+};
+
+/**
+ * The structure of a device driver for a radio in Contiki.
+ */
+struct radio_driver {
+
+  int (* init)(void);
+
+  /** Prepare the radio with a packet to be sent. */
+  int (* prepare)(const void *payload, unsigned short payload_len);
+
+  /** Send the packet that has previously been prepared. */
+  int (* transmit)(unsigned short transmit_len);
+
+  /** Prepare & transmit a packet. */
+  int (* send)(const void *payload, unsigned short payload_len);
+
+  /** Read a received packet into a buffer. */
+  int (* read)(void *buf, unsigned short buf_len);
+
+  /** Perform a Clear-Channel Assessment (CCA) to find out if there is
+      a packet in the air or not. */
+  int (* channel_clear)(void);
+
+  /** Check if the radio driver is currently receiving a packet */
+  int (* receiving_packet)(void);
+
+  /** Check if the radio driver has just received a packet */
+  int (* pending_packet)(void);
+
+  /** Turn the radio on. */
+  int (* on)(void);
+
+  /** Turn the radio off. */
+  int (* off)(void);
+
+  /** Get a radio parameter value. */
+  radio_result_t (* get_value)(radio_param_t param, radio_value_t *value);
+
+  /** Set a radio parameter value. */
+  radio_result_t (* set_value)(radio_param_t param, radio_value_t value);
+
+  /**
+   * Get a radio parameter object. The argument 'dest' must point to a
+   * memory area of at least 'size' bytes, and this memory area will
+   * contain the parameter object if the function succeeds.
+   */
+  radio_result_t (* get_object)(radio_param_t param, void *dest, size_t size);
+
+  /**
+   * Set a radio parameter object. The memory area referred to by the
+   * argument 'src' will not be accessed after the function returns.
+   */
+  radio_result_t (* set_object)(radio_param_t param, const void *src,
+                                size_t size);
+
+};
+
+#endif /* RADIO_H_ */
+
+/** @} */
+/** @} */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1-config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1-config.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, STMicroelectronics.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef __SPIRIT1_CONFIG_H__
+#define __SPIRIT1_CONFIG_H__
+/*---------------------------------------------------------------------------*/
+#include "radio.h"
+#include "SPIRIT_Config.h"
+#include "spirit1-const.h"
+/*---------------------------------------------------------------------------*/
+#define CCA_THRESHOLD               -98.0   /* dBm */
+#define XTAL_FREQUENCY              50000000    /* Hz */ 
+#define SPIRIT_MAX_FIFO_LEN         (96) // betzw - WAS: 600
+/*---------------------------------------------------------------------------*/
+
+/* Sometimes Spirit1 seems to NOT deliver (correctly) the 'IRQ_RX_DATA_READY'
+ * event for packets which have a length which is close to a multiple of
+ * RX FIFO size. Furthermore, in these cases also the content delivery seems
+ * to be compromised as well as the generation of RX/TX FIFO errors.
+ * This can be avoided by reducing the maximum packet length to a value which
+ * is lower than the RX FIFO size.
+ *
+ * Enable beyond macro if you want to use the version of the driver which avoids
+ * FIFO overflows by reducing packet length.
+ *
+ * NOTE: the non delivery of event 'IRQ_RX_DATA_READY' MUST still be
+ *       investigated further deeply (both on HW & SW level)!
+ */
+#define RX_FIFO_THR_WA
+
+/**    
+ * The MAX_PACKET_LEN is an arbitrary value used to define the two array
+ * spirit_txbuf and spirit_rxbuf.
+ * The SPIRIT1 supports with its packet handler a length of 65,535 bytes,
+ * and in direct mode (without packet handler) there is no limit of data.
+ */
+#ifdef RX_FIFO_THR_WA
+#define MAX_PACKET_LEN              (SPIRIT_MAX_FIFO_LEN-1)
+#else
+#define MAX_PACKET_LEN              (255) // betzw - WAS: SPIRIT_MAX_FIFO_LEN, but LEN_WIDTH is set to 7 so the variable payload length is theoretically from 0 to 255 bytes
+#endif
+
+/*---------------------------------------------------------------------------*/
+/**    
+ * Spirit1 IC version
+ */
+#define SPIRIT1_VERSION             SPIRIT_VERSION_3_0
+/*---------------------------------------------------------------------------*/
+#endif /* __SPIRIT1_CONFIG_H__ */
+/*---------------------------------------------------------------------------*/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1-const.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1-const.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, STMicroelectronics.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef __SPIRIT1_CONST_H__
+#define __SPIRIT1_CONST_H__
+/*---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+
+/* The state bitfield and values for different states, as read from MC_STATE[1:0] registers,
+which are returned on any SPI read or write operation. */
+#define SPIRIT1_STATE_STATEBITS           (0x00FE)
+/*---------------------------------------------------------------------------*/
+
+#define SPIRIT1_STATE_STANDBY             ((0x0040)<<1)
+#define SPIRIT1_STATE_SLEEP               ((0x0036)<<1)
+#define SPIRIT1_STATE_READY               ((0x0003)<<1)
+#define SPIRIT1_STATE_LOCK                ((0x000F)<<1)
+#define SPIRIT1_STATE_RX                  ((0x0033)<<1)
+#define SPIRIT1_STATE_TX                  ((0x005F)<<1)
+/* NB the below states were extracted from ST drivers, but are not specified in the datasheet */
+#define SPIRIT1_STATE_PM_SETUP            ((0x003D)<<1)
+#define SPIRIT1_STATE_XO_SETTLING         ((0x0023)<<1)
+#define SPIRIT1_STATE_SYNTH_SETUP         ((0x0053)<<1)
+#define SPIRIT1_STATE_PROTOCOL            ((0x001F)<<1)
+#define SPIRIT1_STATE_SYNTH_CALIBRATION   ((0x004F)<<1)
+/*---------------------------------------------------------------------------*/
+/* strobe commands */
+#define SPIRIT1_STROBE_TX             0x60
+#define SPIRIT1_STROBE_RX             0x61
+#define SPIRIT1_STROBE_READY          0x62
+#define SPIRIT1_STROBE_STANDBY        0x63
+#define SPIRIT1_STROBE_SLEEP          0x64
+#define SPIRIT1_STROBE_SABORT         0x67
+#define SPIRIT1_STROBE_SRES           0x70
+#define SPIRIT1_STROBE_FRX            0x71
+#define SPIRIT1_STROBE_FTX            0x72
+/*---------------------------------------------------------------------------*/
+
+
+
+/* Exported types ------------------------------------------------------------*/
+/*------------------------------------------------------------------*/
+
+
+#endif /* __SPIRIT1_CONST_H__ */
+/*---------------------------------------------------------------------------*/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2012, STMicroelectronics.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef __SPIRIT_H__
+#define __SPIRIT_H__
+/*---------------------------------------------------------------------------*/
+#include "radio.h"
+#include "SPIRIT_Config.h"
+#include "spirit1-config.h"
+//#include "spirit1_appli.h"
+#include "spirit1-const.h"
+/*---------------------------------------------------------------------------*/   
+extern const struct radio_driver spirit_radio_driver;
+void spirit1_interrupt_callback(void);
+
+/* exported from spirit1appli.h */
+
+#include "radio_shield_config.h"
+#include "MCU_Interface.h"
+#include "SPIRIT_Config.h"
+// betzw - WAS: #include "SPIRIT1_Util.h"
+
+
+#if defined(X_NUCLEO_IDS01A3)
+	 #define USE_SPIRIT1_433MHz
+#elif defined(X_NUCLEO_IDS01A4)
+         #define USE_SPIRIT1_868MHz
+#elif defined(X_NUCLEO_IDS01A5)
+         #define USE_SPIRIT1_915MHz
+#else
+#error SPIRIT1 Nucleo Shield undefined or unsupported
+#endif
+
+/*  Uncomment the Link Layer features to be used */
+// #define USE_AUTO_ACK
+// #define USE_AUTO_ACK_PIGGYBACKING
+// #define USE_AUTO_RETRANSMISSION
+
+#if defined(USE_AUTO_ACK)&& defined(USE_AUTO_ACK_PIGGYBACKING)&& defined(USE_AUTO_RETRANSMISSION)
+#define USE_STack_PROTOCOL
+
+/* LLP configuration parameters */
+#define EN_AUTOACK                      S_ENABLE
+#define EN_PIGGYBACKING             	S_ENABLE
+#define MAX_RETRANSMISSIONS         	PKT_N_RETX_2
+
+#else
+#define USE_BASIC_PROTOCOL
+
+#endif
+
+/*  Uncomment the system Operating mode */
+//#define USE_LOW_POWER_MODE
+
+#if defined (USE_LOW_POWER_MODE)
+#define LPM_ENABLE
+#define MCU_STOP_MODE
+//#define MCU_SLEEP_MODE
+//#define RF_STANDBY
+#endif
+
+
+/* Exported constants --------------------------------------------------------*/
+
+/*  Radio configuration parameters  */
+#define XTAL_OFFSET_PPM             0
+#define INFINITE_TIMEOUT            0.0
+
+#ifdef USE_SPIRIT1_433MHz
+#define BASE_FREQUENCY              433.0e6
+#endif
+
+#ifdef USE_SPIRIT1_868MHz
+#define BASE_FREQUENCY              868.0e6
+#endif
+
+#ifdef USE_SPIRIT1_915MHz
+//#define BASE_FREQUENCY              915.0e6
+#define BASE_FREQUENCY              902.0e6
+#endif
+
+
+/*  Addresses configuration parameters  */
+#define EN_FILT_MY_ADDRESS          S_DISABLE
+#define MY_ADDRESS                  0x24
+#define EN_FILT_MULTICAST_ADDRESS   S_DISABLE
+#define MULTICAST_ADDRESS           0xEE
+#define EN_FILT_BROADCAST_ADDRESS   S_DISABLE
+#define BROADCAST_ADDRESS           0xFF
+#define DESTINATION_ADDRESS         0x44
+#define EN_FILT_SOURCE_ADDRESS      S_DISABLE
+#define SOURCE_ADDR_MASK            0xf0
+#define SOURCE_ADDR_REF             0x37
+
+#define APPLI_CMD                       0x11
+#define NWK_CMD                         0x22
+#define LED_TOGGLE                      0xff
+#define ACK_OK                          0x01
+#define MAX_BUFFER_LEN                  96
+#define TIME_TO_EXIT_RX                 3000
+#define DELAY_RX_LED_TOGGLE             200
+#define DELAY_TX_LED_GLOW               1000
+#define LPM_WAKEUP_TIME                 100
+#define DATA_SEND_TIME                  30
+
+#define PREAMBLE_LENGTH             PKT_PREAMBLE_LENGTH_04BYTES
+#define SYNC_LENGTH                 PKT_SYNC_LENGTH_4BYTES
+#define CONTROL_LENGTH              PKT_CONTROL_LENGTH_0BYTES
+#define EN_ADDRESS                  S_DISABLE
+#define EN_FEC                      S_DISABLE
+#define CHANNEL_NUMBER              1 // betzw - WAS: 0
+#define LENGTH_TYPE                 PKT_LENGTH_VAR
+#define POWER_INDEX                 7
+#define RECEIVE_TIMEOUT             2000.0 /*change the value for required timeout period*/
+#define RSSI_THRESHOLD              -120
+
+
+
+#define POWER_DBM                   11.6
+#define CHANNEL_SPACE               100e3
+#define FREQ_DEVIATION              127e3
+#define BANDWIDTH                   540.0e3
+#define MODULATION_SELECT           GFSK_BT1
+#define DATARATE                    250000
+#define XTAL_OFFSET_PPM             0
+#define SYNC_WORD                   0x88888888
+#define LENGTH_WIDTH                8 // betzw - NOTE: only 255 bytes for payload!!!
+#define CRC_MODE                    PKT_CRC_MODE_16BITS_2
+#define EN_WHITENING                S_DISABLE
+#define INFINITE_TIMEOUT            0.0
+
+// extern volatile FlagStatus xRxDoneFlag, xTxDoneFlag;
+// extern volatile FlagStatus PushButtonStatusWakeup;
+extern uint16_t wakeupCounter;
+extern uint16_t dataSendCounter ;
+// extern volatile FlagStatus PushButtonStatusData, datasendFlag;
+
+typedef struct
+{
+  uint8_t Cmdtag;
+  uint8_t CmdType;
+  uint8_t CmdLen;
+  uint8_t Cmd;
+  uint8_t DataLen;
+  uint8_t* DataBuff;
+}AppliFrame_t;
+
+/*---------------------------------------------------------------------------*/
+#endif /* __SPIRIT_H__ */
+/*---------------------------------------------------------------------------*/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/stm32l-spirit1-config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/stm32l-spirit1-config.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,98 @@
+/**
+  ******************************************************************************
+  * @file    stm32l-spirit1-config.h
+  * @author  MCD Application Team
+  * @version V3.4.0
+  * @date    29-June-2012
+  * @brief   Evaluation board specific configuration file.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32L_SPIRIT1_CONFIG_H
+#define __STM32L_SPIRIT1_CONFIG_H
+
+/* Includes ------------------------------------------------------------------*/
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* Define the STM32F10x hardware depending on the used evaluation board */
+#ifdef USE_STM3210B_EVAL
+  #define USB_DISCONNECT                      GPIOD  
+  #define USB_DISCONNECT_PIN                  GPIO_PIN_9
+  #define RCC_APB2Periph_GPIO_DISCONNECT      RCC_APB2Periph_GPIOD
+  #define EVAL_COM1_IRQHandler                USART1_IRQHandler 
+
+#elif defined (USE_STM3210E_EVAL)
+  #define USB_DISCONNECT                      GPIOB  
+  #define USB_DISCONNECT_PIN                  GPIO_PIN_14
+  #define RCC_APB2Periph_GPIO_DISCONNECT      RCC_APB2Periph_GPIOB
+  #define EVAL_COM1_IRQHandler                USART1_IRQHandler 
+
+#elif defined (USE_STM3210C_EVAL)
+  #define USB_DISCONNECT                      0  
+  #define USB_DISCONNECT_PIN                  0
+  #define RCC_APB2Periph_GPIO_DISCONNECT      0
+  #define EVAL_COM1_IRQHandler                USART2_IRQHandler 
+
+#elif defined (USE_STM32L152_EVAL) || defined (USE_STM32L152D_EVAL)
+ /* 
+   For STM32L15xx devices it is possible to use the internal USB pullup
+   controlled by register SYSCFG_PMC (refer to RM0038 reference manual for
+   more details).
+   It is also possible to use external pullup (and disable the internal pullup)
+   by setting the define USB_USE_EXTERNAL_PULLUP in file platform_config.h
+   and configuring the right pin to be used for the external pull up configuration.
+   To have more details on how to use an external pull up, please refer to 
+   STM3210E-EVAL evaluation board manuals.
+   */
+ /* Uncomment the following define to use an external pull up instead of the 
+    integrated STM32L15xx internal pull up. In this case make sure to set up
+    correctly the external required hardware and the GPIO defines below.*/
+/* #define USB_USE_EXTERNAL_PULLUP */
+
+ #if !defined(USB_USE_EXTERNAL_PULLUP)
+  #define STM32L15_USB_CONNECT                SYSCFG_USBPuCmd(ENABLE)
+  #define STM32L15_USB_DISCONNECT             SYSCFG_USBPuCmd(DISABLE)
+
+ #elif defined(USB_USE_EXTERNAL_PULLUP)
+  /* PA0 is chosen just as illustrating example, you should modify the defines
+    below according to your hardware configuration. */ 
+  #define USB_DISCONNECT                      GPIOA
+  #define USB_DISCONNECT_PIN                  GPIO_PIN_0
+  #define RCC_AHBPeriph_GPIO_DISCONNECT       RCC_AHBPeriph_GPIOA
+  #define STM32L15_USB_CONNECT                GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN)
+  #define STM32L15_USB_DISCONNECT             GPIO_SetBits(USB_DISCONNECT, USB_DISCONNECT_PIN)
+ #endif /* USB_USE_EXTERNAL_PULLUP */
+
+#ifdef USE_STM32L152_EVAL 
+ #define EVAL_COM1_IRQHandler              USART2_IRQHandler
+#elif defined (USE_STM32L152D_EVAL) 
+ #define EVAL_COM1_IRQHandler              USART1_IRQHandler
+#endif /*USE_STM32L152_EVAL*/
+
+#endif /* USE_STM3210B_EVAL */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+#endif /* __STM32L_SPIRIT1_CONFIG_H */
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/Release_Notes.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/Release_Notes.html	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,154 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head>
+
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<link rel="File-List" href="Library_files/filelist.xml">
+<link rel="Edit-Time-Data" href="Library_files/editdata.mso"><!--[if !mso]> <style> v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><title>Release Notes for SPIRIT1 Driver</title><!--[if gte mso 9]><xml> <o:DocumentProperties> <o:Author>STMicroelectronics</o:Author> <o:LastAuthor>STMicroelectronics</o:LastAuthor> <o:Revision>37</o:Revision> <o:TotalTime>136</o:TotalTime> <o:Created>2009-02-27T19:26:00Z</o:Created> <o:LastSaved>2009-03-01T17:56:00Z</o:LastSaved> <o:Pages>1</o:Pages> <o:Words>522</o:Words> <o:Characters>2977</o:Characters> <o:Company>STMicroelectronics</o:Company> <o:Lines>24</o:Lines> <o:Paragraphs>6</o:Paragraphs> <o:CharactersWithSpaces>3493</o:CharactersWithSpaces> <o:Version>11.6568</o:Version> </o:DocumentProperties> </xml><![endif]--><!--[if gte mso 9]><xml> <w:WordDocument> <w:Zoom>110</w:Zoom> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]-->
+
+
+
+<style>
+<!--
+/* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+{mso-style-parent:"";
+margin:0in;
+margin-bottom:.0001pt;
+mso-pagination:widow-orphan;
+font-size:12.0pt;
+font-family:"Times New Roman";
+mso-fareast-font-family:"Times New Roman";}
+h2
+{mso-style-next:Normal;
+margin-top:12.0pt;
+margin-right:0in;
+margin-bottom:3.0pt;
+margin-left:0in;
+mso-pagination:widow-orphan;
+page-break-after:avoid;
+mso-outline-level:2;
+font-size:14.0pt;
+font-family:Arial;
+font-weight:bold;
+font-style:italic;}
+a:link, span.MsoHyperlink
+{color:blue;
+text-decoration:underline;
+text-underline:single;}
+a:visited, span.MsoHyperlinkFollowed
+{color:blue;
+text-decoration:underline;
+text-underline:single;}
+p
+{mso-margin-top-alt:auto;
+margin-right:0in;
+mso-margin-bottom-alt:auto;
+margin-left:0in;
+mso-pagination:widow-orphan;
+font-size:12.0pt;
+font-family:"Times New Roman";
+mso-fareast-font-family:"Times New Roman";}
+@page Section1
+{size:8.5in 11.0in;
+margin:1.0in 1.25in 1.0in 1.25in;
+mso-header-margin:.5in;
+mso-footer-margin:.5in;
+mso-paper-source:0;}
+div.Section1
+{page:Section1;}
+-->
+</style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]--><!--[if gte mso 9]><xml> <o:shapedefaults v:ext="edit" spidmax="5122"/> </xml><![endif]--><!--[if gte mso 9]><xml> <o:shapelayout v:ext="edit"> <o:idmap v:ext="edit" data="1"/> </o:shapelayout></xml><![endif]-->
+<meta content="MCD Application Team" name="author"></head><body link="blue" vlink="blue">
+<div class="Section1">
+<p class="MsoNormal"><span style="font-family: Arial;"><o:p><br>
+</o:p></span></p>
+<div align="center">
+<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" cellspacing="0" width="900">
+<tbody>
+<tr>
+<td style="padding: 0cm;" valign="top">
+<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" cellspacing="0" width="900">
+<tbody>
+<tr>
+<td style="vertical-align: top;">
+<p class="MsoNormal"><span style="font-size: 8pt; font-family: Arial; color: blue;"><a href="../../../../Release_Notes.html">Back to Release page</a><o:p></o:p></span></p>
+</td>
+</tr>
+<tr style="">
+<td style="padding: 1.5pt;">
+<h1 style="margin-bottom: 18pt; text-align: center;" align="center"><span style="font-size: 20pt; font-family: Verdana; color: rgb(51, 102, 255);">Release
+Notes for SPIRIT1 Driver</span><span style="font-size: 20pt; font-family: Verdana;"><o:p></o:p></span></h1>
+<p class="MsoNormal" style="text-align: center;" align="center"><span style="font-size: 10pt; font-family: Arial; color: black;">Copyright
+2014 STMicroelectronics</span><span style="color: black;"><u1:p></u1:p><o:p></o:p></span></p>
+<p class="MsoNormal" style="text-align: center;" align="center"><span style="font-size: 10pt; font-family: Arial; color: black;"><img alt="" id="_x0000_i1025" src="../../../../_htmresc/st_logo.png" style="border: 0px solid ; width: 86px; height: 65px;"></span><span style="font-size: 10pt;"><o:p></o:p></span></p>
+</td>
+</tr>
+</tbody>
+</table>
+<p class="MsoNormal"><span style="font-family: Arial; display: none;"><o:p>&nbsp;</o:p></span></p>
+<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" width="900">
+<tbody>
+<tr style="">
+<td style="padding: 0cm;" valign="top">
+<span style="font-family: &quot;Times New Roman&quot;;">
+</span>
+<h2 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><a name="History"></a><span style="font-size: 12pt; color: white;">Update History</span></h2>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-right: 500pt; width: 200px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V3.0.1
+/ 10-Oct-2014</span></h3>
+<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main
+Changes<o:p></o:p></span></u></b></p>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<span style="font-size: 10pt; font-family: Verdana;"></span><span style="font-size: 10pt; font-family: Verdana;"></span>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<span style="font-size: 10pt; font-family: Verdana;"></span>
+<ul style="list-style-type: square;">
+<li><span style="font-size: 10pt; font-family: Verdana;">First
+official release.</span><span style="color: rgb(0, 0, 0); font-family: Verdana; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; display: inline ! important; float: none;"></span><span style="font-size: 10pt; font-family: Verdana;"></span><span style="font-size: 10pt; font-family: Verdana;"></span></li>
+</ul>
+<span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"></span>
+<h2 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><a name="License"></a><span style="font-size: 12pt; color: white;">License<o:p></o:p></span><br>
+</h2>
+
+
+<font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"). You may not use this file except in compliance with the License. You may obtain a copy of the License at:</span><br><br>
+
+
+<font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"><center>
+<a href=http://www.st.com/software_license_agreement_liberty_v2> http://www.st.com/software_license_agreement_liberty_v2</a></center></span><br><br>
+
+<font size="-1"><span style="font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;">Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+</a></span>
+
+</font>
+
+
+<p class="MsoNormal"><span style="font-size: 10pt; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;; color: black;"><o:p></o:p></span></p>
+<b><span style="font-size: 10pt; font-family: Verdana; color: black;"></span></b>
+<div class="MsoNormal" style="text-align: center;" align="center"><span style="color: black;">
+<hr align="center" size="2" width="100%"></span></div>
+<p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt; text-align: center;" align="center"><span style="font-size: 10pt; font-family: Verdana; color: black;">For
+complete documentation on</span><span style="font-size: 10pt; font-family: Verdana;"><span style="color: black;">&nbsp;SPIRIT1 Driver
+visit </span><u><span style="color: blue;"><a href="http://www.st.com/web/catalog/sense_power/FM1968/CL1976/SC1845/PF253167" target="_blank">www.st.com/SPIRIT1</a></span></u></span><span style="font-size: 10pt; font-family: Verdana;"><a target="_blank" href="http://www.st.com/web/catalog/sense_power/FM1968/CL1976/SC1898/PF258646"><u><span style="color: blue;"></span></u></a></span><span style="font-size: 10pt; font-family: Verdana;"><u><span style="color: blue;"></span></u></span><span style="color: black;"><o:p></o:p></span></p>
+</td>
+</tr>
+</tbody>
+</table>
+<p class="MsoNormal"><span style="font-size: 10pt;"><o:p></o:p></span></p>
+</td>
+</tr>
+</tbody>
+</table>
+</div>
+<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
+</div>
+</body></html>
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/MCU_Interface.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/MCU_Interface.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,152 @@
+/**
+ * @file    MCU_Interface.h
+ * @author  VMA division - AMS
+ * @version V2.0.2
+ * @date    Febrary 7, 2015
+ * @brief   Header file for low level SPIRIT SPI driver.
+ * @details
+ *
+ * This header file constitutes an interface to the SPI driver used to
+ * communicate with Spirit.
+ * It exports some function prototypes to write/read registers and FIFOs
+ * and to send command strobes.
+ * Since the Spirit libraries are totally platform independent, the implementation
+ * of these functions are not provided here. The user have to implement these functions
+ * taking care to keep the exported prototypes.
+ *
+ * These functions are:
+ *
+ * <ul>
+ * <li>SpiritSpiInit</i>
+ * <li>SpiritSpiWriteRegisters</i>
+ * <li>SpiritSpiReadRegisters</i>
+ * <li>SpiritSpiCommandStrobes</i>
+ * <li>SpiritSpiWriteLinearFifo</i>
+ * <li>SpiritSpiReadLinearFifo</i>
+ * </ul>
+ *
+ * @note An example of SPI driver implementation is available in the <i>Sdk_Eval</i> library.
+ *
+ * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+ * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+ * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * THIS SOURCE CODE IS PROTECTED BY A LICENSE.
+ * FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE LOCATED
+ * IN THE ROOT DIRECTORY OF THIS FIRMWARE PACKAGE.
+ *
+ * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
+ */
+
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __MCU_INTERFACE_H
+#define __MCU_INTERFACE_H
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/** @defgroup SPIRIT_SPI_Driver         SPI Driver
+ * @brief Header file for low level SPIRIT SPI driver.
+ * @details See the file <i>@ref MCU_Interface.h</i> for more details.
+ * @{
+ */
+
+
+
+/** @defgroup SPI_Exported_Types        SPI Exported Types
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup SPI_Exported_Constants    SPI Exported Constants
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup SPI_Exported_Macros       SPI Exported Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup SPI_Exported_Functions    SPI Exported Functions
+ * @{
+ */
+
+typedef SpiritStatus StatusBytes;
+
+void SdkEvalSpiInit(void);
+StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
+StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
+StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode);
+StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
+StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
+
+void SdkEvalEnterShutdown(void);
+void SdkEvalExitShutdown(void);
+SpiritFlagStatus SdkEvalCheckShutdown(void);
+
+#define SpiritEnterShutdown                                  SdkEvalEnterShutdown
+#define SpiritExitShutdown                                   SdkEvalExitShutdown
+#define SpiritCheckShutdown                                  (SpiritFlagStatus)SdkEvalCheckShutdown
+
+
+#define SpiritSpiInit                                                  SdkEvalSpiInit
+#define SpiritSpiWriteRegisters(cRegAddress, cNbBytes, pcBuffer)       SdkEvalSpiWriteRegisters(cRegAddress, cNbBytes, pcBuffer)
+#define SpiritSpiReadRegisters(cRegAddress, cNbBytes, pcBuffer)        SdkEvalSpiReadRegisters(cRegAddress, cNbBytes, pcBuffer)
+#define SpiritSpiCommandStrobes(cCommandCode)                          SdkEvalSpiCommandStrobes(cCommandCode)
+#define SpiritSpiWriteLinearFifo(cNbBytes, pcBuffer)                         SdkEvalSpiWriteFifo(cNbBytes, pcBuffer)
+#define SpiritSpiReadLinearFifo(cNbBytes, pcBuffer)                          SdkEvalSpiReadFifo(cNbBytes, pcBuffer)
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Aes.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Aes.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,205 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Aes.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT AES Engine.
+  *
+ * @details
+ *
+ * In order to encrypt data, the user must manage the AES_END IRQ.
+ * The data have to be splitted in blocks of 16 bytes and written
+ * into the <i>AES DATA IN registers</i>. Then, after the key is written
+ * into the <i>AES KEY registers</i>, a command of <i>Execute encryption</i>
+ * has to be sent.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *  SpiritAesWriteDataIn(data_buff , N_BYTES);
+ *  SpiritAesExecuteEncryption();
+ *
+ *  while(!aes_end_flag);       // the flag is set by the ISR routine which manages the AES_END irq
+ *  aes_end_flag=RESET;
+ *
+ *  SpiritAesReadDataOut(enc_data_buff , N_BYTES);
+ *
+ * @endcode
+ *
+ * In order to decrypt data, the user must manage the AES_END IRQ and have a decryption key.
+ * There are two operative modes to make the data decryption:
+ * <ul>
+ * <li> Derive the decryption key from the encryption key and decrypt data directly
+ * using the <i>SpiritAesDeriveDecKeyExecuteDec()</i> function
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *  SpiritAesWriteDataIn(enc_data_buff , N_BYTES);
+ *  SpiritAesDeriveDecKeyExecuteDec();
+ *
+ *  while(!aes_end_flag);       // the flag is set by the ISR routine which manages the AES_END irq
+ *  aes_end_flag=RESET;
+ *
+ *  SpiritAesReadDataOut(data_buff , N_BYTES);
+ *
+ * @endcode
+ * </li>
+ *
+ * <li> Derive the decryption key from the encryption key using the <i>SpiritAesDeriveDecKeyFromEnc()</i>
+ * function, store it into the <i>AES KEY registers</i> and then decrypt data using the
+ * <i>SpiritAesExecuteDecryption()</i> function
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *  SpiritAesWriteDataIn(key_enc , 16);
+ *  SpiritAesDeriveDecKeyFromEnc();
+ *
+ *  while(!aes_end_flag);       // the flag is set by the ISR routine which manages the AES_END irq
+ *  aes_end_flag=RESET;
+ *
+ *  SpiritAesReadDataOut(key_dec , 16);
+ *
+ *  SpiritAesWriteKey(key_dec);
+ *  SpiritAesWriteDataIn(enc_data_buff , 16);
+ *  SpiritAesExecuteDecryption();
+ *
+ *  while(!aes_end_flag);       // the flag is set by the ISR routine which manages the AES_END irq
+ *  aes_end_flag=RESET;
+ *
+ *  SpiritAesReadDataOut(data_buff , N_BYTES);
+ *
+ * @endcode
+ * </li>
+ * </ul>
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_AES_H
+#define __SPIRIT_AES_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_Aes AES
+ * @brief Configuration and management of SPIRIT AES Engine.
+ * @details See the file <i>@ref SPIRIT_Aes.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup Aes_Exported_Types AES Exported Types
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Aes_Exported_Constants     AES Exported Constants
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Aes_Exported_Macros        AES Exported Macros
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Aes_Exported_Functions     AES Exported Functions
+ * @{
+ */
+
+void SpiritAesMode(SpiritFunctionalState xNewState);
+void SpiritAesWriteDataIn(uint8_t* pcBufferDataIn, uint8_t cDataLength);
+void SpiritAesReadDataOut(uint8_t* pcBufferDataOut, uint8_t cDataLength);
+void SpiritAesWriteKey(uint8_t* pcKey);
+void SpiritAesReadKey(uint8_t* pcKey);
+void SpiritAesDeriveDecKeyFromEnc(void);
+void SpiritAesExecuteEncryption(void);
+void SpiritAesExecuteDecryption(void);
+void SpiritAesDeriveDecKeyExecuteDec(void);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Calibration.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Calibration.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,226 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Calibration.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT VCO-RCO calibration.
+  *
+ * @details
+ *
+ * This module allows the user to set some parameters which deal
+ * with the oscillators calibration.
+ * The state machine of Spirit contemplates some optional calibrating operations
+ * in the transition between the READY and the LOCK state.
+ * The user is allowed to enable or disable the automatic RCO/VCO calibration
+ * by calling the functions <i>@ref SpiritCalibrationVco()</i> and <i>@ref SpiritCalibrationRco()</i>.
+ * The following example shows how to do an initial calibration of VCO.
+ *
+ * <b>Example:</b>
+ * @code
+ *  uint8_t calData;
+ *
+ *  SpiritCalibrationVco(S_ENABLE);
+ *  SpiritCmdStrobeLockTx();
+ *
+ *  while(g_xStatus.MC_STATE != MC_STATE_LOCK){
+ *      SpiritRefreshStatus();
+ *  }
+ *
+ *  calData = SpiritCalibrationGetVcoCalDataTx();
+ *  SpiritCalibrationSetVcoCalDataTx(calData);
+ *
+ *  SpiritCmdStrobeReady();
+ *  SpiritCalibrationVco(S_DISABLE);
+ *
+ * @endcode
+ *
+ * Similar operations can be done for the RCO calibrator.
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_CALIBRATION_H
+#define __SPIRIT_CALIBRATION_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_Calibration Calibration
+ * @brief Configuration and management of SPIRIT VCO-RCO calibration.
+ * @details See the file <i>@ref SPIRIT_Calibration.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup Calibration_Exported_Types Calibration Exported Types
+ * @{
+ */
+
+
+/**
+ * @brief  VCO / RCO calibration window.
+ */
+typedef enum
+{
+
+  CALIB_TIME_7_33_US_24MHZ = 0x00,	/*!< calibration window of 7.33 us with XTAL=24MHz */
+  CALIB_TIME_14_67_US_24MHZ,		/*!< calibration window of 14.67 us with XTAL=24MHz */
+  CALIB_TIME_29_33_US_24MHZ,		/*!< calibration window of 29.33 us with XTAL=24MHz */
+  CALIB_TIME_58_67_US_24MHZ,		/*!< calibration window of 58.67 us with XTAL=24MHz */
+
+  CALIB_TIME_6_77_US_26MHZ = 0x00,	/*!< calibration window of 6.77 us with XTAL=26MHz */
+  CALIB_TIME_13_54_US_26MHZ,		/*!< calibration window of 13.54 us with XTAL=26MHz */
+  CALIB_TIME_27_08_US_26MHZ,		/*!< calibration window of 27.08 us with XTAL=26MHz */
+  CALIB_TIME_54_15_US_26MHZ		/*!< calibration window of 54.15 us with XTAL=26MHz */
+
+} VcoWin;
+
+
+#define IS_VCO_WIN(REF)   (REF == CALIB_TIME_7_33_US_24MHZ  ||\
+                           REF == CALIB_TIME_14_67_US_24MHZ ||\
+                           REF == CALIB_TIME_29_33_US_24MHZ ||\
+                           REF == CALIB_TIME_58_67_US_24MHZ ||\
+                           REF == CALIB_TIME_6_77_US_26MHZ  ||\
+                           REF == CALIB_TIME_13_54_US_26MHZ ||\
+                           REF == CALIB_TIME_27_08_US_26MHZ ||\
+                           REF == CALIB_TIME_54_15_US_26MHZ \
+                           )
+
+/**
+ * @brief  VCO_H / VCO_L selection.
+ */
+typedef enum
+{
+
+  VCO_L = 0x00,	        /*!< VCO lower */
+  VCO_H,		/*!< VCO higher */
+} VcoSel;
+
+
+#define IS_VCO_SEL(REF)   (REF == VCO_L  ||\
+                           REF == VCO_H \
+                           )
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Calibration_Exported_Constants     Calibration Exported Constants
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup VCO_Calibration   VCO Calibration
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+
+
+/**
+ * @defgroup Calibration_Exported_Macros        Calibration Exported Macros
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Calibration_Exported_Functions     Calibration Exported Functions
+ * @{
+ */
+
+void SpiritCalibrationRco(SpiritFunctionalState xNewState);
+void SpiritCalibrationVco(SpiritFunctionalState xNewState);
+void SpiritCalibrationSetRcoCalWords(uint8_t cRwt, uint8_t cRfb);
+void SpiritCalibrationGetRcoCalWords(uint8_t* pcRwt, uint8_t* pcRfb);
+uint8_t SpiritCalibrationGetVcoCalData(void);
+void SpiritCalibrationSetVcoCalDataTx(uint8_t cVcoCalData);
+uint8_t SpiritCalibrationGetVcoCalDataTx(void);
+void SpiritCalibrationSetVcoCalDataRx(uint8_t cVcoCalData);
+uint8_t SpiritCalibrationGetVcoCalDataRx(void);
+void SpiritCalibrationSetVcoWindow(VcoWin xRefWord);
+VcoWin SpiritCalibrationGetVcoWindow(void);
+VcoSel SpiritCalibrationGetVcoSelecttion(void);
+void SpiritCalibrationSelectVco(VcoSel xVco);
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Commands.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Commands.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,336 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Commands.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Management of SPIRIT Commands.
+  *
+ * @details
+ *
+ * In this module can be found all the API used to strobe commands to
+ * Spirit.
+ * Every command strobe is an SPI transaction with a specific command code.
+ *
+ * <b>Example:</b>
+ * @code
+ *   ...
+ *
+ *   SpiritCmdStrobeRx();
+ *
+ *   ...
+ * @endcode
+ *
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_COMMANDS_H
+#define __SPIRIT_COMMANDS_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_Commands    Commands
+ * @brief Management of SPIRIT Commands.
+ * @details See the file <i>@ref SPIRIT_Commands.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup Commands_Exported_Types    Commands Exported Types
+ * @{
+ */
+
+/**
+  * @brief  SPIRIT Commands codes enumeration
+  */
+typedef enum
+{
+  CMD_TX =  COMMAND_TX,                           /*!< Start to transmit; valid only from READY */
+  CMD_RX =  COMMAND_RX,                           /*!< Start to receive; valid only from READY */
+  CMD_READY =  COMMAND_READY,                     /*!< Go to READY; valid only from STANDBY or SLEEP or LOCK */
+  CMD_STANDBY =  COMMAND_STANDBY,                 /*!< Go to STANDBY; valid only from READY */
+  CMD_SLEEP = COMMAND_SLEEP,                      /*!< Go to SLEEP; valid only from READY */
+  CMD_LOCKRX = COMMAND_LOCKRX,                    /*!< Go to LOCK state by using the RX configuration of the synth; valid only from READY */
+  CMD_LOCKTX = COMMAND_LOCKTX,                    /*!< Go to LOCK state by using the TX configuration of the synth; valid only from READY */
+  CMD_SABORT = COMMAND_SABORT,                    /*!< Force exit form TX or RX states and go to READY state; valid only from TX or RX */
+  CMD_LDC_RELOAD = COMMAND_LDC_RELOAD,            /*!< LDC Mode: Reload the LDC timer with the value stored in the  LDC_PRESCALER / COUNTER  registers; valid from all states  */
+  CMD_SEQUENCE_UPDATE =  COMMAND_SEQUENCE_UPDATE, /*!< Autoretransmission: Reload the Packet sequence counter with the value stored in the PROTOCOL[2] register valid from all states */
+  CMD_AES_ENC = COMMAND_AES_ENC,                  /*!< Commands: Start the encryption routine; valid from all states; valid from all states */
+  CMD_AES_KEY = COMMAND_AES_KEY,                  /*!< Commands: Start the procedure to compute the key for the decryption; valid from all states */
+  CMD_AES_DEC = COMMAND_AES_DEC,                  /*!< Commands: Start the decryption routine using the current key; valid from all states */
+  CMD_AES_KEY_DEC = COMMAND_AES_KEY_DEC,          /*!< Commands: Compute the key and start the decryption; valid from all states */
+  CMD_SRES = COMMAND_SRES,                        /*!< Reset of all digital part, except SPI registers */
+  CMD_FLUSHRXFIFO = COMMAND_FLUSHRXFIFO,          /*!< Clean the RX FIFO; valid from all states */
+  CMD_FLUSHTXFIFO = COMMAND_FLUSHTXFIFO,          /*!< Clean the TX FIFO; valid from all states */
+} SpiritCmd;
+
+#define IS_SPIRIT_CMD(CMD)  (CMD == CMD_TX || \
+                             CMD == CMD_RX || \
+                             CMD == CMD_READY || \
+                             CMD == CMD_STANDBY || \
+                             CMD == CMD_SLEEP || \
+                             CMD == CMD_LOCKRX || \
+                             CMD == CMD_LOCKTX || \
+                             CMD == CMD_SABORT || \
+                             CMD == CMD_LDC_RELOAD || \
+                             CMD == CMD_SEQUENCE_UPDATE || \
+                             CMD == CMD_AES_ENC || \
+                             CMD == CMD_AES_KEY || \
+                             CMD == CMD_AES_DEC || \
+                             CMD == CMD_AES_KEY_DEC || \
+                             CMD == CMD_SRES || \
+                             CMD == CMD_FLUSHRXFIFO || \
+                             CMD == CMD_FLUSHTXFIFO \
+                            )
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Commands_Exported_Constants        Commands Exported Constants
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Commands_Exported_Macros   Commands Exported Macros
+ * @{
+ */
+
+/**
+ * @brief  Sends the TX command to SPIRIT. Start to transmit.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeTx()      {SpiritManagementWaCmdStrobeTx(); \
+                                  SpiritCmdStrobeCommand(CMD_TX);} 
+
+
+/**
+ * @brief  Sends the RX command to SPIRIT. Start to receive.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeRx()      {SpiritManagementWaCmdStrobeRx(); \
+                                  SpiritCmdStrobeCommand(CMD_RX); \
+                                  } 
+
+
+/**
+ * @brief  Sends the Ready state command to SPIRIT. Go to READY.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeReady()          SpiritCmdStrobeCommand(CMD_READY)
+
+
+
+/**
+ * @brief  Sends the Standby command to SPIRIT. Go to STANDBY.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeStandby()        SpiritCmdStrobeCommand(CMD_STANDBY)
+
+
+
+/**
+ * @brief  Sends the Sleep command to SPIRIT. Go to SLEEP.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeSleep()          SpiritCmdStrobeCommand(CMD_SLEEP)
+
+
+
+/**
+ * @brief  Sends the LOCK_RX command to SPIRIT. Go to the LOCK state by using the RX configuration of the synthesizer.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeLockRx()         SpiritCmdStrobeCommand(CMD_LOCKRX)
+
+
+
+/**
+ * @brief  Sends the LOCK_TX command to SPIRIT. Go to the LOCK state by using the TX configuration of the synthesizer.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeLockTx()         SpiritCmdStrobeCommand(CMD_LOCKTX)
+
+
+
+/**
+ * @brief  Sends the SABORT command to SPIRIT. Exit from TX or RX states and go to READY state.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeSabort()         SpiritCmdStrobeCommand(CMD_SABORT)
+
+
+/**
+ * @brief  Sends the LDC_RELOAD command to SPIRIT. Reload the LDC timer with the value stored in the LDC_PRESCALER / COUNTER registers.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeLdcReload()      SpiritCmdStrobeCommand(CMD_LDC_RELOAD)
+
+
+
+/**
+ * @brief  Sends the SEQUENCE_UPDATE command to SPIRIT. Reload the Packet sequence counter with the value stored in the PROTOCOL[2] register.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeSequenceUpdate() SpiritCmdStrobeCommand(CMD_SEQUENCE_UPDATE)
+
+
+
+/**
+ * @brief  Sends the AES_ENC command to SPIRIT. Starts the encryption routine.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeAesEnc()         SpiritCmdStrobeCommand(CMD_AES_ENC)
+
+
+
+/**
+ * @brief  Sends the AES_KEY command to SPIRIT. Starts the procedure to compute the key for the decryption.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeAesKey()         SpiritCmdStrobeCommand(CMD_AES_KEY)
+
+
+
+/**
+ * @brief  Sends the AES_DEC command to SPIRIT. Starts the decryption using the current key.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeAesDec()         SpiritCmdStrobeCommand(CMD_AES_DEC)
+
+
+
+/**
+ * @brief  Sends the KEY_DEC command to SPIRIT. Computes the key derivation and start the decryption.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeAesKeyDec()     SpiritCmdStrobeCommand(CMD_AES_KEY_DEC)
+
+/**
+ * @brief  Sends the SRES command to SPIRIT. Partial reset: all digital circuit will be reset (exception for SPI only).
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeSres()          SpiritCmdStrobeCommand(CMD_SRES)  
+  
+
+/**
+ * @brief  Sends the FLUSHRXFIFO command to SPIRIT. Clean the RX FIFO.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeFlushRxFifo()    SpiritCmdStrobeCommand(CMD_FLUSHRXFIFO)
+
+
+
+/**
+ * @brief  Sends the FLUSHTXFIFO command to SPIRIT. Clean the TX FIFO.
+ * @param  None.
+ * @retval None.
+ */
+#define SpiritCmdStrobeFlushTxFifo()    SpiritCmdStrobeCommand(CMD_FLUSHTXFIFO)
+
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Commands_Exported_Functions    Commands Exported Functions
+ * @{
+ */
+void SpiritCmdStrobeCommand(SpiritCmd xCommandCode);
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Config.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,147 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Config.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Spirit Configuration and useful defines 
+  * 
+ * @details
+ *
+ * This file is used to include all or a part of the Spirit
+ * libraries into the application program which will be used.
+ * Moreover some important parameters are defined here and the
+ * user is allowed to edit them.
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_CONFIG_H
+#define __SPIRIT_CONFIG_H
+
+
+  /* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Aes.h"
+#include "SPIRIT_Calibration.h"
+#include "SPIRIT_Commands.h"
+#include "SPIRIT_Csma.h"
+#include "SPIRIT_DirectRF.h"
+#include "SPIRIT_General.h"
+#include "SPIRIT_Gpio.h"
+#include "SPIRIT_Irq.h"
+#include "SPIRIT_Timer.h"
+#include "SPIRIT_LinearFifo.h"
+#include "SPIRIT_PktBasic.h"
+#include "SPIRIT_PktMbus.h"
+#include "SPIRIT_PktStack.h"
+
+#include "SPIRIT_Qi.h"
+#include "SPIRIT_Radio.h"
+#include "MCU_Interface.h"
+#include "SPIRIT_Types.h"
+#include "SPIRIT_Management.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @addtogroup SPIRIT_Libraries        SPIRIT Libraries
+ * @brief This firmware implements libraries which allow the user
+ * to manage the features of Spirit without knowing the hardware details.
+ * @details The <i>SPIRIT_Libraries</i> modules are totally platform independent. The library provides one
+ * module for each device feature. Each module refers to some functions whose prototypes are located in the
+ * header file <i>@ref MCU_Interface.h</i>. The user who want to use these libraries on a particular
+ * platform has to implement these functions respecting them signatures.
+ * @{
+ */
+
+/** @defgroup SPIRIT_Configuration      Configuration
+ * @brief Spirit Configuration and useful defines.
+ * @details See the file <i>@ref SPIRIT_Config.h</i> for more details.
+ * @{
+ */
+
+
+/** @defgroup Configuration_Exported_Types      Configuration Exported Types
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Configuration_Exported_Constants  Configuration Exported Constants
+ * @{
+ */
+#define DOUBLE_XTAL_THR                         30000000
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Configuration_Exported_Macros     Configuration Exported Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Configuration_Exported_Functions  Configuration Exported Functions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Csma.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Csma.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,263 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Csma.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT CSMA.
+ * @details
+ *
+ * The Spirit CSMA feature, when configured and enabled, is transparent
+ * for the user. It means the user has only to call the <i>@ref SpiritCsmaInit()</i>
+ * function on a filled structure and then enable the CSMA policy using the <i>@ref SpiritCsma()</i>
+ * function.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ * CsmaInit csmaInit={
+ *   S_DISABLE,         // persistent mode
+ *   TBIT_TIME_64,      // Tbit time
+ *   TCCA_TIME_3,       // Tcca time
+ *   5,                 // max number of backoffs
+ *   0xFA21,            // BU counter seed
+ *   32                 // CU prescaler
+ * };
+ *
+ * ...
+ *
+ * SpiritCsmaInit(&csmaInit);
+ * SpiritCsma(S_ENABLE);
+ *
+ *
+ * @endcode
+ *
+ * @note The CS status depends of the RSSI threshold set. Please see the Spirit_Qi
+ * module for details.
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_CSMA_H
+#define __SPIRIT_CSMA_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Types.h"
+#include "SPIRIT_Regs.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_Csma        CSMA
+ * @brief Configuration and management of SPIRIT CSMA.
+ * @details See the file <i>@ref SPIRIT_Csma.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup Csma_Exported_Types        CSMA Exported Types
+ * @{
+ */
+
+
+/**
+ * @brief  Multiplier for Tcca time enumeration (Tcca = Multiplier*Tbit).
+ */
+typedef enum
+{
+  TBIT_TIME_64 = CSMA_CCA_PERIOD_64TBIT,      /*!< CSMA/CA: Sets CCA period to 64*TBIT */
+  TBIT_TIME_128 = CSMA_CCA_PERIOD_128TBIT,    /*!< CSMA/CA: Sets CCA period to 128*TBIT */
+  TBIT_TIME_256 = CSMA_CCA_PERIOD_256TBIT,    /*!< CSMA/CA: Sets CCA period to 256*TBIT */
+  TBIT_TIME_512 = CSMA_CCA_PERIOD_512TBIT,    /*!< CSMA/CA: Sets CCA period to 512*TBIT */
+}CcaPeriod;
+
+#define IS_CCA_PERIOD(PERIOD)   (PERIOD == TBIT_TIME_64 || \
+				 PERIOD == TBIT_TIME_128 || \
+				 PERIOD == TBIT_TIME_256 || \
+				 PERIOD == TBIT_TIME_512)
+
+
+/**
+ * @brief  Multiplier of Tcca time enumeration to obtain Tlisten (Tlisten = [1...15]*Tcca).
+ */
+typedef enum
+{
+  TCCA_TIME_0   = 0x00,     /*!< CSMA/CA: Sets CCA length to 0 */
+  TCCA_TIME_1   = 0x10,     /*!< CSMA/CA: Sets CCA length to 1*TLISTEN */
+  TCCA_TIME_2   = 0x20,     /*!< CSMA/CA: Sets CCA length to 2*TLISTEN */
+  TCCA_TIME_3   = 0x30,     /*!< CSMA/CA: Sets CCA length to 3*TLISTEN */
+  TCCA_TIME_4   = 0x40,     /*!< CSMA/CA: Sets CCA length to 4*TLISTEN */
+  TCCA_TIME_5   = 0x50,     /*!< CSMA/CA: Sets CCA length to 5*TLISTEN */
+  TCCA_TIME_6   = 0x60,     /*!< CSMA/CA: Sets CCA length to 6*TLISTEN */
+  TCCA_TIME_7   = 0x70,     /*!< CSMA/CA: Sets CCA length to 7*TLISTEN */
+  TCCA_TIME_8   = 0x80,     /*!< CSMA/CA: Sets CCA length to 8*TLISTEN */
+  TCCA_TIME_9   = 0x90,     /*!< CSMA/CA: Sets CCA length to 9*TLISTEN */
+  TCCA_TIME_10  = 0xA0,     /*!< CSMA/CA: Sets CCA length to 10*TLISTEN */
+  TCCA_TIME_11  = 0xB0,     /*!< CSMA/CA: Sets CCA length to 11*TLISTEN */
+  TCCA_TIME_12  = 0xC0,     /*!< CSMA/CA: Sets CCA length to 12*TLISTEN */
+  TCCA_TIME_13  = 0xD0,     /*!< CSMA/CA: Sets CCA length to 13*TLISTEN */
+  TCCA_TIME_14  = 0xE0,     /*!< CSMA/CA: Sets CCA length to 14*TLISTEN */
+  TCCA_TIME_15  = 0xF0,     /*!< CSMA/CA: Sets CCA length to 15*TLISTEN */
+}CsmaLength;
+
+#define IS_CSMA_LENGTH(LENGTH)	(LENGTH == TCCA_TIME_0 || \
+                                 LENGTH == TCCA_TIME_1 || \
+				 LENGTH == TCCA_TIME_2 || \
+				 LENGTH == TCCA_TIME_3 || \
+				 LENGTH == TCCA_TIME_4 || \
+				 LENGTH == TCCA_TIME_5 || \
+				 LENGTH == TCCA_TIME_6 || \
+				 LENGTH == TCCA_TIME_7 || \
+				 LENGTH == TCCA_TIME_8 || \
+				 LENGTH == TCCA_TIME_9 || \
+				 LENGTH == TCCA_TIME_10 || \
+				 LENGTH == TCCA_TIME_11 || \
+				 LENGTH == TCCA_TIME_12 || \
+				 LENGTH == TCCA_TIME_13 || \
+				 LENGTH == TCCA_TIME_14 || \
+				 LENGTH == TCCA_TIME_15)
+
+
+/**
+  * @brief  SPIRIT CSMA Init structure definition
+  */
+typedef struct
+{
+  SpiritFunctionalState     xCsmaPersistentMode;          /*!< Specifies if the CSMA persistent mode has to be on or off.
+                                                               This parameter can be S_ENABLE or S_DISABLE */
+  CcaPeriod                 xMultiplierTbit;              /*!< Specifies the Tbit multiplier to obtain the Tcca.
+                                                               This parameter can be a value of @ref CcaPeriod */
+  CsmaLength                xCcaLength;                   /*!< Specifies the Tcca multiplier to determinate the Tlisten.
+                                                               This parameter can be a value of @ref CsmaLength. */
+  uint8_t                   cMaxNb;                       /*!< Specifies the max number of backoff cycles. Not used in persistent mode.
+                                                               This parameter is an uint8_t. */
+  uint16_t                  nBuCounterSeed;               /*!< Specifies the BU counter seed. Not used in persistent mode.
+                                                               This parameter can be a value of 16 bits. */
+  uint8_t                   cBuPrescaler;                 /*!< Specifies the BU prescaler. Not used in persistent mode.
+                                                               This parameter can be a value of 6 bits. */
+}CsmaInit;
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Csma_Exported_Constants    CSMA Exported Constants
+ * @{
+ */
+
+/**
+ * @defgroup Csma_Parameters            CSMA Parameters
+ * @{
+ */
+
+#define IS_BU_COUNTER_SEED(SEED)	(SEED!=0)
+#define IS_BU_PRESCALER(PRESCALER)	(PRESCALER<64)
+#define IS_CMAX_NB(NB)			(NB<8)
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Csma_Exported_Macros       CSMA Exported Macros
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Csma_Exported_Functions    CSMA Exported Functions
+ * @{
+ */
+
+void SpiritCsmaInit(CsmaInit* pxCsmaInit);
+void SpiritCsmaGetInfo(CsmaInit* pxCsmaInit);
+void SpiritCsma(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritCsmaGetCsma(void);
+void SpiritCsmaPersistentMode(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritCsmaGetPersistentMode(void);
+void SpiritCsmaSeedReloadMode(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritCsmaGetSeedReloadMode(void);
+void SpiritCsmaSetBuCounterSeed(uint16_t nBuCounterSeed);
+uint16_t SpiritCsmaGetBuCounterSeed(void);
+void SpiritCsmaSetBuPrescaler(uint8_t cBuPrescaler);
+uint8_t SpiritCsmaGetBuPrescaler(void);
+void SpiritCsmaSetCcaPeriod(CcaPeriod xMultiplierTbit);
+CcaPeriod SpiritCsmaGetCcaPeriod(void);
+void SpiritCsmaSetCcaLength(CsmaLength xCcaLength);
+uint8_t SpiritCsmaGetCcaLength(void);
+void SpiritCsmaSetMaxNumberBackoff(uint8_t cMaxNb);
+uint8_t SpiritCsmaGetMaxNumberBackoff(void);
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_DirectRF.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_DirectRF.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,165 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_DirectRF.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT direct transmission / receive modes.
+ * @details
+ *
+ * This module contains functions to manage the direct Tx/Rx mode.
+ * The user can choose the way to send data to Spirit through the
+ * enumerative types <i>@ref DirectTx</i>/<i>@ref DirectRx</i>.
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT1_DIRECT_RF_H
+#define __SPIRIT1_DIRECT_RF_H
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_DirectRf    Direct RF
+ * @brief Configuration and management of SPIRIT direct transmission / receive modes.
+ * @details See the file <i>@ref SPIRIT_DirectRF.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup DirectRf_Exported_Types    Direct RF Exported Types
+ * @{
+ */
+
+/**
+ * @brief  Direct transmission mode enumeration for SPIRIT.
+ */
+typedef enum
+{
+  NORMAL_TX_MODE = 0x00,          /*!< Normal mode, no direct transmission is used */
+  DIRECT_TX_FIFO_MODE = 0x04,     /*!< Source is FIFO: payload bits are continuously read from the TX FIFO */
+  DIRECT_TX_GPIO_MODE = 0x08,     /*!< Source is GPIO: payload bits are continuously read from one of the GPIO ports and transmitted without any processing */
+  PN9_TX_MODE = 0x0C              /*!< A pseudorandom binary sequence is generated internally */
+}DirectTx;
+
+#define IS_DIRECT_TX(MODE)  (((MODE) == NORMAL_TX_MODE) || \
+			     ((MODE) == DIRECT_TX_FIFO_MODE) || \
+                             ((MODE) == DIRECT_TX_GPIO_MODE)  || \
+                             ((MODE) == PN9_TX_MODE))
+
+/**
+ * @brief  Direct receive mode enumeration for SPIRIT.
+ */
+typedef enum
+{
+  NORMAL_RX_MODE = 0x00,          /*!< Normal mode, no direct reception is used */
+  DIRECT_RX_FIFO_MODE = 0x10,     /*!< Destination is FIFO: payload bits are continuously written to the RX FIFO and not subjected to any processing*/
+  DIRECT_RX_GPIO_MODE = 0x20      /*!< Destination is GPIO: payload bits are continuously written to one of the GPIO ports and not subjected to any processing*/
+}DirectRx;
+
+#define IS_DIRECT_RX(MODE)  (((MODE) == NORMAL_RX_MODE) || \
+		             ((MODE) == DIRECT_RX_FIFO_MODE) || \
+		             ((MODE) == DIRECT_RX_GPIO_MODE))
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup DirectRf_Exported_Constants        Direct RF Exported Constants
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup DirectRf_Exported_Macros           Direct RF Exported Macros
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup DirectRf_Exported_Functions        Direct RF Exported Functions
+ * @{
+ */
+
+void SpiritDirectRfSetRxMode(DirectRx xDirectRx);
+DirectRx SpiritDirectRfGetRxMode(void);
+void SpiritDirectRfSetTxMode(DirectTx xDirectTx);
+DirectTx SpiritDirectRfGetTxMode(void);
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_General.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_General.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,227 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_General.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT General functionalities.
+ * @details
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_GENERAL_H
+#define __SPIRIT_GENERAL_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_General     General
+ * @brief Configuration and management of SPIRIT General functionalities.
+ * @details See the file <i>@ref SPIRIT_General.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup General_Exported_Types     General Exported Types
+ * @{
+ */
+
+
+/**
+ * @brief  SPIRIT ModeExtRef enumeration
+ */
+
+typedef enum
+{
+  MODE_EXT_XO = 0,
+  MODE_EXT_XIN = !MODE_EXT_XO
+} ModeExtRef;
+
+#define IS_MODE_EXT(MODE)   (MODE == MODE_EXT_XO || \
+                             MODE == MODE_EXT_XIN)
+
+
+/**
+ * @brief  SPIRIT BatteryLevel enumeration
+ */
+
+typedef enum
+{
+  BLD_LVL_2_7_V = 0,
+  BLD_LVL_2_5_V = 1,
+  BLD_LVL_2_3_V = 2,
+  BLD_LVL_2_1_V = 3
+} BatteryLevel;
+
+#define IS_BLD_LVL(MODE)  (MODE == BLD_LVL_2_7_V || \
+                           MODE == BLD_LVL_2_5_V || \
+                           MODE == BLD_LVL_2_3_V || \
+                           MODE == BLD_LVL_2_1_V)
+
+
+/**
+ * @brief  SPIRIT GmConf enumeration
+ */
+
+typedef enum
+{
+  GM_SU_13_2 = 0,
+  GM_SU_18_2,
+  GM_SU_21_5,
+  GM_SU_25_6,
+  GM_SU_28_8,
+  GM_SU_33_9,
+  GM_SU_38_5,
+  GM_SU_43_0
+} GmConf;
+
+#define IS_GM_CONF(MODE)    (MODE == GM_SU_13_2 || \
+                             MODE == GM_SU_18_2 || \
+                             MODE == GM_SU_21_5 || \
+                             MODE == GM_SU_25_6 || \
+                             MODE == GM_SU_28_8 || \
+                             MODE == GM_SU_33_9 || \
+                             MODE == GM_SU_38_5 || \
+                             MODE == GM_SU_43_0)
+
+
+/**
+ * @brief  SPIRIT packet type enumeration
+ */
+
+typedef enum
+{
+  PKT_BASIC = 0x00,
+  PKT_MBUS = 0x02,
+  PKT_STACK
+
+} PacketType;
+
+#define IS_PKT_TYPE(TYPE)    (TYPE == PKT_BASIC || \
+                             TYPE == PKT_MBUS || \
+                             TYPE == PKT_STACK || \
+                             )
+
+
+/**
+ * @brief  SPIRIT version type enumeration
+ */
+
+typedef enum
+{
+  SPIRIT_VERSION_2_1 = 0x01,    /* Deprecated */
+  SPIRIT_VERSION_3_0,           /* The only version of SPIRIT1 */
+} SpiritVersion;
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup General_Exported_Constants         General Exported Constants
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup General_Exported_Macros            General Exported Macros
+ * @{
+ */
+#define SpiritGeneralLibraryVersion() "Spirit1_Libraries_v.3.2.0"
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup General_Exported_Functions         General Exported Functions
+ * @{
+ */
+
+
+void SpiritGeneralBatteryLevel(SpiritFunctionalState xNewState);
+void SpiritGeneralSetBatteryLevel(BatteryLevel xBatteryLevel);
+BatteryLevel SpiritGeneralGetBatteryLevel(void);
+void SpiritGeneralBrownOut(SpiritFunctionalState xNewState);
+void SpiritGeneralHighPwr(SpiritFunctionalState xNewState);
+void SpiritGeneralSetExtRef(ModeExtRef xExtMode);
+ModeExtRef SpiritGeneralGetExtRef(void);
+void SpiritGeneralSetXoGm(GmConf xGm);
+GmConf SpiritGeneralGetXoGm(void);
+PacketType SpiritGeneralGetPktType(void);
+uint16_t SpiritGeneralGetDevicePartNumber(void);
+uint8_t SpiritGeneralGetSpiritVersion(void);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Gpio.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Gpio.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,405 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Gpio.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   This file provides all the low level API to manage SPIRIT GPIO.
+  * 
+ * @details
+ *
+ * This module can be used to configure the Spirit GPIO pins to perform
+ * specific functions.
+ * The structure <i>@ref gpioIRQ</i> can be used to specify these features for
+ * one of the four Spirit Gpio pin.
+ * The following example shows how to configure a pin (GPIO 3) to be used as an IRQ source
+ * for a microcontroller using the <i>@ref SpiritGpioInit()</i> function.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ * SGpioInit gpioIRQ={
+ *   SPIRIT_GPIO_3,
+ *   SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP,
+ *   SPIRIT_GPIO_DIG_OUT_IRQ
+ * };
+ *
+ * ...
+ *
+ * SpiritGpioInit(&gpioIRQ);
+ *
+ * @endcode
+ *
+ * @note Please read the functions documentation for the other GPIO features.
+ *
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_GPIO_H
+#define __SPIRIT_GPIO_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/** @defgroup SPIRIT_Gpio       GPIO
+ * @brief Configuration and management of SPIRIT GPIO.
+ * @details See the file <i>@ref SPIRIT_Gpio.h</i> for more details.
+ * @{
+ */
+
+
+
+/** @defgroup Gpio_Exported_Types       GPIO Exported Types
+ * @{
+ */
+
+/**
+ * @brief  SPIRIT GPIO pin enumeration.
+ */
+typedef enum
+{
+  SPIRIT_GPIO_0  = GPIO0_CONF_BASE, /*!< GPIO_0 selected */
+  SPIRIT_GPIO_1  = GPIO1_CONF_BASE, /*!< GPIO_1 selected */
+  SPIRIT_GPIO_2  = GPIO2_CONF_BASE, /*!< GPIO_2 selected */
+  SPIRIT_GPIO_3  = GPIO3_CONF_BASE  /*!< GPIO_3 selected */
+}SpiritGpioPin;
+
+
+#define IS_SPIRIT_GPIO(PIN)  ((PIN == SPIRIT_GPIO_0) || \
+                              (PIN == SPIRIT_GPIO_1) || \
+                              (PIN == SPIRIT_GPIO_2) || \
+                              (PIN == SPIRIT_GPIO_3))
+
+
+/**
+ * @brief  SPIRIT GPIO mode enumeration.
+ */
+typedef enum
+{
+  SPIRIT_GPIO_MODE_DIGITAL_INPUT      = 0x01, /*!< Digital Input on GPIO */
+  SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP  = 0x02, /*!< Digital Output on GPIO (low current) */
+  SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_HP  = 0x03  /*!< Digital Output on GPIO (high current) */
+}SpiritGpioMode;
+
+#define IS_SPIRIT_GPIO_MODE(MODE)   ((MODE == SPIRIT_GPIO_MODE_DIGITAL_INPUT) || \
+                                     (MODE == SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_LP) || \
+                                     (MODE == SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_HP))
+
+
+
+/**
+ * @brief  SPIRIT I/O selection enumeration.
+ */
+typedef enum
+{
+  SPIRIT_GPIO_DIG_OUT_IRQ                               = 0x00, /*!< nIRQ (Interrupt Request, active low) , default configuration after POR */
+  SPIRIT_GPIO_DIG_OUT_POR_INV                           = 0x08, /*!< POR inverted (active low) */
+  SPIRIT_GPIO_DIG_OUT_WUT_EXP                           = 0x10, /*!< Wake-Up Timer expiration: "1" when WUT has expired */
+  SPIRIT_GPIO_DIG_OUT_LBD                               = 0x18, /*!< Low battery detection: "1" when battery is below threshold setting */
+  SPIRIT_GPIO_DIG_OUT_TX_DATA                           = 0x20, /*!< TX data internal clock output (TX data are sampled on the rising edge of it) */
+  SPIRIT_GPIO_DIG_OUT_TX_STATE                          = 0x28, /*!< TX state indication: "1" when Spirit1 is passing in the TX state */
+  SPIRIT_GPIO_DIG_OUT_TX_FIFO_ALMOST_EMPTY              = 0x30, /*!< TX FIFO Almost Empty Flag */
+  SPIRIT_GPIO_DIG_OUT_TX_FIFO_ALMOST_FULL               = 0x38, /*!< TX FIFO Almost Full Flag */
+  SPIRIT_GPIO_DIG_OUT_RX_DATA                           = 0x40, /*!< RX data output */
+  SPIRIT_GPIO_DIG_OUT_RX_CLOCK                          = 0x48, /*!< RX clock output (recovered from received data) */
+  SPIRIT_GPIO_DIG_OUT_RX_STATE                          = 0x50, /*!< RX state indication: "1" when Spirit1 is passing in the RX state */
+  SPIRIT_GPIO_DIG_OUT_RX_FIFO_ALMOST_FULL               = 0x58, /*!< RX FIFO Almost Full Flag */
+  SPIRIT_GPIO_DIG_OUT_RX_FIFO_ALMOST_EMPTY              = 0x60, /*!< RX FIFO Almost Empty Flag */
+  SPIRIT_GPIO_DIG_OUT_ANTENNA_SWITCH                    = 0x68, /*!< Antenna switch used for antenna diversity  */
+  SPIRIT_GPIO_DIG_OUT_VALID_PREAMBLE                    = 0x70, /*!< Valid Preamble Detected Flag */
+  SPIRIT_GPIO_DIG_OUT_SYNC_DETECTED                     = 0x78, /*!< Sync WordSync Word Detected Flag */
+  SPIRIT_GPIO_DIG_OUT_RSSI_THRESHOLD                    = 0x80, /*!< RSSI above threshold */
+  SPIRIT_GPIO_DIG_OUT_MCU_CLOCK                         = 0x88, /*!< MCU Clock */
+  SPIRIT_GPIO_DIG_OUT_TX_RX_MODE                        = 0x90, /*!< TX or RX mode indicator (to enable an external range extender) */
+  SPIRIT_GPIO_DIG_OUT_VDD                               = 0x98, /*!< VDD (to emulate an additional GPIO of the MCU, programmable by SPI) */
+  SPIRIT_GPIO_DIG_OUT_GND                               = 0xA0, /*!< GND (to emulate an additional GPIO of the MCU, programmable by SPI) */
+  SPIRIT_GPIO_DIG_OUT_SMPS_EXT                          = 0xA8, /*!< External SMPS enable signal (active high) */
+  SPIRIT_GPIO_DIG_OUT_SLEEP_OR_STANDBY                  = 0xB0,
+  SPIRIT_GPIO_DIG_OUT_READY                             = 0xB8,
+  SPIRIT_GPIO_DIG_OUT_LOCK                              = 0xC0,
+  SPIRIT_GPIO_DIG_OUT_WAIT_FOR_LOCK_SIG                 = 0xC8,
+  SPIRIT_GPIO_DIG_OUT_WAIT_FOR_TIMER_FOR_LOCK           = 0xD0,
+  SPIRIT_GPIO_DIG_OUT_WAIT_FOR_READY2_SIG               = 0xD8,
+  SPIRIT_GPIO_DIG_OUT_WAIT_FOR_TIMER_FOR_PM_SET         = 0xE0,
+  SPIRIT_GPIO_DIG_OUT_WAIT_VCO_CALIBRATION              = 0xE8,
+  SPIRIT_GPIO_DIG_OUT_ENABLE_SYNTH_FULL_CIRCUIT         = 0xF0,
+  SPIRIT_GPIO_DIG_OUT_WAIT_FOR_RCCAL_OK_SIG             = 0xFF,
+
+  SPIRIT_GPIO_DIG_IN_TX_COMMAND                         = 0x00,
+  SPIRIT_GPIO_DIG_IN_RX_COMMAND                         = 0x08,
+  SPIRIT_GPIO_DIG_IN_TX_DATA_INPUT_FOR_DIRECTRF         = 0x10,
+  SPIRIT_GPIO_DIG_IN_DATA_WAKEUP                        = 0x18,
+  SPIRIT_GPIO_DIG_IN_EXT_CLOCK_AT_34_7KHZ               = 0x20
+
+}SpiritGpioIO;
+
+#define IS_SPIRIT_GPIO_IO(IO_SEL)        ((IO_SEL == SPIRIT_GPIO_DIG_OUT_IRQ) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_POR_INV) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_WUT_EXP) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_LBD) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_TX_DATA) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_TX_STATE) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_TX_FIFO_ALMOST_EMPTY) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_TX_FIFO_ALMOST_FULL) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_RX_DATA) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_RX_CLOCK) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_RX_STATE) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_RX_FIFO_ALMOST_FULL) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_RX_FIFO_ALMOST_EMPTY) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_ANTENNA_SWITCH) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_VALID_PREAMBLE) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_SYNC_DETECTED) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_RSSI_THRESHOLD) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_MCU_CLOCK) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_TX_RX_MODE) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_VDD) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_GND) || \
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_SMPS_EXT) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_SLEEP_OR_STANDBY) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_READY) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_LOCK) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_WAIT_FOR_LOCK_SIG) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_WAIT_FOR_TIMER_FOR_LOCK) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_WAIT_FOR_READY2_SIG) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_WAIT_FOR_TIMER_FOR_PM_SET) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_WAIT_VCO_CALIBRATION) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_ENABLE_SYNTH_FULL_CIRCUIT) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_OUT_WAIT_FOR_RCCAL_OK_SIG) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_IN_TX_COMMAND) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_IN_RX_COMMAND) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_IN_TX_DATA_INPUT_FOR_DIRECTRF) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_IN_DATA_WAKEUP) ||\
+                                          (IO_SEL == SPIRIT_GPIO_DIG_IN_EXT_CLOCK_AT_34_7KHZ))
+
+/**
+ * @brief  SPIRIT OutputLevel enumeration.
+ */
+
+typedef enum
+{
+  LOW = 0,
+  HIGH = !LOW
+}OutputLevel;
+
+#define IS_SPIRIT_GPIO_LEVEL(LEVEL)      ((LEVEL == LOW) || \
+                                          (LEVEL == HIGH))
+
+
+/**
+ * @brief  SPIRIT GPIO Init structure definition.
+ */
+typedef struct
+{
+  SpiritGpioPin xSpiritGpioPin;    /*!< Specifies the GPIO pins to be configured.
+                                        This parameter can be any value of @ref SpiritGpioPin */
+
+  SpiritGpioMode xSpiritGpioMode;  /*!< Specifies the operating mode for the selected pins.
+                                        This parameter can be a value of @ref SpiritGpioMode */
+
+  SpiritGpioIO xSpiritGpioIO;      /*!< Specifies the I/O selection for the selected pins.
+                                        This parameter can be a value of @ref SpiritGpioIO */
+
+}SGpioInit;
+
+
+
+/**
+ * @brief  SPIRIT clock output XO prescaler enumeration.
+ */
+
+typedef enum
+{
+ XO_RATIO_1     = 0x00, /*!< XO Clock signal available on the GPIO divided by 1     */
+ XO_RATIO_2_3	= 0x02, /*!< XO Clock signal available on the GPIO divided by 2/3   */
+ XO_RATIO_1_2	= 0x04, /*!< XO Clock signal available on the GPIO divided by 1/2   */
+ XO_RATIO_1_3	= 0x06, /*!< XO Clock signal available on the GPIO divided by 1/3   */
+ XO_RATIO_1_4	= 0x08, /*!< XO Clock signal available on the GPIO divided by 1/4   */
+ XO_RATIO_1_6	= 0x0A, /*!< XO Clock signal available on the GPIO divided by 1/6   */
+ XO_RATIO_1_8	= 0x0C, /*!< XO Clock signal available on the GPIO divided by 1/8   */
+ XO_RATIO_1_12	= 0x0E, /*!< XO Clock signal available on the GPIO divided by 1/12  */
+ XO_RATIO_1_16	= 0x10, /*!< XO Clock signal available on the GPIO divided by 1/16  */
+ XO_RATIO_1_24	= 0x12, /*!< XO Clock signal available on the GPIO divided by 1/24  */
+ XO_RATIO_1_36	= 0x14, /*!< XO Clock signal available on the GPIO divided by 1/36  */
+ XO_RATIO_1_48	= 0x16, /*!< XO Clock signal available on the GPIO divided by 1/48  */
+ XO_RATIO_1_64	= 0x18, /*!< XO Clock signal available on the GPIO divided by 1/64  */
+ XO_RATIO_1_96	= 0x1A, /*!< XO Clock signal available on the GPIO divided by 1/96  */
+ XO_RATIO_1_128	= 0x1C, /*!< XO Clock signal available on the GPIO divided by 1/128 */
+ XO_RATIO_1_192	= 0x1E  /*!< XO Clock signal available on the GPIO divided by 1/196 */
+}ClockOutputXOPrescaler;
+
+#define IS_SPIRIT_CLOCK_OUTPUT_XO(RATIO) ((RATIO == XO_RATIO_1) || \
+                                           (RATIO == XO_RATIO_2_3) || \
+                                           (RATIO == XO_RATIO_1_2) || \
+                                           (RATIO == XO_RATIO_1_3) || \
+                                           (RATIO == XO_RATIO_1_4) || \
+                                           (RATIO == XO_RATIO_1_6) || \
+                                           (RATIO == XO_RATIO_1_8) || \
+                                           (RATIO == XO_RATIO_1_12) || \
+                                           (RATIO == XO_RATIO_1_16) || \
+                                           (RATIO == XO_RATIO_1_24) || \
+                                           (RATIO == XO_RATIO_1_36) || \
+                                           (RATIO == XO_RATIO_1_48) || \
+                                           (RATIO == XO_RATIO_1_64) || \
+                                           (RATIO == XO_RATIO_1_96) || \
+                                           (RATIO == XO_RATIO_1_128) || \
+                                           (RATIO == XO_RATIO_1_192))
+
+/**
+ * @brief  SPIRIT Clock Output RCO prescaler enumeration.
+ */
+
+typedef enum
+{
+ RCO_RATIO_1              = 0x00, /*!< RCO Clock signal available on the GPIO divided by 1     */
+ RCO_RATIO_1_128	  = 0x01  /*!< RCO Clock signal available on the GPIO divided by 1/128   */
+}ClockOutputRCOPrescaler;
+
+#define IS_SPIRIT_CLOCK_OUTPUT_RCO(RATIO) ((RATIO == RCO_RATIO_1) || \
+                                           (RATIO == RCO_RATIO_1_128))
+
+/**
+ * @brief  SPIRIT ExtraClockCycles enumeration.
+ */
+
+typedef enum
+{
+EXTRA_CLOCK_CYCLES_0	= 0x00, /*!< 0   extra clock cycles provided to the MCU before switching to STANDBY state */
+EXTRA_CLOCK_CYCLES_64	= 0x20, /*!< 64  extra clock cycles provided to the MCU before switching to STANDBY state */
+EXTRA_CLOCK_CYCLES_256	= 0x40, /*!< 256 extra clock cycles provided to the MCU before switching to STANDBY state */
+EXTRA_CLOCK_CYCLES_512	= 0x60  /*!< 512 extra clock cycles provided to the MCU before switching to STANDBY state */
+}ExtraClockCycles;
+
+#define IS_SPIRIT_CLOCK_OUTPUT_EXTRA_CYCLES(CYCLES) ((CYCLES == EXTRA_CLOCK_CYCLES_0) || \
+                                                      (CYCLES == EXTRA_CLOCK_CYCLES_64) || \
+                                                      (CYCLES == EXTRA_CLOCK_CYCLES_256) || \
+                                                      (CYCLES == EXTRA_CLOCK_CYCLES_512))
+
+
+/**
+ * @brief  SPIRIT Clock Output initialization structure definition.
+ */
+typedef struct
+{
+  ClockOutputXOPrescaler   xClockOutputXOPrescaler;  /*!< Specifies the XO Ratio as clock output.
+                                                          This parameter can be any value of @ref ClockOutputXOPrescaler */
+
+  ClockOutputRCOPrescaler  xClockOutputRCOPrescaler; /*!< Specifies the RCO Ratio as clock output.
+                                                          This parameter can be a value of @ref ClockOutputRCOPrescaler */
+
+  ExtraClockCycles         xExtraClockCycles;       /*!< Specifies the Extra Clock Cycles provided before entering in Standby State.
+                                                          This parameter can be a value of @ref ExtraClockCycles */
+
+}ClockOutputInit;
+
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Gpio_Exported_Constants   GPIO Exported Constants
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Gpio_Exported_Macros      GPIO Exported Macros
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Gpio_Exported_Functions   GPIO Exported Functions
+ * @{
+ */
+
+void SpiritGpioInit(SGpioInit* pxGpioInitStruct);
+void SpiritGpioTemperatureSensor(SpiritFunctionalState xNewState);
+void SpiritGpioSetLevel(SpiritGpioPin xGpioX, OutputLevel xLevel);
+OutputLevel SpiritGpioGetLevel(SpiritGpioPin xGpioX);
+void SpiritGpioClockOutput(SpiritFunctionalState xNewState);
+void SpiritGpioClockOutputInit(ClockOutputInit* pxClockOutputInitStruct);
+void SpiritGpioSetXOPrescaler(ClockOutputXOPrescaler xXOPrescaler);
+ClockOutputXOPrescaler SpiritGpioGetXOPrescaler(void);
+void SpiritGpioSetRCOPrescaler(ClockOutputRCOPrescaler xRCOPrescaler);
+ClockOutputRCOPrescaler SpiritGpioGetRCOPrescaler(void);
+void SpiritGpioSetExtraClockCycles(ExtraClockCycles xExtraCycles);
+ExtraClockCycles SpiritGpioGetExtraClockCycles(void);
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Irq.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Irq.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,357 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Irq.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT IRQs.
+  * 
+ * @details
+ *
+ * On the Spirit side specific IRQs can be enabled by setting a specific bitmask.
+ * The Spirit libraries allow the user to do this in two different ways:
+ * <ul>
+ *
+ * <li>The first enables the IRQs one by one, i.e. using an SPI transaction for each
+ * IRQ to enable.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *  SpiritIrqDeInit(NULL);                // this call is used to reset the IRQ mask registers
+ *  SpiritIrq(RX_DATA_READY , S_ENABLE);
+ *  SpiritIrq(VALID_SYNC , S_ENABLE);
+ *  SpiritIrq(RX_TIMEOUT , S_ENABLE);
+ *
+ * @endcode
+ *
+ * </li>
+ *
+ * <li>The second strategy is to set the IRQ bitfields structure. So, during the initialization the user
+ * has to fill the @ref SpiritIrqs structure setting to one the single field related to the IRQ he
+ * wants to enable, and to zero the single field related to all the IRQs he wants to disable.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *  SpiritIrqs irqMask;
+ *
+ *  ...
+ *
+ *  SpiritIrqDeInit(&irqMask);                // this call is used to reset the IRQ mask registers
+ *                                            // and to set to 0x00000000 the irq mask in order to disable
+ *                                            // all IRQs (disabled by default on startup)
+ *  irqMask.IRQ_RX_DATA_READY = 1;
+ *  irqMask.IRQ_VALID_SYNC = 1;
+ *  irqMask.IRQ_RX_TIMEOUT = 1;
+ *
+ *  ...
+ * @endcode
+ * </li>
+ * </ul>
+ *
+ * The most applications will require a Spirit IRQ notification on an microcontroller EXTI line.
+ * Then, the user can check which IRQ has been raised using two different ways.
+ *
+ * On the ISR of the EXTI line phisically linked to the Spirit pin configured for IRQ:
+ *
+ * <ul>
+ * <li> Check <b>only one</b> Spirit IRQ (because the Spirit IRQ status register automatically blanks itself
+ * after an SPI reading) into the ISR.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *  if(SpiritIrqCheckFlag(RX_DATA_READY))
+ *  {
+ *          // do something...
+ *  }
+ *
+ * @endcode
+ * </li>
+ *
+ * <li> Check more than one Spirit IRQ status by storing the entire IRQ status registers into a bitfields <i>@ref SpiritIrqs</i> structure
+ * and then check the interested bits.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *  SpiritIrqGetStatus(&irqStatus);
+ *
+ *  if(irqStatus.IRQ_RX_DATA_READY)
+ *  {
+ *          // do something...
+ *  }
+ *  if(irqStatus.IRQ_VALID_SYNC)
+ *  {
+ *         // do something...
+ *  }
+ *  if(irqStatus.RX_TIMEOUT)
+ *  {
+ *         // do something...
+ *  }
+ *
+ * @endcode
+ * </li>
+ * </ul>
+ *
+
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT1_IRQ_H
+#define __SPIRIT1_IRQ_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_Irq IRQ
+ * @brief Configuration and management of SPIRIT IRQs.
+ * @details See the file <i>@ref SPIRIT_Irq.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup Irq_Exported_Types IRQ Exported Types
+ * @{
+ */
+
+
+/**
+ * @brief IRQ bitfield structure for SPIRIT. This structure is used to read or write the single IRQ bit.
+ *        During the initialization the user has to fill this structure setting to one the single field related
+ *        to the IRQ he wants to enable, and to zero the single field related to all the IRQs he wants to disable.
+ *        The same structure can be used to retrieve all the IRQ events from the IRQ registers IRQ_STATUS[3:0],
+ *        and read if one or more specific IRQ raised.
+ * @note  The fields order in the structure depends on used endianness (little or big
+ *        endian). The actual definition is valid ONLY for LITTLE ENDIAN mode. Be sure to
+ *        change opportunely the fields order when use a different endianness.
+ */
+typedef struct
+{
+	  SpiritFlagStatus  IRQ_SYNTH_LOCK_TIMEOUT:1;       /*!< IRQ: only for debug; LOCK state timeout */
+	  SpiritFlagStatus  IRQ_SYNTH_LOCK_STARTUP:1;       /*!< IRQ: only for debug; see CALIBR_START_COUNTER */
+	  SpiritFlagStatus  IRQ_SYNTH_CAL_TIMEOUT:1;        /*!< IRQ: only for debug; SYNTH calibration timeout */
+	  SpiritFlagStatus  IRQ_TX_START_TIME:1;            /*!< IRQ: only for debug; TX circuitry startup time; see TX_START_COUNTER */
+	  SpiritFlagStatus  IRQ_RX_START_TIME:1;            /*!< IRQ: only for debug; RX circuitry startup time; see TX_START_COUNTER */
+	  SpiritFlagStatus  IRQ_RX_TIMEOUT:1;               /*!< IRQ: RX operation timeout */
+	  SpiritFlagStatus  IRQ_AES_END:1;                  /*!< IRQ: AES End of operation */
+	  SpiritFlagStatus  reserved:1;                     /*!< Reserved bit */
+
+	  SpiritFlagStatus  IRQ_READY:1;                    /*!< IRQ: READY state */
+	  SpiritFlagStatus  IRQ_STANDBY_DELAYED:1;          /*!< IRQ: STANDBY state after MCU_CK_CONF_CLOCK_TAIL_X clock cycles */
+	  SpiritFlagStatus  IRQ_LOW_BATT_LVL:1;             /*!< IRQ: Battery level below threshold*/
+	  SpiritFlagStatus  IRQ_POR:1;                      /*!< IRQ: Power On Reset */
+	  SpiritFlagStatus  IRQ_BOR:1;                      /*!< IRQ: Brown out event (both accurate and inaccurate)*/
+	  SpiritFlagStatus  IRQ_LOCK:1;                     /*!< IRQ: LOCK state */
+	  SpiritFlagStatus  IRQ_PM_COUNT_EXPIRED:1;         /*!< IRQ: only for debug; Power Management startup timer expiration (see reg PM_START_COUNTER, 0xB5) */
+	  SpiritFlagStatus  IRQ_XO_COUNT_EXPIRED:1;         /*!< IRQ: only for debug; Crystal oscillator settling time counter expired */
+
+	  SpiritFlagStatus  IRQ_TX_FIFO_ALMOST_EMPTY:1;     /*!< IRQ: TX FIFO almost empty */
+	  SpiritFlagStatus  IRQ_RX_FIFO_ALMOST_FULL:1;      /*!< IRQ: RX FIFO almost full */
+	  SpiritFlagStatus  IRQ_RX_FIFO_ALMOST_EMPTY:1;     /*!< IRQ: RX FIFO almost empty  */
+	  SpiritFlagStatus  IRQ_MAX_BO_CCA_REACH:1;         /*!< IRQ: Max number of back-off during CCA */
+	  SpiritFlagStatus  IRQ_VALID_PREAMBLE:1;           /*!< IRQ: Valid preamble detected */
+	  SpiritFlagStatus  IRQ_VALID_SYNC:1;               /*!< IRQ: Sync word detected */
+	  SpiritFlagStatus  IRQ_RSSI_ABOVE_TH:1;            /*!< IRQ: RSSI above threshold */
+	  SpiritFlagStatus  IRQ_WKUP_TOUT_LDC:1;            /*!< IRQ: Wake-up timeout in LDC mode */
+
+	  SpiritFlagStatus  IRQ_RX_DATA_READY:1;            /*!< IRQ: RX data ready */
+	  SpiritFlagStatus  IRQ_RX_DATA_DISC:1;             /*!< IRQ: RX data discarded (upon filtering) */
+	  SpiritFlagStatus  IRQ_TX_DATA_SENT:1;             /*!< IRQ: TX data sent */
+	  SpiritFlagStatus  IRQ_MAX_RE_TX_REACH:1;          /*!< IRQ: Max re-TX reached */
+	  SpiritFlagStatus  IRQ_CRC_ERROR:1;                /*!< IRQ: CRC error */
+	  SpiritFlagStatus  IRQ_TX_FIFO_ERROR:1;            /*!< IRQ: TX FIFO underflow/overflow error */
+	  SpiritFlagStatus  IRQ_RX_FIFO_ERROR:1;            /*!< IRQ: RX FIFO underflow/overflow error */
+	  SpiritFlagStatus  IRQ_TX_FIFO_ALMOST_FULL:1;      /*!< IRQ: TX FIFO almost full */
+} SpiritIrqs;
+
+// betzw: uint32_t masks
+#define IRQ_TX_FIFO_ALMOST_EMPTY_MASK	(0x00010000) /* (1<<16) */
+#define IRQ_RX_FIFO_ALMOST_FULL_MASK	(0x00020000) /* (1<<17) */
+#define IRQ_VALID_SYNC_MASK				(0x00200000) /* (1<<21) */
+#define IRQ_RX_DATA_READY_MASK			(0x01000000) /* (1<<24) */
+#define IRQ_RX_DATA_DISC_MASK			(0x02000000) /* (1<<25) */
+#define IRQ_TX_DATA_SENT_MASK			(0x04000000) /* (1<<26) */
+#define IRQ_TX_FIFO_ERROR_MASK			(0x20000000) /* (1<<29) */
+#define IRQ_RX_FIFO_ERROR_MASK			(0x40000000) /* (1<<30) */
+
+/**
+ * @brief  IRQ list enumeration for SPIRIT. This enumeration type can be used to address a
+ *         specific IRQ.
+ */
+typedef enum
+{
+  RX_DATA_READY = 0x00000001,           /*!< IRQ: RX data ready */
+  RX_DATA_DISC = 0x00000002,            /*!< IRQ: RX data discarded (upon filtering) */
+  TX_DATA_SENT = 0x00000004,            /*!< IRQ: TX data sent */
+  MAX_RE_TX_REACH = 0x00000008,         /*!< IRQ: Max re-TX reached */
+  CRC_ERROR = 0x00000010,               /*!< IRQ: CRC error */
+  TX_FIFO_ERROR = 0x00000020,           /*!< IRQ: TX FIFO underflow/overflow error */
+  RX_FIFO_ERROR = 0x00000040,           /*!< IRQ: RX FIFO underflow/overflow error */
+  TX_FIFO_ALMOST_FULL = 0x00000080,     /*!< IRQ: TX FIFO almost full */
+  TX_FIFO_ALMOST_EMPTY = 0x00000100,    /*!< IRQ: TX FIFO almost empty */
+  RX_FIFO_ALMOST_FULL = 0x00000200,     /*!< IRQ: RX FIFO almost full */
+  RX_FIFO_ALMOST_EMPTY = 0x00000400,    /*!< IRQ: RX FIFO almost empty  */
+  MAX_BO_CCA_REACH = 0x00000800,        /*!< IRQ: Max number of back-off during CCA */
+  VALID_PREAMBLE = 0x00001000,          /*!< IRQ: Valid preamble detected */
+  VALID_SYNC = 0x00002000,              /*!< IRQ: Sync word detected */
+  RSSI_ABOVE_TH = 0x00004000,           /*!< IRQ: RSSI above threshold */
+  WKUP_TOUT_LDC = 0x00008000,           /*!< IRQ: Wake-up timeout in LDC mode */
+  READY = 0x00010000,                   /*!< IRQ: READY state */
+  STANDBY_DELAYED = 0x00020000,         /*!< IRQ: STANDBY state after MCU_CK_CONF_CLOCK_TAIL_X clock cycles */
+  LOW_BATT_LVL = 0x00040000,            /*!< IRQ: Battery level below threshold*/
+  POR = 0x00080000,                     /*!< IRQ: Power On Reset */
+  BOR = 0x00100000,                     /*!< IRQ: Brown out event (both accurate and inaccurate)*/
+  LOCK = 0x00200000,                    /*!< IRQ: LOCK state */
+  PM_COUNT_EXPIRED = 0x00400000,        /*!< IRQ: only for debug; Power Management startup timer expiration (see reg PM_START_COUNTER, 0xB5) */
+  XO_COUNT_EXPIRED = 0x00800000,        /*!< IRQ: only for debug; Crystal oscillator settling time counter expired */
+  SYNTH_LOCK_TIMEOUT = 0x01000000,      /*!< IRQ: only for debug; LOCK state timeout */
+  SYNTH_LOCK_STARTUP = 0x02000000,      /*!< IRQ: only for debug; see CALIBR_START_COUNTER */
+  SYNTH_CAL_TIMEOUT = 0x04000000,       /*!< IRQ: only for debug; SYNTH calibration timeout */
+  TX_START_TIME = 0x08000000,	        /*!< IRQ: only for debug; TX circuitry startup time; see TX_START_COUNTER */
+  RX_START_TIME = 0x10000000,	        /*!< IRQ: only for debug; RX circuitry startup time; see TX_START_COUNTER */
+  RX_TIMEOUT = 0x20000000,	        /*!< IRQ: RX operation timeout */
+  AES_END = 0x40000000,                 /*!< IRQ: AES End of operation */
+  ALL_IRQ = 0x7FFFFFFF			/*!< All the above mentioned IRQs */
+
+} IrqList;
+
+#define IS_SPIRIT_IRQ_LIST(VALUE)   ((VALUE == RX_DATA_READY) || \
+                                     (VALUE == RX_DATA_DISC)  || \
+                                     (VALUE == TX_DATA_SENT)  || \
+                                     (VALUE == MAX_RE_TX_REACH)  || \
+                                     (VALUE == CRC_ERROR)  || \
+                                     (VALUE == TX_FIFO_ERROR)  || \
+                                     (VALUE == RX_FIFO_ERROR)  || \
+                                     (VALUE == TX_FIFO_ALMOST_FULL)  || \
+                                     (VALUE == TX_FIFO_ALMOST_EMPTY)  || \
+                                     (VALUE == RX_FIFO_ALMOST_FULL)  || \
+                                     (VALUE == RX_FIFO_ALMOST_EMPTY)  || \
+                                     (VALUE == MAX_BO_CCA_REACH)  || \
+                                     (VALUE == VALID_PREAMBLE)  || \
+                                     (VALUE == VALID_SYNC)  || \
+                                     (VALUE == RSSI_ABOVE_TH)  || \
+                                     (VALUE == WKUP_TOUT_LDC)  || \
+                                     (VALUE == READY)  || \
+                                     (VALUE == STANDBY_DELAYED)  || \
+                                     (VALUE == LOW_BATT_LVL)  || \
+                                     (VALUE == POR)  || \
+                                     (VALUE == BOR)  || \
+                                     (VALUE == LOCK)  || \
+                                     (VALUE == PM_COUNT_EXPIRED)  || \
+                                     (VALUE == XO_COUNT_EXPIRED)  || \
+                                     (VALUE == SYNTH_LOCK_TIMEOUT)  || \
+                                     (VALUE == SYNTH_LOCK_STARTUP)  || \
+                                     (VALUE == SYNTH_CAL_TIMEOUT)  || \
+                                     (VALUE == TX_START_TIME)  || \
+                                     (VALUE == RX_START_TIME)  || \
+                                     (VALUE == RX_TIMEOUT)  || \
+                                     (VALUE == AES_END)   || \
+				     (VALUE == ALL_IRQ ))
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Irq_Exported_Constants     IRQ Exported Constants
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Irq_Exported_Macros        IRQ Exported Macros
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Irq_Exported_Functions     IRQ Exported Functions
+ * @{
+ */
+
+void SpiritIrqDeInit(SpiritIrqs* pxIrqInit);
+void SpiritIrqInit(SpiritIrqs* pxIrqInit);
+void SpiritIrq(IrqList xIrq, SpiritFunctionalState xNewState);
+void SpiritIrqGetMask(SpiritIrqs* pxIrqMask);
+void SpiritIrqGetStatus(SpiritIrqs* pxIrqStatus);
+void SpiritIrqClearStatus(void);
+SpiritBool SpiritIrqCheckFlag(IrqList xFlag);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_LinearFifo.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_LinearFifo.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,136 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_LinearFifo.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT Fifo.
+ * @details
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+ *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_LINEAR_FIFO_H
+#define __SPIRIT_LINEAR_FIFO_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_LinearFifo          Linear FIFO
+ * @brief Configuration and management of SPIRIT FIFO.
+ * @details See the file <i>@ref SPIRIT_LinearFifo.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup LinearFifo_Exported_Types  Linear FIFO Exported Types
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup LinearFifo_Exported_Constants      Linear FIFO Exported Constants
+ * @{
+ */
+#define IS_FIFO_THR(VAL)  (VAL<=96)
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup LinearFifo_Exported_Macros         Linear FIFO Exported Macros
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup LinearFifo_Exported_Functions                      Linear FIFO Exported Functions
+ * @{
+ */
+
+uint8_t SpiritLinearFifoReadNumElementsRxFifo(void);
+uint8_t SpiritLinearFifoReadNumElementsTxFifo(void);
+void SpiritLinearFifoSetAlmostFullThresholdRx(uint8_t cThrRxFifo);
+uint8_t SpiritLinearFifoGetAlmostFullThresholdRx(void);
+void SpiritLinearFifoSetAlmostEmptyThresholdRx(uint8_t cThrRxFifo);
+uint8_t SpiritLinearFifoGetAlmostEmptyThresholdRx(void);
+void SpiritLinearFifoSetAlmostFullThresholdTx(uint8_t cThrTxFifo);
+uint8_t SpiritLinearFifoGetAlmostFullThresholdTx(void);
+void SpiritLinearFifoSetAlmostEmptyThresholdTx(uint8_t cThrTxFifo);
+uint8_t SpiritLinearFifoGetAlmostEmptyThresholdTx(void);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Management.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Management.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,100 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Management.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   The management layer for SPIRIT1 library.
+ * @details
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef SPIRIT_MANAGEMENT_H_
+#define SPIRIT_MANAGEMENT_H_
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Config.h"
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_MANAGEMENT          Management
+ * @brief Workarounds for Spirit1.
+ * @details See the file <i>@ref SPIRIT_Management.h</i> for more details.
+ * @{
+ */
+
+
+/**
+ * @addgroup SPIRIT_MANAGEMENT_FUNCTIONS
+ * @{
+ */
+
+   
+
+
+uint8_t SpiritManagementWaVcoCalibration(void);
+void SpiritManagementWaCmdStrobeTx(void);
+void SpiritManagementWaCmdStrobeRx(void);
+void SpiritManagementWaTRxFcMem(uint32_t nDesiredFreq);
+void SpiritManagementWaExtraCurrent(void);
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
+ /******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktBasic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktBasic.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,696 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_PktBasic.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT Basic packets.
+  * 
+ * @details
+ *
+ * This module can be used to manage the configuration of Spirit Basic
+ * packets.
+ * The user can obtain a packet configuration filling the structure
+ * <i>@ref PktBasicInit</i>, defining in it some general parameters
+ * for the Spirit Basic packet format.
+ * Another structure the user can fill is <i>@ref PktBasicAddressesInit</i>
+ * to define the addresses which will be used during the communication.
+ * Moreover, functions to set the payload length and the destination address
+ * are provided.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ * PktBasicInit basicInit={
+ *   PKT_PREAMBLE_LENGTH_08BYTES,       // preamble length in bytes
+ *   PKT_SYNC_LENGTH_4BYTES,            // sync word length in bytes
+ *   0x1A2635A8,                        // sync word
+ *   PKT_LENGTH_VAR,                    // variable or fixed payload length
+ *   7,                                 // length field width in bits (used only for variable length)
+ *   PKT_NO_CRC,                        // CRC mode
+ *   PKT_CONTROL_LENGTH_0BYTES,         // control field length
+ *   S_ENABLE,                          // address field
+ *   S_DISABLE,                         // FEC
+ *   S_ENABLE                           // whitening
+ * };
+ *
+ * PktBasicAddressesInit addressInit={
+ *   S_ENABLE,                          // enable/disable filtering on my address
+ *   0x34,                              // my address (address of the current node)
+ *   S_DISABLE,                         // enable/disable filtering on multicast address
+ *   0xEE,                              // multicast address
+ *   S_DISABLE,                         // enable/disable filtering on broadcast address
+ *   0xFF                               // broadcast address
+ * };
+ *
+ * ...
+ *
+ * SpiritPktBasicInit(&basicInit);
+ * SpiritPktBasicAddressesInit(&addressInit);
+ *
+ * ...
+ *
+ * SpiritPktBasicSetPayloadLength(20);
+ * SpiritPktBasicSetDestinationAddress(0x44);
+ *
+ * ...
+ *
+ * @endcode
+ *
+ * The module provides some other functions that can be used to modify
+ * or read only some configuration parameters.
+ *
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_PKT_BASIC_H
+#define __SPIRIT_PKT_BASIC_H
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+#include "SPIRIT_PktCommon.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_PktBasic    Pkt Basic
+ * @brief Configuration and management of SPIRIT Basic packets.
+ * @details See the file <i>@ref SPIRIT_PktBasic.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup PktBasic_Exported_Types    Pkt Basic Exported Types
+ * @{
+ */
+
+
+/**
+ * @brief  Preamble length in bytes enumeration.
+ */
+typedef PktPreambleLength                  BasicPreambleLength;
+
+#define IS_BASIC_PREAMBLE_LENGTH           IS_PKT_PREAMBLE_LENGTH
+
+/**
+ * @brief  Sync length in bytes enumeration.
+ */
+typedef PktSyncLength                      BasicSyncLength;
+
+#define IS_BASIC_SYNC_LENGTH               IS_PKT_SYNC_LENGTH
+
+
+
+/**
+ * @brief  CRC length in bytes enumeration.
+ */
+typedef PktCrcMode                         BasicCrcMode;
+
+#define IS_BASIC_CRC_MODE                  IS_PKT_CRC_MODE
+
+
+/**
+ * @brief  Fixed or variable payload length enumeration.
+ */
+typedef PktFixVarLength                    BasicFixVarLength;
+
+#define IS_BASIC_FIX_VAR_LENGTH            IS_PKT_FIX_VAR_LENGTH
+
+/**
+ * @brief  Control length in bytes enumeration.
+ */
+typedef PktControlLength                   BasicControlLength;
+
+#define IS_BASIC_CONTROL_LENGTH            IS_PKT_CONTROL_LENGTH
+
+/**
+ * @brief  Sync words enumeration.
+ */
+typedef PktSyncX                           BasicSyncX;
+
+#define IS_BASIC_SYNCx                     IS_PKT_SYNCx
+
+
+/**
+ * @brief  SPIRIT Basic Packet Init structure definition. This structure allows users to set the main options
+ *         for the Basic packet.
+ */
+typedef struct
+{
+
+  BasicPreambleLength           xPreambleLength;        /*!< Specifies the preamble length.
+                                                             This parameter can be any value of @ref BasicPreambleLength */
+  BasicSyncLength               xSyncLength;            /*!< Specifies the sync word length. The 32bit word passed (lSyncWords) will be stored in the SYNCx registers from the MSb
+                                                             until the number of bytes in xSyncLength has been stored.
+                                                             This parameter can be any value of @ref BasicSyncLength */
+  uint32_t                      lSyncWords;             /*!< Specifies the sync words.
+                                                             This parameter is a uint32_t word with format: 0x|SYNC1|SYNC2|SYNC3|SYNC4| */
+  BasicFixVarLength             xFixVarLength;          /*!< Specifies if a fixed length of packet has to be used.
+                                                             This parameter can be any value of @ref BasicFixVarLength */
+  uint8_t                       cPktLengthWidth;        /*!< Specifies the size of the length of packet in bits. This field is useful only if
+                                                             the field xFixVarLength is set to BASIC_LENGTH_VAR. For Basic packets the length width
+                                                             is log2( max payload length + control length (0 to 4) + address length (0 or 1)).
+                                                             This parameter is an uint8_t */
+  BasicCrcMode                  xCrcMode;               /*!< Specifies the CRC word length of packet.
+                                                             This parameter can be any value of @ref BasicCrcMode */
+  BasicControlLength            xControlLength;         /*!< Specifies the length of a control field to be sent.
+                                                             This parameter can be any value of @ref BasicControlLength */
+  SpiritFunctionalState         xAddressField;          /*!< Specifies if the destination address has to be sent.
+                                                             This parameter can be S_ENABLE or S_DISABLE */
+  SpiritFunctionalState         xFec;                   /*!< Specifies if FEC has to be enabled.
+                                                             This parameter can be S_ENABLE or S_DISABLE */
+  SpiritFunctionalState         xDataWhitening;         /*!< Specifies if data whitening has to be enabled.
+                                                             This parameter can be S_ENABLE or S_DISABLE */
+}PktBasicInit;
+
+
+/**
+ * @brief  SPIRIT Basic Packet address structure definition. This structure allows users to specify
+ *         the node/multicast/broadcast addresses and the correspondent filtering options.
+ */
+typedef struct
+{
+
+  SpiritFunctionalState         xFilterOnMyAddress;             /*!< If set RX packet is accepted if its destination address matches with cMyAddress.
+                                                                     This parameter can be S_ENABLE or S_DISABLE */
+  uint8_t                       cMyAddress;                     /*!< Specifies the TX packet source address (address of this node).
+                                                                     This parameter is an uint8_t */
+  SpiritFunctionalState         xFilterOnMulticastAddress;      /*!< If set RX packet is accepted if its destination address matches with cMulticastAddress.
+                                                                     This parameter can be S_ENABLE or S_DISABLE */
+  uint8_t                       cMulticastAddress;              /*!< Specifies the Multicast group address for this node.
+                                                                     This parameter is an uint8_t */
+  SpiritFunctionalState         xFilterOnBroadcastAddress;      /*!< If set RX packet is accepted if its destination address matches with cBroadcastAddress.
+                                                                     This parameter can be S_ENABLE or S_DISABLE */
+  uint8_t                       cBroadcastAddress;              /*!< Specifies the Broadcast address for this node.
+                                                                     This parameter is an uint8_t */
+}PktBasicAddressesInit;
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktBasic_Exported_Constants        Pkt Basic Exported Constants
+ * @{
+ */
+
+#define IS_BASIC_LENGTH_WIDTH_BITS                      IS_PKT_LENGTH_WIDTH_BITS
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktBasic_Exported_Macros   Pkt Basic Exported Macros
+ * @{
+ */
+
+/**
+ * @brief  Macro used to compute per lower part of the packet length
+ *         for Spirit Basic packets, to write in the PCKTLEN0 register.
+ * @param  nLength Length of the packet payload.
+ *         This parameter is an uint16_t.
+ * @retval None.
+ */
+#define BASIC_BUILD_PCKTLEN0(nLength)                                            BUILD_PCKTLEN0(nLength)
+
+
+/**
+ * @brief  Macro used to compute per upper part of the packet length
+ *         for Spirit Basic packets, to write the PCKTLEN1 register.
+ * @param  nLengthLength of the packet payload.
+ *         This parameter is an uint16_t.
+ * @retval None.
+ */
+#define BASIC_BUILD_PCKTLEN1(nLength)                                            BUILD_PCKTLEN1(nLength)
+
+/**
+ * @brief  Sets the CONTROL field length for SPIRIT Basic packets.
+ * @param  xControlLength length of CONTROL field in bytes.
+ *         This parameter can be any value of @ref PktControlLength.
+ * @retval None.
+ */
+#define SpiritPktBasicSetControlLength(xControlLength)                  SpiritPktCommonSetControlLength(xControlLength)
+
+
+/**
+ * @brief  Returns the CONTROL field length for SPIRIT Basic packets.
+ * @param  None.
+ * @retval uint8_t Control field length.
+ */
+#define SpiritPktBasicGetControlLength()                                SpiritPktCommonGetControlLength()
+
+
+/**
+ * @brief  Sets the PREAMBLE field length for SPIRIT Basic packets.
+ * @param  xPreambleLength length of PREAMBLE field in bytes.
+ *         This parameter can be any value of @ref BasicPreambleLength.
+ * @retval None.
+ */
+#define SpiritPktBasicSetPreambleLength(xPreambleLength)                SpiritPktCommonSetPreambleLength((PktPreambleLength)xPreambleLength)
+
+
+/**
+ * @brief  Returns the PREAMBLE field length mode for SPIRIT Basic packets.
+ * @param  None.
+ * @retval uint8_t Preamble field length in bytes.
+ */
+#define SpiritPktBasicGetPreambleLength()                               SpiritPktCommonGetPreambleLength()
+
+
+/**
+ * @brief  Sets the SYNC field length for SPIRIT Basic packets.
+ * @param  xSyncLength length of SYNC field in bytes.
+ *         This parameter can be any value of @ref BasicSyncLength.
+ * @retval None.
+ */
+#define SpiritPktBasicSetSyncLength(xSyncLength)                         SpiritPktCommonSetSyncLength((PktSyncLength)xSyncLength)
+
+
+/**
+ * @brief  Returns the SYNC field length for SPIRIT Basic packets.
+ * @param  None.
+ * @retval uint8_t SYNC field length in bytes.
+ */
+#define SpiritPktBasicGetSyncLength()                                   SpiritPktCommonGetSyncLength()
+
+
+/**
+ * @brief  Sets fixed or variable payload length mode for SPIRIT packets.
+ * @param  xFixVarLength variable or fixed length.
+ *         BASIC_FIXED_LENGTH_VAR -> variable (the length is extracted from the received packet).
+ *         BASIC_FIXED_LENGTH_FIX -> fix (the length is set by PCKTLEN0 and PCKTLEN1).
+ * @retval None.
+ */
+#define SpiritPktBasicSetFixVarLength(xFixVarLength)                    SpiritPktCommonSetFixVarLength((PktFixVarLength)xFixVarLength)
+
+
+/**
+ * @brief  Enables or Disables the CRC filtering.
+ * @param  xNewState new state for CRC_CHECK.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktBasicFilterOnCrc(xNewState)                            SpiritPktCommonFilterOnCrc(xNewState)
+
+
+/**
+ * @brief  Returns the CRC filtering bit.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktBasicGetFilterOnCrc()                                  SpiritPktCommonGetFilterOnCrc()
+
+
+/**
+ * @brief  Sets the CRC mode for SPIRIT Basic packets.
+ * @param  xCrcMode CRC mode.
+ *         This parameter can be any value of @ref BasicCrcMode.
+ * @retval None.
+ */
+#define SpiritPktBasicSetCrcMode(xCrcMode)                              SpiritPktCommonSetCrcMode((PktCrcMode)xCrcMode)
+
+
+/**
+ * @brief  Returns the CRC mode for SPIRIT Basic packets.
+ * @param  None.
+ * @retval BasicCrcMode Crc mode.
+ */
+#define SpiritPktBasicGetCrcMode()                                      (BasicCrcMode)SpiritPktCommonGetCrcMode()
+
+
+/**
+ * @brief  Enables or Disables WHITENING for SPIRIT packets.
+ * @param  xNewState new state for WHITENING mode.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktBasicWhitening(xNewState)                               SpiritPktCommonWhitening(xNewState)
+
+
+/**
+ * @brief  Enables or Disables FEC for SPIRIT Basic packets.
+ * @param  xNewState new state for FEC mode.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktBasicFec(xNewState)                                     SpiritPktCommonFec(xNewState)
+
+
+/**
+ * @brief  Sets a specific SYNC word for SPIRIT Basic packets.
+ * @param  xSyncX SYNC word number to be set.
+ *         This parameter can be any value of @ref BasicSyncX.
+ * @param  cSyncWord SYNC word.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktBasicSetSyncxWord(xSyncX, cSyncWord)                   SpiritPktCommonSetSyncxWord((PktSyncX)xSyncX, cSyncWord)
+
+
+/**
+ * @brief  Returns a specific SYNC words for SPIRIT Basic packets.
+ * @param  xSyncX SYNC word number to be get.
+ *         This parameter can be any value of @ref BasicSyncX.
+ * @retval uint8_t Sync word x.
+ */
+#define SpiritPktBasicGetSyncxWord(xSyncX)                              SpiritPktCommonGetSyncxWord(xSyncX)
+
+
+/**
+ * @brief  Sets multiple SYNC words for SPIRIT Basic packets.
+ * @param  lSyncWords SYNC words to be set with format: 0x|SYNC1|SYNC2|SYNC3|SYNC4|.
+ *         This parameter is a uint32_t.
+ * @param  xSyncLength SYNC length in bytes. The 32bit word passed will be stored in the SYNCx registers from the MSb
+ *         until the number of bytes in xSyncLength has been stored.
+ *         This parameter is a @ref BasicSyncLength.
+ * @retval None.
+ */
+#define SpiritPktBasicSetSyncWords(lSyncWords, xSyncLength)              SpiritPktCommonSetSyncWords(lSyncWords, (PktSyncLength)xSyncLength)
+
+
+/**
+ * @brief  Returns multiple SYNC words for SPIRIT Basic packets.
+ * @param  xSyncLength SYNC length in bytes. The 32bit word passed will be stored in the SYNCx registers from the MSb
+ *         until the number of bytes in xSyncLength has been stored.
+ *         This parameter is a pointer to @ref BasicSyncLength.
+ * @retval uint32_t Sync words. The format of the read 32 bit word is 0x|SYNC1|SYNC2|SYNC3|SYNC4|.
+ */
+#define SpiritPktBasicGetSyncWords(xSyncLength)                         SpiritPktCommonGetSyncWords((PktSyncLength)xSyncLength)
+
+
+/**
+ * @brief  Returns the SPIRIT variable length width (in number of bits).
+ * @param  None.
+ * @retval Variable length width in bits.
+ */
+#define SpiritPktBasicGetVarLengthWidth()                               SpiritPktCommonGetVarLengthWidth()
+
+
+/**
+ * @brief  Sets the destination address for the Tx packet.
+ * @param  cAddress destination address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktBasicSetDestinationAddress(cAddress)                   SpiritPktCommonSetDestinationAddress(cAddress)
+
+
+/**
+ * @brief  Returns the settled destination address.
+ * @param  None.
+ * @retval uint8_t Transmitted destination address.
+ */
+#define SpiritPktBasicGetTransmittedDestAddress()                       SpiritPktCommonGetTransmittedDestAddress()
+
+
+/**
+ * @brief  Sets the node address. When the filtering on my address is on, if the destination address extracted from the received packet is equal to the content of the
+ *         my address, then the packet is accepted (this is the address of the node).
+ * @param  cAddress Address of the present node.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktBasicSetMyAddress(cAddress)                            SpiritPktCommonSetMyAddress(cAddress)
+
+
+/**
+ * @brief  Returns the address of the present node.
+ * @param  None.
+ * @retval uint8_t My address (address of this node).
+ */
+#define SpiritPktBasicGetMyAddress()                                    SpiritPktCommonGetMyAddress()
+
+
+/**
+ * @brief  Sets the broadcast address. When the broadcast filtering is on, if the destination address extracted from the received packet is equal to the content of the
+ *         BROADCAST_ADDR register, then the packet is accepted.
+ * @param  cAddress Broadcast address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktBasicSetBroadcastAddress(cAddress)                     SpiritPktCommonSetBroadcastAddress(cAddress)
+
+
+/**
+ * @brief  Returns the broadcast address.
+ * @param  None.
+ * @retval uint8_t Broadcast address.
+ */
+#define SpiritPktBasicGetBroadcastAddress()                             SpiritPktCommonGetBroadcastAddress()
+
+
+/**
+ * @brief  Sets the multicast address. When the multicast filtering is on, if the destination address extracted from the received packet is equal to the content of the
+ *         MULTICAST_ADDR register, then the packet is accepted.
+ * @param  cAddress Multicast address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktBasicSetMulticastAddress(cAddress)                     SpiritPktCommonSetMulticastAddress(cAddress)
+
+
+/**
+ * @brief  Returns the multicast address.
+ * @param  None.
+ * @retval uint8_t Multicast address.
+ */
+#define SpiritPktBasicGetMulticastAddress()                             SpiritPktCommonGetMulticastAddress()
+
+
+/**
+ * @brief  Sets the control mask. The 1 bits of the CONTROL_MASK indicate the
+ *         bits to be used in filtering. (All 0s no filtering)
+ * @param  lMask Control mask.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+#define SpiritPktBasicSetCtrlMask(lMask)                                SpiritPktCommonSetCtrlMask(lMask)
+
+
+/**
+ * @brief  Returns the control mask. The 1 bits of the CONTROL_MASK indicate the
+ *         bits to be used in filtering. (All 0s no filtering)
+ * @param  None.
+ * @retval uint32_t Control mask.
+ */
+#define SpiritPktBasicGetCtrlMask()                                     SpiritPktCommonGetCtrlMask()
+
+
+/**
+ * @brief  Sets the control field reference. If the bits enabled by the
+ *         CONTROL_MASK match the ones of the control fields extracted from the received packet
+ *         then the packet is accepted.
+ * @param  lReference Control reference.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+#define SpiritPktBasicSetCtrlReference(lReference)                      SpiritPktCommonSetCtrlReference(lReference)
+
+
+/**
+ * @brief  Returns the control field reference.
+ * @param  None.
+ * @retval uint32_t Control reference.
+ */
+#define SpiritPktBasicGetCtrlReference()                                SpiritPktCommonGetCtrlReference()
+
+
+/**
+ * @brief  Sets the TX control field.
+ * @param  lField Tx control field.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+#define SpiritPktBasicSetTransmittedCtrlField(lField)                   SpiritPktCommonSetTransmittedCtrlField(lField)
+
+
+/**
+ * @brief  Returns the TX control field.
+ * @param  None.
+ * @retval uint32_t Control field of the transmitted packet.
+ */
+#define SpiritPktBasicGetTransmittedCtrlField()                         SpiritPktCommonGetTransmittedCtrlField()
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with My address.
+ * @param  xNewState new state for DEST_VS_SOURCE_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktBasicFilterOnMyAddress(xNewState)                      SpiritPktCommonFilterOnMyAddress(xNewState)
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with multicast address.
+ * @param  xNewState new state for DEST_VS_MULTICAST_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktBasicFilterOnMulticastAddress(xNewState)               SpiritPktCommonFilterOnMulticastAddress(xNewState)
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with broadcast address.
+ * @param  xNewState new state for DEST_VS_BROADCAST_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktBasicFilterOnBroadcastAddress(xNewState)               SpiritPktCommonFilterOnBroadcastAddress(xNewState)
+
+
+/**
+ * @brief  Returns the enable bit of the my address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktBasicGetFilterOnMyAddress()                            SpiritPktCommonGetFilterOnMyAddress();
+
+
+/**
+ * @brief  Returns the enable bit of the multicast address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktBasicGetFilterOnMulticastAddress()                     SpiritPktCommonGetFilterOnMulticastAddress();
+
+
+/**
+ * @brief  Returns the enable bit of the broadcast address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktBasicGetFilterOnBroadcastAddress()                     SpiritPktCommonGetFilterOnBroadcastAddress();
+
+
+/**
+ * @brief  Returns the destination address of the received packet.
+ * @param  None.
+ * @retval uint8_t Destination address of the received packet.
+ */
+#define SpiritPktBasicGetReceivedDestAddress()                          SpiritPktCommonGetReceivedDestAddress()
+
+
+/**
+ * @brief  Returns the control field of the received packet.
+ * @param  None.
+ * @retval uint32_t Received control field.
+ */
+#define SpiritPktBasicGetReceivedCtrlField()                            SpiritPktCommonGetReceivedCtrlField()
+
+
+/**
+ * @brief  Returns the CRC field of the received packet.
+ * @param  cCrcFieldVect array in which the CRC field has to be stored.
+ *         This parameter is an uint8_t array of 3 elements.
+ * @retval None.
+ */
+#define SpiritPktBasicGetReceivedCrcField(cCrcFieldVect)                SpiritPktCommonGetReceivedCrcField(cCrcFieldVect)
+
+
+/**
+ * @brief  If enabled RX packet is accepted only if the masked control field matches the
+ *         masked control field reference (CONTROL_MASK & CONTROL_FIELD_REF == CONTROL_MASK & RX_CONTROL_FIELD).
+ * @param  xNewState new state for Control filtering enable bit.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ * @note   This filtering control is enabled by default but the control mask is by default set to 0.
+ *         As a matter of fact the user has to enable the control filtering bit after the packet initialization
+ *         because the PktInit routine disables it.
+ */
+#define SpiritPktBasicFilterOnControlField(xNewState)                           SpiritPktCommonFilterOnControlField(xNewState)
+
+
+/**
+ * @brief  Returns the enable bit of the control field filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktBasicGetFilterOnControlField()                                 SpiritPktCommonGetFilterOnControlField();
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktBasic_Exported_Functions        Pkt Basic Exported Functions
+ * @{
+ */
+
+void SpiritPktBasicInit(PktBasicInit* pxPktBasicInit);
+void SpiritPktBasicGetInfo(PktBasicInit* pxPktBasicInit);
+void SpiritPktBasicAddressesInit(PktBasicAddressesInit* pxPktBasicAddresses);
+void SpiritPktBasicGetAddressesInfo(PktBasicAddressesInit* pxPktBasicAddresses);
+void SpiritPktBasicSetFormat(void);
+void SpiritPktBasicAddressField(SpiritFunctionalState xAddressField);
+SpiritFunctionalState SpiritPktBasicGetAddressField(void);
+void SpiritPktBasicSetPayloadLength(uint16_t nPayloadLength);
+uint16_t SpiritPktBasicGetPayloadLength(void);
+uint16_t SpiritPktBasicGetReceivedPktLength(void);
+void SpiritPktBasicSetVarLengthWidth(uint16_t nMaxPayloadLength,SpiritFunctionalState xAddressField, BasicControlLength xControlLength);
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktCommon.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktCommon.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,432 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_PktCommon.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of the common features of SPIRIT packets.
+  * 
+ * @details
+ *
+ * This module provides all the common functions and definitions used by the
+ * packets modules.
+ * Here are also defined all the generic enumeration types that are redefined
+ * in the specific packets modules, but every enumeration value is referred
+ * to this module. So the user who wants to configure the preamble of a Basic,
+ * or a STack packet has to use the enumeration values defined here.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *   ...
+ *
+ *   SpiritPktBasicSetPreambleLength(PKT_PREAMBLE_LENGTH_18BYTES);
+ *
+ *   ...
+ *
+ * @endcode
+ *
+ * @note Is recommended for the user to not use these API directly
+ * importing this module in his application.
+ *
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_PKT_COMMON_H
+#define __SPIRIT_PKT_COMMON_H
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_PktCommon           Pkt Common
+ * @brief Configuration and management of the common features of SPIRIT packets.
+ * @details See the file <i>@ref SPIRIT_PktCommon.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup PktCommon_Exported_Types   Pkt Common Exported Types
+ * @{
+ */
+
+
+/**
+ * @brief  Preamble length in bytes enumeration.
+ */
+typedef enum
+{
+  PKT_PREAMBLE_LENGTH_01BYTE            = 0x00, /*!< Preamble length 1 byte*/
+  PKT_PREAMBLE_LENGTH_02BYTES           = 0x08, /*!< Preamble length 2 bytes */
+  PKT_PREAMBLE_LENGTH_03BYTES           = 0x10, /*!< Preamble length 3 bytes */
+  PKT_PREAMBLE_LENGTH_04BYTES           = 0x18, /*!< Preamble length 4 bytes */
+  PKT_PREAMBLE_LENGTH_05BYTES           = 0x20, /*!< Preamble length 5 bytes */
+  PKT_PREAMBLE_LENGTH_06BYTES           = 0x28, /*!< Preamble length 6 bytes */
+  PKT_PREAMBLE_LENGTH_07BYTES           = 0x30, /*!< Preamble length 7 bytes */
+  PKT_PREAMBLE_LENGTH_08BYTES           = 0x38, /*!< Preamble length 8 bytes */
+  PKT_PREAMBLE_LENGTH_09BYTES           = 0x40, /*!< Preamble length 9 bytes */
+  PKT_PREAMBLE_LENGTH_10BYTES           = 0x48, /*!< Preamble length 10 bytes */
+  PKT_PREAMBLE_LENGTH_11BYTES           = 0x50, /*!< Preamble length 11 bytes */
+  PKT_PREAMBLE_LENGTH_12BYTES           = 0x58, /*!< Preamble length 12 bytes */
+  PKT_PREAMBLE_LENGTH_13BYTES           = 0x60, /*!< Preamble length 13 bytes */
+  PKT_PREAMBLE_LENGTH_14BYTES           = 0x68, /*!< Preamble length 14 bytes */
+  PKT_PREAMBLE_LENGTH_15BYTES           = 0x70, /*!< Preamble length 15 bytes */
+  PKT_PREAMBLE_LENGTH_16BYTES           = 0x78, /*!< Preamble length 16 bytes */
+  PKT_PREAMBLE_LENGTH_17BYTES           = 0x80, /*!< Preamble length 17 bytes */
+  PKT_PREAMBLE_LENGTH_18BYTES           = 0x88, /*!< Preamble length 18 bytes */
+  PKT_PREAMBLE_LENGTH_19BYTES           = 0x90, /*!< Preamble length 19 bytes */
+  PKT_PREAMBLE_LENGTH_20BYTES           = 0x98, /*!< Preamble length 20 bytes */
+  PKT_PREAMBLE_LENGTH_21BYTES           = 0xA0, /*!< Preamble length 21 bytes */
+  PKT_PREAMBLE_LENGTH_22BYTES           = 0xA8, /*!< Preamble length 22 bytes */
+  PKT_PREAMBLE_LENGTH_23BYTES           = 0xB0, /*!< Preamble length 23 bytes */
+  PKT_PREAMBLE_LENGTH_24BYTES           = 0xB8, /*!< Preamble length 24 bytes */
+  PKT_PREAMBLE_LENGTH_25BYTES           = 0xC0, /*!< Preamble length 25 bytes */
+  PKT_PREAMBLE_LENGTH_26BYTES           = 0xC8, /*!< Preamble length 26 bytes */
+  PKT_PREAMBLE_LENGTH_27BYTES           = 0xD0, /*!< Preamble length 27 bytes */
+  PKT_PREAMBLE_LENGTH_28BYTES           = 0xD8, /*!< Preamble length 28 bytes */
+  PKT_PREAMBLE_LENGTH_29BYTES           = 0xE0, /*!< Preamble length 29 bytes */
+  PKT_PREAMBLE_LENGTH_30BYTES           = 0xE8, /*!< Preamble length 30 bytes */
+  PKT_PREAMBLE_LENGTH_31BYTES           = 0xF0, /*!< Preamble length 31 bytes */
+  PKT_PREAMBLE_LENGTH_32BYTES           = 0xF8  /*!< Preamble length 32 bytes */
+
+}PktPreambleLength;
+
+#define IS_PKT_PREAMBLE_LENGTH(LENGTH)  ((LENGTH == PKT_PREAMBLE_LENGTH_01BYTE) || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_02BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_03BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_04BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_05BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_06BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_07BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_08BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_09BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_10BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_11BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_12BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_13BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_14BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_15BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_16BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_17BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_18BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_19BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_20BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_21BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_22BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_23BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_24BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_25BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_26BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_27BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_28BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_29BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_30BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_31BYTES)  || \
+                                           (LENGTH == PKT_PREAMBLE_LENGTH_32BYTES))
+
+
+
+/**
+ * @brief  Sync length in bytes enumeration.
+ */
+typedef enum
+{
+  PKT_SYNC_LENGTH_1BYTE            = 0x00, /*!< Sync length 1 byte*/
+  PKT_SYNC_LENGTH_2BYTES           = 0x02, /*!< Sync length 2 bytes*/
+  PKT_SYNC_LENGTH_3BYTES           = 0x04, /*!< Sync length 3 bytes */
+  PKT_SYNC_LENGTH_4BYTES           = 0x06 , /*!< Sync length 4 bytes */
+
+}PktSyncLength;
+
+#define IS_PKT_SYNC_LENGTH(LENGTH)     ((LENGTH == PKT_SYNC_LENGTH_1BYTE) || \
+                                          (LENGTH == PKT_SYNC_LENGTH_2BYTES)|| \
+                                          (LENGTH == PKT_SYNC_LENGTH_3BYTES)|| \
+                                          (LENGTH == PKT_SYNC_LENGTH_4BYTES))
+
+
+
+/**
+ * @brief  CRC length in bytes enumeration.
+ */
+typedef enum
+{
+  PKT_NO_CRC               = 0x00, /*!< No CRC                              */
+  PKT_CRC_MODE_8BITS       = 0x20, /*!< CRC length 8 bits  - poly: 0x07     */
+  PKT_CRC_MODE_16BITS_1    = 0x40, /*!< CRC length 16 bits - poly: 0x8005   */
+  PKT_CRC_MODE_16BITS_2    = 0x60, /*!< CRC length 16 bits - poly: 0x1021   */
+  PKT_CRC_MODE_24BITS      = 0x80, /*!< CRC length 24 bits - poly: 0x864CFB */
+
+}PktCrcMode;
+
+#define IS_PKT_CRC_MODE(MODE)   ((MODE == PKT_NO_CRC) || \
+                                   (MODE == PKT_CRC_MODE_8BITS)  || \
+                                   (MODE == PKT_CRC_MODE_16BITS_1)  || \
+                                   (MODE == PKT_CRC_MODE_16BITS_2) || \
+                                   (MODE == PKT_CRC_MODE_24BITS))
+
+
+
+/**
+ * @brief  Fixed or variable payload length enumeration.
+ */
+typedef enum
+{
+  PKT_LENGTH_FIX  = 0x00,    /*!< Fixed payload length     */
+  PKT_LENGTH_VAR  = 0x01     /*!< Variable payload length  */
+
+}PktFixVarLength;
+
+#define IS_PKT_FIX_VAR_LENGTH(LENGTH)   ((LENGTH == PKT_LENGTH_FIX) || \
+                                           (LENGTH == PKT_LENGTH_VAR))
+
+
+/**
+ * @brief  Control length in bytes enumeration for SPIRIT packets.
+ */
+typedef enum
+{
+  PKT_CONTROL_LENGTH_0BYTES = 0x00,     /*!< Control length 0 byte*/
+  PKT_CONTROL_LENGTH_1BYTE,             /*!< Control length 1 byte*/
+  PKT_CONTROL_LENGTH_2BYTES,            /*!< Control length 2 bytes*/
+  PKT_CONTROL_LENGTH_3BYTES,            /*!< Control length 3 bytes*/
+  PKT_CONTROL_LENGTH_4BYTES             /*!< Control length 4 bytes*/
+
+}PktControlLength;
+
+#define IS_PKT_CONTROL_LENGTH(LENGTH) ((LENGTH == PKT_CONTROL_LENGTH_0BYTES) || \
+                                         (LENGTH == PKT_CONTROL_LENGTH_1BYTE)   || \
+                                         (LENGTH == PKT_CONTROL_LENGTH_2BYTES)  || \
+                                         (LENGTH == PKT_CONTROL_LENGTH_3BYTES)  || \
+                                         (LENGTH == PKT_CONTROL_LENGTH_4BYTES))
+
+/**
+ * @brief  Sync words enumeration for SPIRIT packets.
+ */
+typedef enum
+{
+  PKT_SYNC_WORD_1=0x01,  /*!< Index of the 1st sync word*/
+  PKT_SYNC_WORD_2,       /*!< Index of the 2nd sync word*/
+  PKT_SYNC_WORD_3,       /*!< Index of the 3rd sync word*/
+  PKT_SYNC_WORD_4        /*!< Index of the 4th sync word*/
+
+}PktSyncX;
+
+#define IS_PKT_SYNCx(WORD)    ((WORD == PKT_SYNC_WORD_1) || \
+                                 (WORD == PKT_SYNC_WORD_2) || \
+                                 (WORD == PKT_SYNC_WORD_3) || \
+                                 (WORD == PKT_SYNC_WORD_4))
+
+
+
+/**
+ * @brief  Max retransmissions number enumeration for SPIRIT packets.
+ */
+typedef enum
+{
+  PKT_DISABLE_RETX    = 0x00,   /*!< No retrasmissions*/
+  PKT_N_RETX_1        = 0x10,   /*!< Max retrasmissions 1*/
+  PKT_N_RETX_2        = 0x20,   /*!< Max retrasmissions 2*/
+  PKT_N_RETX_3        = 0x30,   /*!< Max retrasmissions 3*/
+  PKT_N_RETX_4        = 0x40,   /*!< Max retrasmissions 4*/
+  PKT_N_RETX_5        = 0x50,   /*!< Max retrasmissions 5*/
+  PKT_N_RETX_6        = 0x60,   /*!< Max retrasmissions 6*/
+  PKT_N_RETX_7        = 0x70,   /*!< Max retrasmissions 7*/
+  PKT_N_RETX_8        = 0x80,   /*!< Max retrasmissions 8*/
+  PKT_N_RETX_9        = 0x90,   /*!< Max retrasmissions 9*/
+  PKT_N_RETX_10       = 0xA0,   /*!< Max retrasmissions 10*/
+  PKT_N_RETX_11       = 0xB0,   /*!< Max retrasmissions 11*/
+  PKT_N_RETX_12       = 0xC0,   /*!< Max retrasmissions 12*/
+  PKT_N_RETX_13       = 0xD0,   /*!< Max retrasmissions 13*/
+  PKT_N_RETX_14       = 0xE0,   /*!< Max retrasmissions 14*/
+  PKT_N_RETX_15       = 0xF0    /*!< Max retrasmissions 15*/
+
+}PktNMaxReTx;
+
+#define IS_PKT_NMAX_RETX(N_RETX)    ((N_RETX == PKT_DISABLE_RETX) || \
+                                       (N_RETX == PKT_N_RETX_1) || \
+                                       (N_RETX == PKT_N_RETX_2) || \
+                                       (N_RETX == PKT_N_RETX_3) || \
+                                       (N_RETX == PKT_N_RETX_4) || \
+                                       (N_RETX == PKT_N_RETX_5) || \
+                                       (N_RETX == PKT_N_RETX_6) || \
+                                       (N_RETX == PKT_N_RETX_7) || \
+                                       (N_RETX == PKT_N_RETX_8) || \
+                                       (N_RETX == PKT_N_RETX_9) || \
+                                       (N_RETX == PKT_N_RETX_10) || \
+                                       (N_RETX == PKT_N_RETX_11) || \
+                                       (N_RETX == PKT_N_RETX_12) || \
+                                       (N_RETX == PKT_N_RETX_13) || \
+                                       (N_RETX == PKT_N_RETX_14) || \
+                                       (N_RETX == PKT_N_RETX_15))
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktCommon_Exported_Constants               Pkt Common Exported Constants
+ * @{
+ */
+
+#define IS_PKT_LENGTH_WIDTH_BITS(BITS)                (BITS<=16)
+#define IS_PKT_SEQ_NUMBER_RELOAD(SEQN)                (SEQN<=3)
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktCommon_Exported_Macros                  Pkt Common Exported Macros
+ * @{
+ */
+
+
+/**
+ * @brief  Macro used to compute the lower part of the packet length, to write in the PCKTLEN0 register
+ * @param  nLength Length of the packet payload.
+ *         This parameter is an uint16_t.
+ * @retval None.
+ */
+#define BUILD_PCKTLEN0(nLength) ((nLength) & 0xFF)
+
+
+/**
+ * @brief  Macro used to compute the upper part of the packet length, to write the PCKTLEN1 register
+ * @param  nLength Length of the packet payload.
+ *         This parameter is an uint16_t.
+ * @retval None.
+ */
+#define BUILD_PCKTLEN1(nLength) ((nLength) >> 8)
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktCommon_Exported_Functions               Pkt Common Exported Functions
+ * @{
+ */
+
+void SpiritPktCommonSetControlLength(PktControlLength xControlLength);
+uint8_t SpiritPktCommonGetControlLength(void);
+void SpiritPktCommonSetPreambleLength(PktPreambleLength xPreambleLength);
+uint8_t SpiritPktCommonGetPreambleLength(void);
+void SpiritPktCommonSetSyncLength(PktSyncLength xSyncLength);
+uint8_t SpiritPktCommonGetSyncLength(void);
+void SpiritPktCommonSetFixVarLength(PktFixVarLength xFixVarLength);
+void SpiritPktCommonFilterOnCrc(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritPktCommonGetFilterOnCrc(void);
+void SpiritPktCommonSetCrcMode(PktCrcMode xCrcLength);
+PktCrcMode SpiritPktCommonGetCrcMode(void);
+void SpiritPktCommonWhitening(SpiritFunctionalState xNewState);
+void SpiritPktCommonFec(SpiritFunctionalState xNewState);
+void SpiritPktCommonSetSyncxWord(PktSyncX xSyncX,  uint8_t cSyncWord);
+uint8_t SpiritPktCommonGetSyncxWord(PktSyncX xSyncX);
+void SpiritPktCommonSetSyncWords(uint32_t lSyncWords, PktSyncLength xSyncLength);
+uint32_t SpiritPktCommonGetSyncWords(PktSyncLength xSyncLength);
+uint8_t SpiritPktCommonGetVarLengthWidth(void);
+void SpiritPktCommonSetDestinationAddress(uint8_t cAddress);
+uint8_t SpiritPktCommonGetTransmittedDestAddress(void);
+void SpiritPktCommonSetMyAddress(uint8_t cAddress);
+uint8_t SpiritPktCommonGetMyAddress(void);
+void SpiritPktCommonSetBroadcastAddress(uint8_t cAddress);
+uint8_t SpiritPktCommonGetBroadcastAddress(void);
+SpiritFunctionalState SpiritPktCommonGetTxAckRequest(void);
+void SpiritPktCommonSetMulticastAddress(uint8_t cAddress);
+uint8_t SpiritPktCommonGetMulticastAddress(void);
+void SpiritPktCommonSetCtrlMask(uint32_t lMask);
+uint32_t SpiritPktCommonGetCtrlMask(void);
+void SpiritPktCommonSetCtrlReference(uint32_t lReference);
+uint32_t SpiritPktCommonGetCtrlReference(void);
+void SpiritPktCommonSetTransmittedCtrlField(uint32_t lField);
+uint32_t SpiritPktCommonGetTransmittedCtrlField(void);
+void SpiritPktCommonFilterOnMyAddress(SpiritFunctionalState xNewState);
+void SpiritPktCommonFilterOnMulticastAddress(SpiritFunctionalState xNewState);
+void SpiritPktCommonFilterOnBroadcastAddress(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritPktCommonGetFilterOnMyAddress(void);
+SpiritFunctionalState SpiritPktCommonGetFilterOnMulticastAddress(void);
+SpiritFunctionalState SpiritPktCommonGetFilterOnBroadcastAddress(void);
+uint8_t SpiritPktCommonGetReceivedDestAddress(void);
+uint32_t SpiritPktCommonGetReceivedCtrlField(void);
+void SpiritPktCommonGetReceivedCrcField(uint8_t* cCrcFieldVect);
+void SpiritPktCommonAutoAck(SpiritFunctionalState xAutoAck,SpiritFunctionalState xPiggybacking);
+void SpiritPktCommonRequireAck(SpiritFunctionalState xRequireAck);
+void SpiritPktCommonSetTransmittedSeqNumberReload(uint8_t cSeqNumberReload);
+void SpiritPktCommonSetNMaxReTx(PktNMaxReTx xNMaxReTx);
+uint8_t SpiritPktCommonGetNMaxReTx(void);
+uint8_t SpiritPktCommonGetReceivedDestAddress(void);
+uint8_t SpiritPktCommonGetReceivedSourceAddress(void);
+uint8_t SpiritPktCommonGetReceivedSeqNumber(void);
+uint8_t SpiritPktCommonGetReceivedNackRx(void);
+uint8_t SpiritPktCommonGetTransmittedSeqNumber(void);
+uint8_t SpiritPktCommonGetNReTx(void);
+void SpiritPktCommonFilterOnControlField(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritPktCommonGetFilterOnControlField(void);
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktMbus.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktMbus.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,206 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_PktMbus.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT MBUS packets.
+  * 
+ * @details
+ *
+ * This module can be used to manage the configuration of Spirit MBUS
+ * packets.
+ * The user can obtain a packet configuration filling the structure
+ * <i>@ref PktMbusInit</i>, defining in it some general parameters
+ * for the Spirit MBUS packet format.
+ * Since the MBUS protocol is a standard, the configuration of a MBUS
+ * packet is very simple to do.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ * PktMbusInit mbusInit={
+ *   MBUS_SUBMODE_S1_S2_LONG_HEADER,    // MBUS submode selection
+ *   36,                                // added "01" chips on preamble
+ *   16                                 // postamble length in "01" chips
+ * };
+ *
+ * ...
+ *
+ * SpiritPktMbusInit(&mbusInit);
+ *
+ * ...
+ *
+ * @endcode
+ *
+ * The module provides some other functions that can be used to modify
+ * or read only some configuration parameters.
+ *
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_PACKET_MBUS_H
+#define __SPIRIT_PACKET_MBUS_H
+
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+#include "SPIRIT_PktCommon.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_PktMbus     Pkt MBUS
+ * @brief Configuration and management of SPIRIT MBUS packets.
+ * @details See the file <i>@ref SPIRIT_PktMbus.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup PktMbus_Exported_Types     Pkt MBUS Exported Types
+ * @{
+ */
+
+
+
+/**
+ * @brief  MBUS submode enumeration.
+ */
+
+typedef enum
+{
+  MBUS_SUBMODE_S1_S2_LONG_HEADER            = MBUS_CTRL_MBUS_SUBMODE_S1_S2L,                /*!< MBUS submode S1, S2 (long header) - Header length = mbus_prmbl_ctrl + 279 (in "01" bit pairs) , Sync word = 0x7696 (length 18 bits) */
+  MBUS_SUBMODE_S1_M_S2_T2_OTHER_TO_METER    = MBUS_CTRL_MBUS_SUBMODE_S2_S1M_T2_OTHER,       /*!< MBUS submode S1-m, S2, T2 (other to meter) - Header length = mbus_prmbl_ctrl + 15 (in "01" bit pairs) , Sync word = 0x7696 (length 18 bits)*/
+  MBUS_SUBMODE_T1_T2_METER_TO_OTHER         = MBUS_CTRL_MBUS_SUBMODE_T1_T2_METER,           /*!< MBUS submode T1, T2 (meter to other) - Header length = mbus_prmbl_ctrl + 19 (in "01" bit pairs) ,  Sync word = 0x3D (length 10 bits)*/
+  MBUS_SUBMODE_R2_SHORT_HEADER              = MBUS_CTRL_MBUS_SUBMODE_R2,                    /*!< MBUS submode R2, short header - Header length = mbus_prmbl_ctrl + 39 (in "01" bit pairs) , Sync word = 0x7696 (length 18 bits)*/
+
+}MbusSubmode;
+
+#define IS_MBUS_SUBMODE(MODE)   (((MODE) == MBUS_SUBMODE_S1_S2_LONG_HEADER) || \
+                                 ((MODE) == MBUS_SUBMODE_S1_M_S2_T2_OTHER_TO_METER) || \
+                                 ((MODE) == MBUS_SUBMODE_T1_T2_METER_TO_OTHER) || \
+                                 ((MODE) == MBUS_SUBMODE_R2_SHORT_HEADER))
+
+
+/**
+ * @brief  SPIRIT MBUS Packet Init structure definition
+ */
+typedef struct
+{
+  MbusSubmode  	    xMbusSubmode;              /*!< Specifies the SUBMODE to be configured.
+                                                    This parameter can be a value of @ref MbusSubmode */
+
+  uint8_t           cPreambleLength;           /*!< Specifies the PREAMBLE length.
+                                                    This parameter can be any value between 0 and 255 chip sequence '01' */
+
+  uint8_t           cPostambleLength;          /*!< Specifies the POSTAMBLE length.
+                                                    This parameter can be any value between 0 and 255 chip sequence '01' */
+
+}PktMbusInit;
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktMbus_Exported_Constants         Pkt MBUS Exported Constants
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktMbus_Exported_Macros            Pkt MBUS Exported Macros
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktMbus_Exported_Functions                 Pkt MBUS Exported Functions
+ * @{
+ */
+void SpiritPktMbusInit(PktMbusInit* pxPktMbusInit);
+void SpiritPktMbusGetInfo(PktMbusInit* pxPktMbusInit);
+void SpiritPktMbusSetFormat(void);
+void SpiritPktMbusSetPreamble(uint8_t cPreamble);
+uint8_t SpiritPktMbusGetPreamble(void);
+void SpiritPktMbusSetPostamble(uint8_t cPostamble);
+uint8_t SpiritPktMbusGetPostamble(void);
+void SpiritPktMbusSetSubmode(MbusSubmode xMbusSubmode);
+MbusSubmode SpiritPktMbusGetSubmode(void);
+void SpiritPktMbusSetPayloadLength(uint16_t nPayloadLength);
+uint16_t SpiritPktMbusGetPayloadLength(void);
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktStack.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_PktStack.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,849 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_PktStack.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT STack packets.
+  * 
+ * @details
+ *
+ * This module can be used to manage the configuration of Spirit STack
+ * packets, and it is quite similar to the Basic packets one since the
+ * STack packets can be considered an extension of Basic.
+ * The user can obtain a packet configuration filling the structure
+ * <i>@ref PktStackInit</i>, defining in it some general parameters
+ * for the Spirit STack packet format.
+ * Another structure the user can fill is <i>@ref PktStackAddressesInit</i>
+ * to define the addresses which will be used during the communication.
+ * The structure <i>@ref PktStackLlpInit</i> is provided in order to configure
+ * the link layer protocol features like autoack, autoretransmission
+ * or piggybacking.
+ * Moreover, functions to set the payload length and the destination address
+ * are provided.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ * PktStackInit stackInit={
+ *   PKT_PREAMBLE_LENGTH_08BYTES,       // preamble length in bytes
+ *   PKT_SYNC_LENGTH_4BYTES,            // sync word length in bytes
+ *   0x1A2635A8,                        // sync word
+ *   PKT_LENGTH_VAR,                    // variable or fixed payload length
+ *   7,                                 // length field width in bits (used only for variable length)
+ *   PKT_NO_CRC,                        // CRC mode
+ *   PKT_CONTROL_LENGTH_0BYTES,         // control field length
+ *   S_DISABLE,                         // FEC
+ *   S_ENABLE                           // whitening
+ * };
+ *
+ * PktStackAddressesInit addressInit={
+ *   S_ENABLE,                          // enable/disable filtering on my address
+ *   0x34,                              // my address (address of the current node)
+ *   S_DISABLE,                         // enable/disable filtering on multicast address
+ *   0xEE,                              // multicast address
+ *   S_DISABLE,                         // enable/disable filtering on broadcast address
+ *   0xFF                               // broadcast address
+ * };
+ *
+ * PktStackLlpInit stackLLPInit ={
+ *   S_DISABLE,                         // enable/disable the autoack feature
+ *   S_DISABLE,                         // enable/disable the piggybacking feature
+ *   PKT_DISABLE_RETX                   // set the max number of retransmissions or disable them
+ * };
+ * ...
+ *
+ * SpiritPktStackInit(&stackInit);
+ * SpiritPktStackAddressesInit(&addressInit);
+ * SpiritPktStackLlpInit(&stackLLPInit);
+ *
+ * ...
+ *
+ * SpiritPktStackSetPayloadLength(20);
+ * SpiritPktStackSetDestinationAddress(0x44);
+ *
+ * ...
+ *
+ * @endcode
+ *
+ * The module provides some other functions that can be used to modify
+ * or read only some configuration parameters.
+ *
+ *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_PKT_STACK_H
+#define __SPIRIT_PKT_STACK_H
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+#include "SPIRIT_PktCommon.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_PktStack    Pkt STack
+ * @brief Configuration and management of SPIRIT STack packets.
+ * @details See the file <i>@ref SPIRIT_PktStack.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup PktStack_Exported_Types    Pkt STack Exported Types
+ * @{
+ */
+
+/**
+ * @brief  Preamble length in bytes enumeration.
+ */
+typedef PktPreambleLength                  StackPreambleLength;
+
+#define IS_STACK_PREAMBLE_LENGTH           IS_PKT_PREAMBLE_LENGTH
+
+/**
+ * @brief  Sync length in bytes enumeration.
+ */
+typedef PktSyncLength                      StackSyncLength;
+
+#define IS_STACK_SYNC_LENGTH               IS_PKT_SYNC_LENGTH
+
+
+
+/**
+ * @brief  CRC length in bytes enumeration.
+ */
+typedef PktCrcMode                         StackCrcMode;
+
+#define IS_STACK_CRC_MODE                  IS_PKT_CRC_MODE
+
+
+/**
+ * @brief  Fixed or variable payload length enumeration.
+ */
+typedef PktFixVarLength                    StackFixVarLength;
+
+#define IS_STACK_FIX_VAR_LENGTH            IS_PKT_FIX_VAR_LENGTH
+
+/**
+ * @brief  Control length in bytes enumeration for SPIRIT.
+ */
+typedef PktControlLength                   StackControlLength;
+
+#define IS_STACK_CONTROL_LENGTH            IS_PKT_CONTROL_LENGTH
+
+/**
+ * @brief  Sync words enumeration for SPIRIT.
+ */
+typedef PktSyncX                           StackSyncX;
+
+#define IS_STACK_SYNCx                     IS_PKT_SYNCx
+
+/**
+ * @brief  Max retransmission number enumeration for SPIRIT.
+ */
+typedef PktNMaxReTx                        StackNMaxReTx;
+
+#define IS_STACK_NMAX_RETX                 IS_PKT_NMAX_RETX
+
+
+/**
+ * @brief  SPIRIT STack Packet Init structure definition. This structure allows users to set the main options
+ *         for the STack packet.
+ */
+typedef struct
+{
+
+  StackPreambleLength           xPreambleLength;         /*!< Specifies the preamble length of packet.
+                                                              This parameter can be any value of @ref StackPreambleLength */
+  StackSyncLength               xSyncLength;             /*!< Specifies the sync word length of packet.
+                                                              This parameter can be any value of @ref StackSyncLength */
+  uint32_t                      lSyncWords;	         /*!< Specifies the sync words.
+                                                              This parameter is a uint32_t word with format: 0x|SYNC1|SYNC2|SYNC3|SYNC4| */
+  StackFixVarLength             xFixVarLength;           /*!< Specifies if a fixed length of packet has to be used.
+                                                              This parameter can be any value of @ref StackFixVarLength */
+  uint8_t            	        cPktLengthWidth;         /*!< Specifies the size of the length of packet in bits. This field is useful only if
+                                                              the field xFixVarLength is set to STACK_LENGTH_VAR. For STack packets the length width
+                                                               is log2( max payload length + control length (0 to 4) + address length (always 2)).
+                                                              This parameter is an uint8_t */
+  StackCrcMode                	xCrcMode;              	 /*!< Specifies the CRC word length of packet.
+                                                              This parameter can be any value of @ref StackCrcMode */
+  StackControlLength            xControlLength;          /*!< Specifies the length of a control field to be sent.
+                                                              This parameter can be any value of @ref StackControlLength */
+  SpiritFunctionalState         xFec;                    /*!< Specifies if FEC has to be enabled.
+                                                              This parameter can be any value of @ref SpiritFunctionalState */
+  SpiritFunctionalState         xDataWhitening;          /*!< Specifies if data whitening has to be enabled.
+                                                              This parameter can be any value of @ref SpiritFunctionalState */
+
+}PktStackInit;
+
+
+/**
+ * @brief  SPIRIT STack packet address structure definition. This structure allows users to specify
+ *         the node/multicast/broadcast addresses and the correspondent filtering options.
+ */
+typedef struct
+{
+
+  SpiritFunctionalState         xFilterOnMyAddress;             /*!< If set RX packet is accepted if its destination address matches with cMyAddress.
+                                                                     This parameter can be S_ENABLE or S_DISABLE */
+  uint8_t                       cMyAddress;                     /*!< Specifies the TX packet source address (address of this node).
+                                                                     This parameter is an uint8_t */
+  SpiritFunctionalState         xFilterOnMulticastAddress;      /*!< If set RX packet is accepted if its destination address matches with cMulticastAddress.
+                                                                     This parameter can be S_ENABLE or S_DISABLE */
+  uint8_t                       cMulticastAddress;              /*!< Specifies the Multicast group address for this node.
+                                                                     This parameter is an uint8_t */
+  SpiritFunctionalState         xFilterOnBroadcastAddress;      /*!< If set RX packet is accepted if its destination address matches with cBroadcastAddress.
+                                                                     This parameter can be S_ENABLE or S_DISABLE */
+  uint8_t                       cBroadcastAddress;              /*!< Specifies the Broadcast address for this node.
+                                                                     This parameter is an uint8_t */
+}PktStackAddressesInit;
+
+
+/**
+ * @brief  SPIRIT STack packet LLP structure definition. This structure allows users to configure
+ *         all the LLP options for STack packets.
+ */
+typedef struct
+{
+
+  SpiritFunctionalState         xAutoAck;                /*!< Specifies if the auto ACK feature is used or not.
+                                                              This parameter can be a value of @ref SpiritFunctionalState */
+  SpiritFunctionalState         xPiggybacking;           /*!< Specifies if the piggybacking feature is used or not.
+                                                              This parameter can be a value of @ref SpiritFunctionalState */
+  StackNMaxReTx                 xNMaxRetx;               /*!< Specifies the number of MAX-Retransmissions.
+                                                              This parameter can be a value of @ref StackNMaxReTx */
+}PktStackLlpInit;
+
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktStack_Exported_Constants        Pkt STack Exported Constants
+ * @{
+ */
+
+#define IS_STACK_LENGTH_WIDTH_BITS                      IS_PKT_LENGTH_WIDTH_BITS
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktStack_Exported_Macros   Pkt STack Exported Macros
+ * @{
+ */
+
+/**
+ * @brief  Macro used to compute the lower part of the packet length
+ *         for Spirit STack packets, to write in the PCKTLEN0 register.
+ * @param  nLength length of the packet payload.
+ *         This parameter is an uint16_t.
+ * @retval None.
+ */
+#define STACK_BUILD_PCKTLEN0(nLength)                                    BUILD_PCKTLEN0(nLength)
+
+
+/**
+ * @brief  Macro used to compute the upper part of the packet length
+ *         for Spirit STack packets, to write the PCKTLEN1 register.
+ * @param  nLength length of the packet payload.
+ *         This parameter is an uint16_t.
+ * @retval None.
+ */
+#define STACK_BUILD_PCKTLEN1(nLength)                                    BUILD_PCKTLEN1(nLength)
+
+
+/**
+ * @brief  Sets the CONTROL length for SPIRIT STack packets.
+ * @param  xControlLength length of CONTROL field in bytes.
+ *         This parameter can be any value of @ref StackControlLength.
+ * @retval None.
+ */
+#define SpiritPktStackSetControlLength(xControlLength)                          SpiritPktCommonSetControlLength(xControlLength)
+
+
+/**
+ * @brief  Returns the CONTROL length for SPIRIT STack packets.
+ * @param  None.
+ * @retval Control length.
+ */
+#define SpiritPktStackGetControlLength()                                       SpiritPktCommonGetControlLength()
+
+
+/**
+ * @brief  Sets the PREAMBLE Length mode for SPIRIT STack packets.
+ * @param  xPreambleLength length of PREAMBLE field in bytes.
+ *         This parameter can be any value of @ref StackPreambleLength.
+ * @retval None.
+ */
+#define SpiritPktStackSetPreambleLength(xPreambleLength)                        SpiritPktCommonSetPreambleLength((PktPreambleLength)xPreambleLength)
+
+
+/**
+ * @brief  Returns the PREAMBLE Length mode for SPIRIT STack packets.
+ * @param  None.
+ * @retval uint8_t Preamble length in bytes.
+ */
+#define SpiritPktStackGetPreambleLength()                                      SpiritPktCommonGetPreambleLength()
+
+
+/**
+ * @brief  Sets the SYNC Length for SPIRIT STack packets.
+ * @param  xSyncLength length of SYNC field in bytes.
+ *         This parameter can be any value of @ref StackSyncLength.
+ * @retval None.
+ */
+#define SpiritPktStackSetSyncLength(xSyncLength)                                SpiritPktCommonSetSyncLength((PktSyncLength)xSyncLength)
+
+
+/**
+ * @brief  Returns the SYNC Length for SPIRIT STack packets.
+ * @param  None.
+ * @retval uint8_t Sync length in bytes.
+ */
+#define SpiritPktStackGetSyncLength()                                           SpiritPktCommonGetSyncLength()
+
+
+/**
+ * @brief  Sets fixed or variable payload length mode for SPIRIT STack packets.
+ * @param  xFixVarLength variable or fixed length.
+ *         PKT_FIXED_LENGTH_VAR -> variable (the length is extracted from the received packet).
+ *         PKT_FIXED_LENGTH_FIX -> fix (the length is set by PCKTLEN0 and PCKTLEN1).
+ * @retval None.
+ */
+#define SpiritPktStackSetFixVarLength(xFixVarLength)                            SpiritPktCommonSetFixVarLength((PktFixVarLength)xFixVarLength)
+
+
+/**
+ * @brief  Enables or Disables the CRC filtering.
+ * @param  xNewState new state for CRC_CHECK.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackFilterOnCrc(xNewState)                                    SpiritPktCommonFilterOnCrc(xNewState)
+
+
+/**
+ * @brief  Returns the CRC filtering bit.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktStackGetFilterOnCrc()                                          SpiritPktCommonGetFilterOnCrc()
+
+
+/**
+ * @brief  Sets the CRC mode for SPIRIT STack packets.
+ * @param  xCrcMode CRC mode.
+ *         This parameter can be any value of @ref StackCrcMode.
+ * @retval None.
+ */
+#define SpiritPktStackSetCrcMode(xCrcMode)                                      SpiritPktCommonSetCrcMode((PktCrcMode)xCrcMode)
+
+
+/**
+ * @brief  Returns the CRC mode for SPIRIT packets.
+ * @param  None.
+ * @retval StackCrcMode Crc mode.
+ */
+#define SpiritPktStackGetCrcMode()                                             (StackCrcMode)SpiritPktCommonGetCrcMode()
+
+
+/**
+ * @brief  Enables or Disables WHITENING for SPIRIT STack packets.
+ * @param  xNewState new state for WHITENING mode.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackWhitening(xNewState)                                     SpiritPktCommonWhitening(xNewState)
+
+
+/**
+ * @brief  Enables or Disables FEC for SPIRIT STack packets.
+ * @param  xNewState new state for FEC mode.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackFec(xNewState)                                            SpiritPktCommonFec(xNewState)
+
+
+/**
+ * @brief  Sets a specific SYNC word for SPIRIT STack packets.
+ * @param  xSyncX SYNC word number to be set.
+ *         This parameter can be any value of @ref StackSyncX.
+ * @param  cSyncWord SYNC word.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetSyncxWord(xSyncX, cSyncWord)                          SpiritPktCommonSetSyncxWord((PktSyncX)xSyncX,cSyncWord)
+
+
+/**
+ * @brief  Returns a specific SYNC word for SPIRIT STack packets.
+ * @param  xSyncX SYNC word number to be get.
+ *         This parameter can be any value of @ref StackSyncX.
+ * @retval uint8_t Sync word x.
+ */
+#define SpiritPktStackGetSyncxWord(xSyncX)                                     SpiritPktCommonGetSyncxWord(xSyncX)
+
+
+/**
+ * @brief  Sets multiple SYNC words for SPIRIT STack packets.
+ * @param  lSyncWords SYNC words to be set with format: 0x|SYNC1|SYNC2|SYNC3|SYNC4|.
+ *         This parameter is a uint32_t.
+ * @param  xSyncLength SYNC length in bytes. The 32bit word passed will be stored in the SYNCx registers from the MSb
+ *         until the number of bytes in xSyncLength has been stored.
+ *         This parameter is a @ref StackSyncLength.
+ * @retval None.
+ */
+#define SpiritPktStackSetSyncWords(lSyncWords, xSyncLength)                    SpiritPktCommonSetSyncWords(lSyncWords,(PktSyncLength)xSyncLength)
+
+
+/**
+ * @brief  Returns multiple SYNC words for SPIRIT packets.
+ * @param  xSyncLength SYNC length in bytes. The 32bit word passed will be stored in the SYNCx registers from the MSb
+ *         until the number of bytes in xSyncLength has been stored.
+ *         This parameter is a pointer to @ref StackSyncLength.
+ * @retval uint32_t Sync words. The format of the read 32 bit word is 0x|SYNC1|SYNC2|SYNC3|SYNC4|.
+ */
+#define SpiritPktStackGetSyncWords(xSyncLength)                                 SpiritPktCommonGetSyncWords((PktSyncLength)xSyncLength)
+
+
+/**
+ * @brief  Returns the SPIRIT variable length width (in number of bits).
+ * @param  None.
+ * @retval uint8_t Variable length width in bits.
+ */
+#define SpiritPktStackGetVarLengthWidth()                                       SpiritPktCommonGetVarLengthWidth()
+
+
+/**
+ * @brief  Sets the destination address for the Tx packet.
+ * @param  cAddress destination address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetDestinationAddress(cAddress)                           SpiritPktCommonSetDestinationAddress(cAddress)
+
+
+/**
+ * @brief  Sets the Rx packet reference source address. The source address extracted from the received packet is masked
+ *         with the source reference mask and then compared to the masked reference value.
+ * @param  cAddress Reference source address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetSourceReferenceAddress(cAddress)                       SpiritPktCommonSetDestinationAddress(cAddress)
+
+
+/**
+ * @brief  Returns the Rx packet reference source address. The source address extracted from the received packet is masked
+ *         with the source reference mask and then compared to the masked reference value.
+ * @param  cAddress Reference source address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktStackGetSourceReferenceAddress()                               SpiritPktCommonGetTransmittedDestAddress()
+
+
+/**
+ * @brief  Returns the settled destination address.
+ * @param  None.
+ * @retval uint8_t Transmitted destination address.
+ */
+#define SpiritPktStackGetTransmittedDestAddress()                               SpiritPktCommonGetTransmittedDestAddress()
+
+
+/**
+ * @brief  Sets the node address. When the filtering on my address is on, if the destination address extracted from the received packet is equal to the content of the
+ *         my address, then the packet is accepted (this is the address of the node).
+ * @param  cAddress Address of the present node.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetMyAddress(cAddress)                                    SpiritPktCommonSetMyAddress(cAddress)
+
+
+/**
+ * @brief  Returns the address of the present node.
+ * @param  None.
+ * @retval uint8_t My address (address of this node).
+ */
+#define SpiritPktStackGetMyAddress()                                            SpiritPktCommonGetMyAddress()
+
+
+/**
+ * @brief  Sets the broadcast address. When the broadcast filtering is on, if the destination address extracted from the received packet is equal to the content of the
+ *         BROADCAST_ADDR register, then the packet is accepted.
+ * @param  cAddress Broadcast address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetBroadcastAddress(cAddress)                             SpiritPktCommonSetBroadcastAddress(cAddress)
+
+
+/**
+ * @brief  Returns the broadcast address.
+ * @param  None.
+ * @retval uint8_t Broadcast address.
+ */
+#define SpiritPktStackGetBroadcastAddress()                                     SpiritPktCommonGetBroadcastAddress()
+
+
+/**
+ * @brief  Sets the multicast address. When the multicast filtering is on, if the destination address extracted from the received packet is equal to the content of the
+ *         MULTICAST_ADDR register, then the packet is accepted.
+ * @param  cAddress Multicast address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetMulticastAddress(cAddress)                             SpiritPktCommonSetMulticastAddress(cAddress)
+
+
+/**
+ * @brief  Returns the multicast address.
+ * @param  None.
+ * @retval uint8_t Multicast address.
+ */
+#define SpiritPktStackGetMulticastAddress()                                     SpiritPktCommonGetMulticastAddress()
+
+
+/**
+ * @brief  Sets the control mask. The 1 bits of the CONTROL_MASK indicate the
+ *         bits to be used in filtering. (All 0s no filtering)
+ * @param  lMask Control mask.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetCtrlMask(lMask)                                        SpiritPktCommonSetCtrlMask(lMask)
+
+
+/**
+ * @brief  Returns the control mask. The 1 bits of the CONTROL_MASK indicate the
+ *         bits to be used in filtering. (All 0s no filtering)
+ * @param  None.
+ * @retval uint32_t Control mask.
+ */
+#define SpiritPktStackGetCtrlMask()                                             SpiritPktCommonGetCtrlMask()
+
+
+/**
+ * @brief  Sets the control field reference. If the bits enabled by the
+ *         CONTROL_MASK match the ones of the control fields extracted from the received packet
+ *         then the packet is accepted.
+ * @param  lReference Control reference.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetCtrlReference(lReference)                              SpiritPktCommonSetCtrlReference(lReference)
+
+
+/**
+ * @brief  Returns the control field reference.
+ * @param  None.
+ * @retval uint32_t Control reference.
+ */
+#define SpiritPktStackGetCtrlReference()                                        SpiritPktCommonGetCtrlReference()
+
+
+/**
+ * @brief  Sets the TX control field.
+ * @param  lField TX CONTROL FIELD.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+#define SpiritPktStackSetTransmittedCtrlField(lField)                           SpiritPktCommonSetTransmittedCtrlField(lField)
+
+
+/**
+ * @brief  Returns the TX control field.
+ * @param  None.
+ * @retval uint32_t Control field of the transmitted packet.
+ */
+#define SpiritPktStackGetTransmittedCtrlField()                                 SpiritPktCommonGetTransmittedCtrlField()
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with TX_SOURCE_ADDRESS.
+ * @param  xNewState new state for DEST_VS_SOURCE_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackFilterOnMyAddress(xNewState)                               SpiritPktCommonFilterOnMyAddress(xNewState)
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with MULTICAST_ADDRESS.
+ * @param  xNewState new state for DEST_VS_MULTICAST_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackFilterOnMulticastAddress(xNewState)                        SpiritPktCommonFilterOnMulticastAddress(xNewState)
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with BROADCAST_ADDRESS.
+ * @param  xNewState new state for DEST_VS_BROADCAST_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackFilterOnBroadcastAddress(xNewState)                        SpiritPktCommonFilterOnBroadcastAddress(xNewState)
+
+
+/**
+ * @brief  Returns the enable bit of the my address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalStateThis parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktStackGetFilterOnMyAddress()                                    SpiritPktCommonGetFilterOnMyAddress();
+
+
+/**
+ * @brief  Returns the enable bit of the multicast address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktStackGetFilterOnMulticastAddress()                             SpiritPktCommonGetFilterOnMulticastAddress();
+
+
+/**
+ * @brief  Returns the enable bit of the broadcast address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktStackGetFilterOnBroadcastAddress()                             SpiritPktCommonGetFilterOnBroadcastAddress();
+
+
+/**
+ * @brief  Returns the control field of the received packet.
+ * @param  None.
+ * @retval uint32_t Received control field.
+ */
+#define SpiritPktStackGetReceivedCtrlField()                                     SpiritPktCommonGetReceivedCtrlField()
+
+
+/**
+ * @brief  Returns the CRC field of the received packet.
+ * @param  cCrcFieldVect array in which the CRC field has to be stored.
+ *         This parameter is an uint8_t array of 3 elements.
+ * @retval None.
+ */
+#define SpiritPktStackGetReceivedCrcField(cCrcFieldVect)                         SpiritPktCommonGetReceivedCrcField(cCrcFieldVect)
+
+/**
+ * @brief  Sets the AUTO ACKNOLEDGEMENT mechanism on the receiver. When the feature is enabled and
+ *         a data packet has been correctly received, then an acknowledgement packet is sent back to the originator of the received
+ *         packet. If the PIGGYBACKING bit is also set, payload data will be read from the FIFO; otherwise an empty packet is sent
+ *         only containing the source and destination addresses and the sequence number of the packet being acknowledged.
+ * @param  xAutoAck new state for autoack.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @param  xPiggybacking new state for autoack.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackAutoAck(xAutoAck, xPiggybacking)                          SpiritPktCommonAutoAck(xAutoAck, xPiggybacking)
+
+
+/**
+ * @brief  Sets the AUTO ACKNOLEDGEMENT mechanism on the transmitter. On the transmitter side, the NACK_TX field can be used to require or not an acknowledgment for each individual packet: if
+ *         NACK_TX is set to "1" then acknowledgment will not be required; if NACK_TX is set to "0" then acknowledgment will be
+ *         required.
+ * @param  xNewState new state for TX_AUTOACK.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackRequireAck(xNewState)                                     SpiritPktCommonRequireAck(xNewState)
+
+
+/**
+ * @brief  Sets the TX sequence number to be used to start counting.
+ * @param  cSeqNumberReload new value for Tx seq number reload.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+#define SpiritPktStackSetTransmittedSeqNumberReload(cSeqNumberReload)           SpiritPktCommonSetTransmittedSeqNumberReload(cSeqNumberReload)
+
+
+/**
+ * @brief  Sets the max number of automatic retransmission.
+ * @param  xNMaxReTx max number of retransmission.
+ *         This parameter can be any value of @ref PktNMaxReTx.
+ * @retval None.
+ */
+#define SpiritPktStackSetNMaxReTx(xNMaxReTx)                                    SpiritPktCommonSetNMaxReTx((PktNMaxReTx)xNMaxReTx)
+
+
+/**
+ * @brief  Returns the max number of automatic retransmission.
+ * @param  None.
+ * @retval uint8_t Max number of retransmissions.
+ */
+#define SpiritPktStackGetNMaxReTx()                                             SpiritPktCommonGetNMaxReTx()
+
+
+/**
+ * @brief  Returns the TX ACK request.
+ * @param  None.
+ * @retval SpiritFunctionalState.
+ */
+#define SpiritPktStackGetGetTxAckRequest()                                       SpiritPktCommonGetTxAckRequest()
+
+/**
+ * @brief  Returns the destination address of the received packet.
+ * @param  None.
+ * @retval uint8_t Destination address of the received packet.
+ */
+#define SpiritPktStackGetReceivedDestAddress()                                  SpiritPktCommonGetReceivedDestAddress()
+
+
+/**
+ * @brief  Returns the source address of the received packet.
+ * @param  None.
+ * @retval uint8_t Source address of the received packet.
+ */
+#define SpiritPktStackGetReceivedSourceAddress()                                SpiritPktCommonGetReceivedSourceAddress()
+
+
+/**
+ * @brief  Returns the sequence number of the received packet.
+ * @param  None.
+ * @retval uint8_t Received Sequence number.
+ */
+#define SpiritPktStackGetReceivedSeqNumber()                                    SpiritPktCommonGetReceivedSeqNumber()
+
+
+/**
+ * @brief  Returns the Nack bit of the received packet
+ * @param  None.
+ * @retval uint8_t Value of the NAck bit.
+ */
+#define SpiritPktStackGetReceivedNackRx()                                       SpiritPktCommonGetReceivedNackRx()
+
+
+/**
+ * @brief  Returns the sequence number of the transmitted packet.
+ * @param  None.
+ * @retval uint8_t Sequence number of the transmitted packet.
+ */
+#define SpiritPktStackGetTransmittedSeqNumber()                                 SpiritPktCommonGetTransmittedSeqNumber()
+
+
+/**
+ * @brief  Returns the number of retransmission done on the transmitted packet.
+ * @param  None.
+ * @retval uint8_t Number of retransmissions done until now.
+ */
+#define SpiritPktStackGetNReTx()                                                SpiritPktCommonGetNReTx()
+
+
+/**
+ * @brief  If enabled RX packet is accepted only if the masked control field matches the
+ *         masked control field reference (CONTROL_MASK & CONTROL_FIELD_REF == CONTROL_MASK & RX_CONTROL_FIELD).
+ * @param  xNewState new state for Control filtering enable bit.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ * @note   This filtering control is enabled by default but the control mask is by default set to 0.
+ *         As a matter of fact the user has to enable the control filtering bit after the packet initialization
+ *         because the PktInit routine disables it.
+ */
+#define SpiritPktStackFilterOnControlField(xNewState)                           SpiritPktCommonFilterOnControlField(xNewState)
+
+
+/**
+ * @brief  Returns the enable bit of the control field filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+#define SpiritPktStackGetFilterOnControlField()                                 SpiritPktCommonGetFilterOnControlField();
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktStack_Exported_Functions        Pkt STack Exported Functions
+ * @{
+ */
+
+void SpiritPktStackInit(PktStackInit* pxPktStackInit);
+void SpiritPktStackGetInfo(PktStackInit* pxPktStackInit);
+void SpiritPktStackAddressesInit(PktStackAddressesInit* pxPktStackAddresses);
+void SpiritPktStackGetAddressesInfo(PktStackAddressesInit* pxPktStackAddresses);
+void SpiritPktStackLlpInit(PktStackLlpInit* pxPktStackLlpInit);
+void SpiritPktStackLlpGetInfo(PktStackLlpInit* pxPktStackLlpInit);
+void SpiritPktStackSetFormat(void);
+void SpiritPktStackSetPayloadLength(uint16_t nPayloadLength);
+uint16_t SpiritPktStackGetPayloadLength(void);
+void SpiritPktStackSetVarLengthWidth(uint16_t nMaxPayloadLength, StackControlLength xControlLength);
+void SpiritPktStackSetRxSourceMask(uint8_t cMask);
+uint8_t SpiritPktStackGetRxSourceMask(void);
+uint16_t SpiritPktStackGetReceivedPktLength(void);
+void SpiritPktStackFilterOnSourceAddress(SpiritFunctionalState xNewState);
+void SpiritPktStackSetAddressLength(void);
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Qi.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Qi.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,300 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Qi.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT QI.
+ * @details
+ *
+ * This module can be used to configure and read some quality indicators
+ * used by Spirit.
+ * API to set thresholds and to read values in raw mode or in dBm are
+ * provided.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *   float rssiValuedBm;
+ *   uint8_t pqiValue, sqiValue;
+ *
+ *   SpiritQiPqiCheck(S_ENABLE);
+ *   SpiritQiSqiCheck(S_ENABLE);
+ *
+ *   ...
+ *
+  *   rssiValueDbm = SpiritQiGetRssidBm();
+ *   pqiValue = SpiritQiGetPqi();
+ *   sqiValue = SpiritQiGetSqi();
+ *
+ *   ...
+ *
+ * @endcode
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_QI_H
+#define __SPIRIT_QI_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_Qi          QI
+ * @brief Configuration and management of SPIRIT QI.
+ * @details See the file <i>@ref SPIRIT_Qi.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup Qi_Exported_Types  QI Exported Types
+ * @{
+ */
+
+
+/**
+ * @brief  PQI threshold value enumeration.
+ */
+typedef enum
+{
+   PQI_TH_0=0x00,
+   PQI_TH_1=0x04,
+   PQI_TH_2=0x08,
+   PQI_TH_3=0x0C,
+   PQI_TH_4=0x10,
+   PQI_TH_5=0x14,
+   PQI_TH_6=0x18,
+   PQI_TH_7=0x1C,
+   PQI_TH_8=0x20,
+   PQI_TH_9=0x24,
+   PQI_TH_10=0x28,
+   PQI_TH_11=0x2C,
+   PQI_TH_12=0x30,
+   PQI_TH_13=0x34,
+   PQI_TH_14=0x38,
+   PQI_TH_15=0x3C
+
+} PqiThreshold;
+
+#define IS_PQI_THR(VALUE)   (VALUE==PQI_TH_0 ||\
+                             VALUE==PQI_TH_1 ||\
+                             VALUE==PQI_TH_2 ||\
+                             VALUE==PQI_TH_3 ||\
+                             VALUE==PQI_TH_4 ||\
+                             VALUE==PQI_TH_5 ||\
+                             VALUE==PQI_TH_6 ||\
+                             VALUE==PQI_TH_7 ||\
+                             VALUE==PQI_TH_8 ||\
+                             VALUE==PQI_TH_9 ||\
+                             VALUE==PQI_TH_10 ||\
+                             VALUE==PQI_TH_11 ||\
+                             VALUE==PQI_TH_12 ||\
+                             VALUE==PQI_TH_13 ||\
+                             VALUE==PQI_TH_14 ||\
+                             VALUE==PQI_TH_15)
+
+/**
+ * @brief  SQI threshold value enumeration.
+ */
+typedef enum
+{
+   SQI_TH_0=0x00,
+   SQI_TH_1=0x40,
+   SQI_TH_2=0x80,
+   SQI_TH_3=0xC0
+
+} SqiThreshold;
+
+#define IS_SQI_THR(VALUE)   (VALUE==SQI_TH_0 ||\
+                             VALUE==SQI_TH_1 ||\
+                             VALUE==SQI_TH_2 ||\
+                             VALUE==SQI_TH_3)
+
+
+/**
+ * @brief  RSSI filter gain value enumeration.
+ */
+typedef enum
+{
+   RSSI_FG_0=0x00,
+   RSSI_FG_1=0x10,
+   RSSI_FG_2=0x20,
+   RSSI_FG_3=0x30,
+   RSSI_FG_4=0x40,
+   RSSI_FG_5=0x50,
+   RSSI_FG_6=0x60,
+   RSSI_FG_7=0x70,
+   RSSI_FG_8=0x80,
+   RSSI_FG_9=0x90,
+   RSSI_FG_10=0xA0,
+   RSSI_FG_11=0xB0,
+   RSSI_FG_12=0xC0,
+   RSSI_FG_13=0xD0,
+   RSSI_FG_14=0xE0,     /*<! recommended value */
+   RSSI_FG_15=0xF0
+
+} RssiFilterGain;
+
+#define IS_RSSI_FILTER_GAIN(VALUE)  (VALUE==RSSI_FG_0 ||\
+                                     VALUE==RSSI_FG_1 ||\
+                                     VALUE==RSSI_FG_2 ||\
+                                     VALUE==RSSI_FG_3 ||\
+                                     VALUE==RSSI_FG_4 ||\
+                                     VALUE==RSSI_FG_5 ||\
+                                     VALUE==RSSI_FG_6 ||\
+                                     VALUE==RSSI_FG_7 ||\
+                                     VALUE==RSSI_FG_8 ||\
+                                     VALUE==RSSI_FG_9 ||\
+                                     VALUE==RSSI_FG_10 ||\
+                                     VALUE==RSSI_FG_11 ||\
+                                     VALUE==RSSI_FG_12 ||\
+                                     VALUE==RSSI_FG_13 ||\
+                                     VALUE==RSSI_FG_14 ||\
+                                     VALUE==RSSI_FG_15)
+
+/**
+ * @brief  CS mode enumeration.
+ */
+typedef enum
+{
+   CS_MODE_STATIC_3DB=0x00,
+   CS_MODE_DYNAMIC_6DB=0x04,
+   CS_MODE_DYNAMIC_12DB=0x08,
+   CS_MODE_DYNAMIC_18DB=0x0C
+
+} CSMode;
+
+#define IS_CS_MODE(MODE)    (MODE==CS_MODE_STATIC_3DB ||\
+                             MODE==CS_MODE_DYNAMIC_6DB ||\
+                             MODE==CS_MODE_DYNAMIC_12DB ||\
+                             MODE==CS_MODE_DYNAMIC_18DB)
+
+/**
+  *@}
+  */
+
+
+/**
+ * @defgroup Qi_Exported_Constants      QI Exported Constants
+ * @{
+ */
+
+/*  range for the RSSI Threshold in dBm  */
+#define IS_RSSI_THR_DBM(VALUE)  (VALUE>=-130 && VALUE<=-2)
+
+/**
+  *@}
+  */
+
+
+/**
+ * @defgroup Qi_Exported_Macros         QI Exported Macros
+ * @{
+ */
+
+/**
+ * @brief  Macro to obtain the RSSI value in dBm
+ * @param  None.
+ * @retval RSSI in dBm.
+ *         This parameter is a float.
+ */
+#define SpiritQiGetRssidBm()            (-120.0+((float)(SpiritQiGetRssi()-20))/2)
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Qi_Exported_Functions       QI Exported Functions
+ * @{
+ */
+
+void SpiritQiPqiCheck(SpiritFunctionalState xNewState);
+void SpiritQiSqiCheck(SpiritFunctionalState xNewState);
+void SpiritQiSetPqiThreshold(PqiThreshold xPqiThr);
+PqiThreshold SpiritQiGetPqiThreshold(void);
+void SpiritQiSetSqiThreshold(SqiThreshold xSqiThr);
+SqiThreshold SpiritQiGetSqiThreshold(void);
+void SpiritQiSetRssiThreshold(uint8_t cRssiThr);
+uint8_t SpiritQiGetRssiThreshold(void);
+uint8_t SpiritQiComputeRssiThreshold(int cDbmValue);
+void SpiritQiSetRssiThresholddBm(int nDbmValue);
+uint8_t SpiritQiGetPqi(void);
+uint8_t SpiritQiGetSqi(void);
+uint8_t SpiritQiGetLqi(void);
+SpiritFlagStatus SpiritQiGetCs(void);
+uint8_t SpiritQiGetRssi(void);
+void SpiritQiSetRssiFilterGain(RssiFilterGain xRssiFg);
+RssiFilterGain SpiritQiGetRssiFilterGain(void);
+void SpiritQiSetCsMode(CSMode xCsMode);
+CSMode SpiritQiGetCsMode(void);
+void SpiritQiCsTimeoutMask(SpiritFunctionalState xNewState);
+void SpiritQiPqiTimeoutMask(SpiritFunctionalState xNewState);
+void SpiritQiSqiTimeoutMask(SpiritFunctionalState xNewState);
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Radio.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Radio.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,636 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Radio.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   This file provides all the low level API to manage Analog and Digital
+  *          radio part of SPIRIT.
+ * @details
+ *
+ * In order to configure the Radio main parameters, the user can
+ * fit <i>SRadioInit</i> structure the and call the <i>SpiritRadioInit()</i>
+ * function passing its pointer as an argument.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ * SRadioInit radioInit = {
+ *     0,                       // Xtal offset in ppm
+ *     433.4e6,                 // base frequency
+ *     20e3,                    // channel space
+ *     0,                       // channel number
+ *     FSK,                     // modulation select
+ *     38400,                   // datarate
+ *     20e3,                    // frequency deviation
+ *     100.5e3                  // channel filter bandwidth
+ * };
+ *
+ * ...
+ *
+ * SpiritRadioInit(&radioInit);
+ * @endcode
+ *
+ * Another important parameter for the radio configuration is the
+ * transmission power.
+ * The user is allowed to configure it using the function <i>SpiritRadioSetPALeveldBm()</i>
+ * which sets the PA LEVEL specified by the first argument to the
+ * power expressed in dBm by the second parameter.
+ *
+ * <b>Example:</b>
+ * @code
+ *
+ *  SpiritRadioSetPALeveldBm(0 , 10.0);
+ *
+ * @endcode
+ *
+ *
+ * @note The effective power that is set can be a little different from the
+ * passed argument in dBm because the function performs an approximation.
+ *
+
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_RADIO_H
+#define __SPIRIT_RADIO_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+#include "SPIRIT_Config.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/** @defgroup SPIRIT_Radio          Radio
+ * @brief Configuration and management of SPIRIT RF Analog and Digital part.
+ * @details See the file <i>@ref SPIRIT_Radio.h</i> for more details.
+ * @{
+ */
+
+
+
+/** @defgroup Radio_Exported_Types      Radio Exported Types
+ * @{
+ */
+
+
+/**
+ * @brief  SPIRIT XTAL frequency enumeration
+ */
+typedef enum
+{
+  XTAL_FLAG_24_MHz     = 0x00, /*!< 24 MHz Xtal selected */
+  XTAL_FLAG_26_MHz     = 0x01  /*!< 26 MHz Xtal selected */
+
+}XtalFlag;
+
+
+#define IS_XTAL_FLAG(FLAG) (((FLAG) == XTAL_FLAG_24_MHz) || \
+                            ((FLAG) == XTAL_FLAG_26_MHz))
+
+/**
+ * @brief  SPIRIT Band enumeration
+ */
+typedef enum
+{
+  HIGH_BAND     = 0x00, /*!< High_Band selected: from 779 MHz to 915 MHz */
+  MIDDLE_BAND   = 0x01, /*!< Middle Band selected: from 387 MHz to 470 MHz */
+  LOW_BAND      = 0x02,  /*!< Low Band selected: from 300 MHz to 348 MHz */
+  VERY_LOW_BAND = 0x03  /*!< Vary low Band selected: from 150 MHz to 174 MHz */
+}BandSelect;
+
+
+#define IS_BAND_SELECTED(BAND) ((BAND == HIGH_BAND) || \
+                                (BAND == MIDDLE_BAND) || \
+                                (BAND == LOW_BAND) || \
+                                (BAND == VERY_LOW_BAND))
+
+/**
+ * @brief  SPIRIT Modulation enumeration
+ */
+typedef enum
+{
+  FSK         = 0x00, /*!< 2-FSK modulation selected */
+  GFSK_BT05   = 0x50, /*!< GFSK modulation selected with BT=0.5 */
+  GFSK_BT1    = 0x10, /*!< GFSK modulation selected with BT=1 */
+  ASK_OOK     = 0x20, /*!< ASK or OOK modulation selected. ASK will use power ramping */
+  MSK         = 0x30  /*!< MSK modulation selected */
+
+}ModulationSelect;
+
+
+#define IS_MODULATION_SELECTED(MOD) (((MOD) == FSK) || \
+                                     ((MOD) == GFSK_BT05) || \
+                                     ((MOD) == GFSK_BT1) || \
+                                     ((MOD) == ASK_OOK) || \
+                                     ((MOD) == MSK))
+
+
+/**
+ * @brief  SPIRIT PA additional load capacitors bank enumeration
+ */
+typedef enum
+{
+  LOAD_0_PF    = PA_POWER0_CWC_0,    /*!< No additional PA load capacitor */
+  LOAD_1_2_PF  = PA_POWER0_CWC_1_2P, /*!< 1.2pF additional PA load capacitor */
+  LOAD_2_4_PF  = PA_POWER0_CWC_2_4P, /*!< 2.4pF additional PA load capacitor */
+  LOAD_3_6_PF  = PA_POWER0_CWC_3_6P  /*!< 3.6pF additional PA load capacitor */
+
+}PALoadCapacitor;
+
+#define IS_PA_LOAD_CAP(CWC) (((CWC) == LOAD_0_PF) || \
+                             ((CWC) == LOAD_1_2_PF) || \
+                             ((CWC) == LOAD_2_4_PF) || \
+                             ((CWC) == LOAD_3_6_PF))
+
+
+/**
+ * @brief  SPIRIT AFC Mode selection
+ */
+typedef enum
+{
+  AFC_SLICER_CORRECTION  = AFC2_AFC_MODE_SLICER,    /*!< AFC loop closed on slicer */
+  AFC_2ND_IF_CORRECTION  = AFC2_AFC_MODE_MIXER      /*!< AFC loop closed on 2nd conversion stage */
+
+}AFCMode;
+
+#define IS_AFC_MODE(MODE)   ((MODE) == AFC_SLICER_CORRECTION || (MODE) == AFC_2ND_IF_CORRECTION)
+
+
+/**
+ * @brief  SPIRIT AGC Mode selection
+ */
+typedef enum
+{
+  AGC_LINEAR_MODE  = AGCCTRL0_AGC_MODE_LINEAR,    /*!< AGC works in linear mode */
+  AGC_BINARY_MODE  = AGCCTRL0_AGC_MODE_BINARY     /*!< AGC works in binary mode */
+
+}AGCMode;
+
+#define IS_AGC_MODE(MODE)   ((MODE) == AGC_LINEAR_MODE || (MODE) == AGC_BINARY_MODE)
+
+
+/**
+ * @brief  SPIRIT Clock Recovery Mode selection
+ */
+typedef enum
+{
+  CLK_REC_PLL  = FDEV0_CLOCK_REG_ALGO_SEL_PLL,    /*!< PLL alogrithm for clock recovery */
+  CLK_REC_DLL  = FDEV0_CLOCK_REG_ALGO_SEL_DLL     /*!< DLL alogrithm for clock recovery */
+
+}ClkRecMode;
+
+#define IS_CLK_REC_MODE(MODE)   ((MODE) == CLK_REC_PLL || (MODE) == CLK_REC_DLL)
+
+
+/**
+ * @brief  SPIRIT Postfilter length
+ */
+typedef enum
+{
+  PSTFLT_LENGTH_8   = 0x00,    /*!< Postfilter length is 8 symbols */
+  PSTFLT_LENGTH_16  = 0x10     /*!< Postfilter length is 16 symbols */
+
+}PstFltLength;
+
+#define IS_PST_FLT_LENGTH(LENGTH)   ((LENGTH) == PSTFLT_LENGTH_8 || (LENGTH) == PSTFLT_LENGTH_16)
+
+
+/**
+ * @brief  SPIRIT OOK Peak Decay
+ */
+typedef enum
+{
+  FAST_DECAY   = 0x00,        /*!< Peak decay control for OOK: fast decay */
+  MEDIUM_FAST_DECAY  = 0x01,  /*!< Peak decay control for OOK: medium_fast decay */
+  MEDIUM_SLOW_DECAY = 0x02,   /*!< Peak decay control for OOK: medium_fast decay */
+  SLOW_DECAY = 0x03           /*!< Peak decay control for OOK: slow decay */
+
+}OokPeakDecay;
+
+#define IS_OOK_PEAK_DECAY(DECAY)   (((DECAY) == FAST_DECAY) ||\
+                                    ((DECAY) == MEDIUM_FAST_DECAY) ||\
+                                    ((DECAY) == MEDIUM_SLOW_DECAY) ||\
+                                    ((DECAY) == SLOW_DECAY))
+
+
+/**
+ * @brief  SPIRIT Radio Init structure definition
+ */
+typedef struct
+{
+  int16_t           nXtalOffsetPpm;     /*!< Specifies the offset frequency (in ppm)
+                                             to compensate crystal inaccuracy expressed
+                                             as signed value.*/
+
+  uint32_t          lFrequencyBase;     /*!< Specifies the base carrier frequency (in Hz),
+                                             i.e. the carrier frequency of channel #0.
+                                             This parameter can be in one of the following ranges:
+                                             High_Band: from 779 MHz to 915 MHz
+                                             Middle Band: from 387 MHz to 470 MHz
+                                             Low Band: from 300 MHz to 348 MHz */
+  uint32_t          nChannelSpace;      /*!< Specifies the channel spacing expressed in Hz.
+                                             The channel spacing is expressed as:
+                                             NxFREQUENCY_STEPS, where FREQUENCY STEPS
+                                             is F_Xo/2^15.
+                                             This parameter can be in the range: [0, F_Xo/2^15*255] Hz */
+  uint8_t           cChannelNumber;      /*!< Specifies the channel number. This value
+                                             is multiplied by the channel spacing and
+                                             added to synthesizer base frequency to
+                                             generate the actual RF carrier frequency */
+  ModulationSelect  xModulationSelect;   /*!< Specifies the modulation. This
+                                             parameter can be any value of
+                                             @ref ModulationSelect */
+  uint32_t          lDatarate;          /*!< Specifies the datarate expressed in bps.
+                                             This parameter can be in the range between
+                                             100 bps and 500 kbps */
+  uint32_t          lFreqDev;           /*!< Specifies the frequency deviation expressed in Hz.
+                                             This parameter can be in the range: [F_Xo*8/2^18, F_Xo*7680/2^18] Hz */
+  uint32_t          lBandwidth;          /*!< Specifies the channel filter bandwidth
+                                             expressed in Hz. This parameter can be
+                                             in the range between 1100 and 800100 Hz */
+
+}SRadioInit;
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Radio_Exported_Constants       Radio Exported Constants
+ * @{
+ */
+
+/** @defgroup Radio_Band
+ * @{
+ */
+
+#define FBASE_DIVIDER           262144           /*!< 2^18 factor dividing fxo in fbase formula */
+
+#define HIGH_BAND_FACTOR      6       /*!< Band select factor for high band. Factor B in the equation 2 */
+#define MIDDLE_BAND_FACTOR    12      /*!< Band select factor for middle band. Factor B in the equation 2 */
+#define LOW_BAND_FACTOR       16      /*!< Band select factor for low band. Factor B in the equation 2 */
+#define VERY_LOW_BAND_FACTOR  32      /*!< Band select factor for very low band. Factor B in the equation 2 */
+
+#define HIGH_BAND_LOWER_LIMIT         778000000   /*!< Lower limit of the high band: 779 MHz */
+#define HIGH_BAND_UPPER_LIMIT         957100000   /*!< Upper limit of the high band: 956 MHz */
+#define MIDDLE_BAND_LOWER_LIMIT       386000000   /*!< Lower limit of the middle band: 387 MHz */
+#define MIDDLE_BAND_UPPER_LIMIT       471100000   /*!< Upper limit of the middle band: 470 MHz */
+#define LOW_BAND_LOWER_LIMIT          299000000   /*!< Lower limit of the low band: 300 MHz */
+#define LOW_BAND_UPPER_LIMIT          349100000   /*!< Upper limit of the low band: 348 MHz */
+#define VERY_LOW_BAND_LOWER_LIMIT     149000000   /*!< Lower limit of the very low band: 150 MHz */
+#define VERY_LOW_BAND_UPPER_LIMIT     175100000   /*!< Upper limit of the very low band: 174 MHz */
+
+#define IS_FREQUENCY_BAND_HIGH(FREQUENCY) ((FREQUENCY)>=HIGH_BAND_LOWER_LIMIT && \
+                                           (FREQUENCY)<=HIGH_BAND_UPPER_LIMIT)
+
+#define IS_FREQUENCY_BAND_MIDDLE(FREQUENCY) ((FREQUENCY)>=MIDDLE_BAND_LOWER_LIMIT && \
+                                             (FREQUENCY)<=MIDDLE_BAND_UPPER_LIMIT)
+
+#define IS_FREQUENCY_BAND_LOW(FREQUENCY) ((FREQUENCY)>=LOW_BAND_LOWER_LIMIT && \
+                                          (FREQUENCY)<=LOW_BAND_UPPER_LIMIT)
+
+#define IS_FREQUENCY_BAND_VERY_LOW(FREQUENCY) ((FREQUENCY)>=VERY_LOW_BAND_LOWER_LIMIT && \
+                                          (FREQUENCY)<=VERY_LOW_BAND_UPPER_LIMIT)
+
+#define IS_FREQUENCY_BAND(FREQUENCY) (IS_FREQUENCY_BAND_HIGH(FREQUENCY)|| \
+                                      IS_FREQUENCY_BAND_MIDDLE(FREQUENCY)|| \
+                                      IS_FREQUENCY_BAND_LOW(FREQUENCY)|| \
+                                      IS_FREQUENCY_BAND_VERY_LOW(FREQUENCY))
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_IF_Offset           Radio IF Offset
+ * @{
+ */
+#define IF_OFFSET_ANA(F_Xo) (lroundf(480140.0/(F_Xo)*12288-64.0))      /*!< It represents the IF_OFFSET_ANA in order
+                                                                               to have an intermediate frequency of 480 kHz */
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_FC_Offset                   Radio FC Offset
+ * @{
+ */
+#define F_OFFSET_DIVIDER           262144             /*!< 2^18 factor dividing fxo in foffset formula */
+#define PPM_FACTOR                 1000000            /*!< 10^6 factor to use with Xtal_offset_ppm */
+
+
+#define F_OFFSET_LOWER_LIMIT(F_Xo)			((-(int32_t)F_Xo)/F_OFFSET_DIVIDER*2048)
+#define F_OFFSET_UPPER_LIMIT(F_Xo)			((int32_t)(F_Xo/F_OFFSET_DIVIDER*2047))
+
+#define IS_FREQUENCY_OFFSET(OFFSET, F_Xo) (OFFSET>=F_OFFSET_LOWER_LIMIT(F_Xo) && OFFSET<=F_OFFSET_UPPER_LIMIT(F_Xo))
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_Channel_Space          Radio Channel Space
+ * @{
+ */
+
+
+#define CHSPACE_DIVIDER         32768              /*!< 2^15 factor dividing fxo in channel space formula */
+
+#define IS_CHANNEL_SPACE(CHANNELSPACE, F_Xo)    (CHANNELSPACE<=(F_Xo/32768*255))
+
+
+
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_Datarate                    Radio Datarate
+ * @{
+ */
+#define MINIMUM_DATARATE                 100  /*!< Minimum datarate supported by SPIRIT1 100 bps */
+#define MAXIMUM_DATARATE                 510000  /*!< Maximum datarate supported by SPIRIT1 500 kbps */
+
+#define IS_DATARATE(DATARATE)           (DATARATE>=MINIMUM_DATARATE && DATARATE<=MAXIMUM_DATARATE)
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_Frequency_Deviation         Radio Frequency Deviation
+ * @{
+ */
+#define F_DEV_MANTISSA_UPPER_LIMIT      7  /*!< Maximum value for the mantissa in frequency deviation formula */
+#define F_DEV_EXPONENT_UPPER_LIMIT      9  /*!< Maximum value for the exponent in frequency deviation formula */
+
+#define F_DEV_LOWER_LIMIT(F_Xo)		(F_Xo>>16)
+#define F_DEV_UPPER_LIMIT(F_Xo)		((F_Xo*15)>>10)
+
+#define IS_F_DEV(FDEV,F_Xo)             (FDEV>=F_DEV_LOWER_LIMIT(F_Xo) && FDEV<=F_DEV_UPPER_LIMIT(F_Xo))
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_Channel_Bandwidth           Radio Channel Bandwidth
+ * @{
+ */
+#define CH_BW_LOWER_LIMIT(F_Xo)      1100*(F_Xo/1000000)/26  /*!< Minimum value of the channel filter bandwidth */
+#define CH_BW_UPPER_LIMIT(F_Xo)    800100*(F_Xo/1000000)/26  /*!< Maximum value of the channel filter bandwidth */
+
+#define IS_CH_BW(BW,F_Xo)         ((BW)>=CH_BW_LOWER_LIMIT(F_Xo) && (BW)<=CH_BW_UPPER_LIMIT(F_Xo))
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_Power_Amplifier                     Radio Power Amplifier
+ * @{
+ */
+
+#define IS_PA_MAX_INDEX(INDEX)       ((INDEX)<=7)
+#define IS_PAPOWER_DBM(PATABLE)      ((PATABLE)>= (-31) && (PATABLE)<=(12))
+#define IS_PAPOWER(PATABLE)          ((PATABLE)<=90)
+#define IS_PA_STEP_WIDTH(WIDTH)      ((WIDTH)>=1 && (WIDTH)<=4)
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_Automatic_Frequency_Correction              Radio Automatic Frequency Correction
+ * @{
+ */
+
+#define IS_AFC_FAST_GAIN(GAIN)      	((GAIN)<=15)
+#define IS_AFC_SLOW_GAIN(GAIN)      	((GAIN)<=15)
+#define IS_AFC_PD_LEAKAGE(LEAKAGE)      ((LEAKAGE)<=31)
+
+/**
+ * @}
+ */
+
+/** @defgroup Radio_Automatic_Gain_Control                      Radio Automatic Gain Control
+ * @{
+ */
+
+#define AGC_MEASURE_TIME_UPPER_LIMIT_US(F_Xo)		(393216.0/F_Xo)
+
+#define IS_AGC_MEASURE_TIME_US(TIME, F_Xo)              (TIME<=AGC_MEASURE_TIME_UPPER_LIMIT_US(F_Xo))
+
+#define IS_AGC_MEASURE_TIME(TIME)                       (TIME<=15)
+
+#define AGC_HOLD_TIME_UPPER_LIMIT_US(F_Xo)		(756.0/F_Xo)
+
+#define IS_AGC_HOLD_TIME_US(TIME,F_Xo)                  (TIME<=AGC_HOLD_TIME_UPPER_LIMIT_US(F_Xo))
+
+
+#define IS_AGC_HOLD_TIME(TIME)                          (TIME<=63)
+
+#define IS_AGC_THRESHOLD(THRESHOLD)                     (THRESHOLD<=15)
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_Clock_Recovery                      Radio Clock Recovery
+ * @{
+ */
+
+#define IS_CLK_REC_P_GAIN(GAIN)       ((GAIN)<=7)
+#define IS_CLK_REC_I_GAIN(GAIN)       ((GAIN)<=15)
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Radio_Exported_Macros                             Radio Exported Macros
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+/** @defgroup Radio_Exported_Functions                          Radio Exported Functions
+ * @{
+ */
+
+uint8_t SpiritRadioInit(SRadioInit* pxSRadioInitStruct);
+void SpiritRadioGetInfo(SRadioInit* pxSRadioInitStruct);
+void SpiritRadioSetXtalFlag(XtalFlag xXtal);
+XtalFlag SpiritRadioGetXtalFlag(void);
+uint8_t SpiritRadioSearchWCP(uint32_t lFc);
+void SpiritRadioSetSynthWord(uint32_t lSynthWord);
+uint32_t SpiritRadioGetSynthWord(void);
+void SpiritRadioSetBand(BandSelect xBand);
+BandSelect SpiritRadioGetBand(void);
+void SpiritRadioSetChannel(uint8_t cChannel);
+uint8_t SpiritRadioGetChannel(void);
+void SpiritRadioSetChannelSpace(uint32_t lChannelSpace);
+uint32_t SpiritRadioGetChannelSpace(void);
+void SpiritRadioSetFrequencyOffsetPpm(int16_t nXtalPpm);
+void SpiritRadioSetFrequencyOffset(int32_t lFOffset);
+int32_t SpiritRadioGetFrequencyOffset(void);
+void SpiritRadioVcoCalibrationWAFB(SpiritFunctionalState xNewstate);
+uint8_t SpiritRadioSetFrequencyBase(uint32_t lFBase);
+uint32_t SpiritRadioGetFrequencyBase(void);
+uint32_t SpiritRadioGetCenterFrequency(void);
+void SpiritRadioSearchDatarateME(uint32_t lDatarate, uint8_t* pcM, uint8_t* pcE);
+void SpiritRadioSearchFreqDevME(uint32_t lFDev, uint8_t* pcM, uint8_t* pcE);
+void SpiritRadioSearchChannelBwME(uint32_t lBandwidth, uint8_t* pcM, uint8_t* pcE);
+void SpiritRadioSetDatarate(uint32_t lDatarate);
+uint32_t SpiritRadioGetDatarate(void);
+void SpiritRadioSetFrequencyDev(uint32_t lFDev);
+uint32_t SpiritRadioGetFrequencyDev(void);
+void SpiritRadioSetChannelBW(uint32_t lBandwidth);
+uint32_t SpiritRadioGetChannelBW(void);
+void SpiritRadioSetModulation(ModulationSelect xModulation);
+ModulationSelect SpiritRadioGetModulation(void);
+void SpiritRadioCWTransmitMode(SpiritFunctionalState xNewState);
+void SpiritRadioSetOokPeakDecay(OokPeakDecay xOokDecay);
+OokPeakDecay SpiritRadioGetOokPeakDecay(void);
+uint8_t SpiritRadioGetdBm2Reg(uint32_t lFBase, float fPowerdBm);
+float SpiritRadioGetReg2dBm(uint32_t lFBase, uint8_t cPowerReg);
+void SpiritRadioSetPATabledBm(uint8_t cPALevelMaxIndex, uint8_t cWidth, PALoadCapacitor xCLoad, float* pfPAtabledBm);
+void SpiritRadioGetPATabledBm(uint8_t* pcPALevelMaxIndex, float* pfPAtabledBm);
+void SpiritRadioSetPATable(uint8_t cPALevelMaxIndex, uint8_t cWidth, PALoadCapacitor xCLoad, uint8_t* pcPAtable);
+void SpiritRadioGetPATable(uint8_t* pcPALevelMaxIndex, uint8_t* pcPAtable);
+void SpiritRadioSetPALeveldBm(uint8_t cIndex, float fPowerdBm);
+float SpiritRadioGetPALeveldBm(uint8_t cIndex);
+void SpiritRadioSetPALevel(uint8_t cIndex, uint8_t cPower);
+uint8_t SpiritRadioGetPALevel(uint8_t cIndex);
+void SpiritRadioSetPACwc(PALoadCapacitor xCLoad);
+PALoadCapacitor SpiritRadioGetPACwc(void);
+void SpiritRadioSetPALevelMaxIndex(uint8_t cIndex);
+uint8_t SpiritRadioGetPALevelMaxIndex(void);
+void SpiritRadioSetPAStepWidth(uint8_t cWidth);
+uint8_t SpiritRadioGetPAStepWidth(void);
+void SpiritRadioPARamping(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritRadioGetPARamping(void);
+void SpiritRadioAFC(SpiritFunctionalState xNewState);
+void SpiritRadioAFCFreezeOnSync(SpiritFunctionalState xNewState);
+void SpiritRadioSetAFCMode(AFCMode xMode);
+AFCMode SpiritRadioGetAFCMode(void);
+void SpiritRadioSetAFCPDLeakage(uint8_t cLeakage);
+uint8_t SpiritRadioGetAFCPDLeakage(void);
+void SpiritRadioSetAFCFastPeriod(uint8_t cLength);
+uint8_t SpiritRadioGetAFCFastPeriod(void);
+void SpiritRadioSetAFCFastGain(uint8_t cGain);
+uint8_t SpiritRadioGetAFCFastGain(void);
+void SpiritRadioSetAFCSlowGain(uint8_t cGain);
+uint8_t SpiritRadioGetAFCSlowGain(void);
+int8_t SpiritRadioGetAFCCorrectionReg(void);
+int32_t SpiritRadioGetAFCCorrectionHz(void);
+void SpiritRadioAGC(SpiritFunctionalState xNewState);
+void SpiritRadioSetAGCMode(AGCMode xMode);
+AGCMode SpiritRadioGetAGCMode(void);
+void SpiritRadioAGCFreezeOnSteady(SpiritFunctionalState xNewState);
+void SpiritRadioAGCFreezeOnSync(SpiritFunctionalState xNewState);
+void SpiritRadioAGCStartMaxAttenuation(SpiritFunctionalState xNewState);
+void SpiritRadioSetAGCMeasureTimeUs(uint16_t nTime);
+uint16_t SpiritRadioGetAGCMeasureTimeUs(void);
+void SpiritRadioSetAGCMeasureTime(uint8_t cTime);
+uint8_t SpiritRadioGetAGCMeasureTime(void);
+void SpiritRadioSetAGCHoldTimeUs(uint8_t cTime);
+uint8_t SpiritRadioGetAGCHoldTimeUs(void);
+void SpiritRadioSetAGCHoldTime(uint8_t cTime);
+uint8_t SpiritRadioGetAGCHoldTime(void);
+void SpiritRadioSetAGCHighThreshold(uint8_t cHighThreshold);
+uint8_t SpiritRadioGetAGCHighThreshold(void);
+void SpiritRadioSetAGCLowThreshold(uint8_t cLowThreshold);
+uint8_t SpiritRadioGetAGCLowThreshold(void);
+void SpiritRadioSetClkRecMode(ClkRecMode xMode);
+ClkRecMode SpiritRadioGetClkRecMode(void);
+void SpiritRadioSetClkRecPGain(uint8_t cPGain);
+uint8_t SpiritRadioGetClkRecPGain(void);
+void SpiritRadioSetClkRecIGain(uint8_t cIGain);
+uint8_t SpiritRadioGetClkRecIGain(void);
+void SpiritRadioSetClkRecPstFltLength(PstFltLength xLength);
+PstFltLength SpiritRadioGetClkRecPstFltLength(void);
+void SpiritRadioCsBlanking(SpiritFunctionalState xNewState);
+void SpiritRadioPersistenRx(SpiritFunctionalState xNewState);
+uint32_t SpiritRadioGetXtalFrequency(void);
+void SpiritRadioSetXtalFrequency(uint32_t lXtalFrequency);
+void SpiritRadioSetRefDiv(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritRadioGetRefDiv(void);
+void SpiritRadioSetDigDiv(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritRadioGetDigDiv(void);
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Regs.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Regs.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3244 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Regs.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   This file contains all the SPIRIT registers address and masks.
+ * @details
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT1_REGS_H
+#define __SPIRIT1_REGS_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ * @addtogroup SPIRIT_Registers         SPIRIT Registers
+ * @brief Header file containing all the SPIRIT registers address and masks.
+ * @details See the file <i>@ref SPIRIT_Regs.h</i> for more details.
+ * @{
+ */
+
+/** @defgroup General_Configuration_Registers
+  * @{
+  */
+
+/** @defgroup ANA_FUNC_CONF_1_Register
+  * @{
+  */
+
+/**
+ *  \brief ANA_FUNC_CONF register 1
+ *  \code
+ *   Read Write
+ *   Default value: 0x0C
+ *   7:5 NUM_EN_PIPES: Number of enabled pipes (starting from Data Pipe 0).
+ *   4:2 GM_CONF[2:0]: Sets the driver gm of the XO at start-up:
+ *       GM_CONF2 | GM_CONF1 | GM_CONF0 | GM [mS]
+ *       ------------------------------------------
+ *           0    |    0     |     0    |  13.2
+ *           0    |    0     |     1    |  18.2
+ *           0    |    1     |     0    |  21.5
+ *           0    |    1     |     1    |  25.6
+ *           1    |    0     |     0    |  28.8
+ *           1    |    0     |     1    |  33.9
+ *           1    |    1     |     0    |  38.5
+ *           1    |    1     |     1    |  43.0
+ *   1:0 SET_BLD_LVL[1:0]: Sets the Battery Level Detector threshold:
+ *       SET_BLD_LVL1 | SET_BLD_LVL0 | Threshold [V]
+ *       ------------------------------------------
+ *             0      |      0       |     2.7
+ *             0      |      1       |     2.5
+ *             1      |      0       |     2.3
+ *             1      |      1       |     2.1
+ *   \endcode
+ */
+
+#define ANA_FUNC_CONF1_BASE					((uint8_t)0x00) /*!< ANA_FUNC_CONF1 Address (R/W) */
+
+#define ANA_FUNC_CONF1_NUM_PIPES_MASK                           ((uint8_t)0xE0) /*!< Mask for number of enabled pipes*/
+
+#define ANA_FUNC_CONF1_GMCONF_MASK		        	((uint8_t)0x1C) /*!< Mask of the GmConf field of ANA_FUNC_CONF1 register (R/W) */
+
+#define GM_13_2				                        ((uint8_t)0x00) /*!< Transconducatance Gm at start-up 13.2 mS */
+#define GM_18_2				                        ((uint8_t)0x04) /*!< Transconducatance Gm at start-up 18.2 mS */
+#define GM_21_5				                        ((uint8_t)0x08) /*!< Transconducatance Gm at start-up 21.5 mS */
+#define GM_25_6				                        ((uint8_t)0x0C) /*!< Transconducatance Gm at start-up 25.6 mS */
+#define GM_28_8				                        ((uint8_t)0x10) /*!< Transconducatance Gm at start-up 28.8 mS */
+#define GM_33_9				                        ((uint8_t)0x14) /*!< Transconducatance Gm at start-up 33.9 mS */
+#define GM_38_5				                        ((uint8_t)0x18) /*!< Transconducatance Gm at start-up 38.5 mS */
+#define GM_43_0				                        ((uint8_t)0x1C) /*!< Transconducatance Gm at start-up 43.0 mS */
+
+#define ANA_FUNC_CONF1_SET_BLD_LVL_MASK		        	((uint8_t)0x03) /*!< Mask of the SET_BLD_LV field of ANA_FUNC_CONF1 register (R/W) */
+
+#define BLD_LVL_2_7				                ((uint8_t)0x00) /*!< Sets the Battery Level Detector threshold to 2.7V */
+#define BLD_LVL_2_5				                ((uint8_t)0x01) /*!< Sets the Battery Level Detector threshold to 2.5V */
+#define BLD_LVL_2_3				                ((uint8_t)0x02) /*!< Sets the Battery Level Detector threshold to 2.3V */
+#define BLD_LVL_2_1				                ((uint8_t)0x03) /*!< Sets the Battery Level Detector threshold to 2.1V */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup ANA_FUNC_CONF_0_Register
+ * @{
+ */
+
+/**
+ *  \brief ANA_FUNC_CONF register 0
+ *  \code
+ *   Read Write
+ *   Default value: 0xC0
+ *   7 Reserved.
+ *   6 24_26_MHz_SELECT: 1 - 26 MHz configuration
+ *                       0 - 24 MHz configuration
+ *   5 AES_ON:           1 - AES engine enabled
+ *                       0 - AES engine disabled
+ *   4 EXT_REF:          1 - Reference signal from XIN pin
+ *                       0 - Reference signal from XO circuit
+ *   3 HIGH_POWER_MODE:  1 - SET_SMPS_LEVEL word will be set to the value to
+ *                           PM_TEST register in RX state, while in TX state it
+ *                           will be fixed to 111 (which programs the SMPS output
+ *                           at max value 1.8V)
+ *                       0 - SET_SMPS_LEVEL word will hold the value written in the
+ *                           PM_TEST register both in RX and TX state
+ *   2 BROWN_OUT:        1 - Brown_Out Detection enabled
+ *                       0 - Brown_Out Detection disabled
+ *   1 BATTERY_LEVEL:    1 - Battery level detector enabled
+ *                       0 - Battery level detector disabled
+ *   0 TS:               1 - Enable the "Temperature Sensor" function
+ *                       0 - Disable the "Temperature Sensor" function
+ *   \endcode
+ */
+
+
+#define ANA_FUNC_CONF0_BASE					((uint8_t)0x01) /*!< ANA_FUNC_CONF0 Address (R/W) */
+
+#define SELECT_24_26_MHZ_MASK              			((uint8_t)0x40) /*!< Configure the RCO if using 26 MHz or 24 MHz master clock/reference signal */
+#define AES_MASK                				((uint8_t)0x20) /*!< AES engine on/off */
+#define EXT_REF_MASK          				        ((uint8_t)0x10) /*!< Reference signal from XIN pin (oscillator external) or from XO circuit (oscillator internal)*/
+#define HIGH_POWER_MODE_MASK	                		((uint8_t)0x08) /*!< SET_SMPS_LEVEL word will be set to the value to PM_TEST register
+                                                                                     in RX state, while in TX state it will be fixed to 111
+                                                                                     (which programs the SMPS output at max value, 1.8V) */
+#define BROWN_OUT_MASK  			          	((uint8_t)0x04) /*!< Accurate Brown-Out detection on/off */
+#define BATTERY_LEVEL_MASK  	                		((uint8_t)0x02) /*!< Battery level detector circuit on/off */
+#define TEMPERATURE_SENSOR_MASK 	        		((uint8_t)0x01) /*!< The Temperature Sensor (available on GPIO0) on/off */
+
+/**
+ * @}
+ */
+
+/** @defgroup ANT_SELECT_CONF_Register
+ * @{
+ */
+
+/**
+ *  \brief ANT_SELECT_CONF register
+ *  \code
+ *   Read Write
+ *   Default value: 0x05
+ *
+ *   7:5   Reserved.
+ *
+ *   4   CS_BLANKING: Blank received data if signal is below the CS threshold
+ *
+ *   3   AS_ENABLE: Enable antenna switching
+ *                       1 - Enable
+ *                       0 - Disable
+ *
+ *   2:0 AS_MEAS_TIME[2:0]: Measurement time according to the formula Tmeas = 24*2^(EchFlt)*2^AS_MEAS_TIME/fxo
+ *   \endcode
+ */
+#define	ANT_SELECT_CONF_BASE					((uint8_t)0x27) /*!< Antenna diversity (works only in static carrier sense mode) */
+#define ANT_SELECT_CS_BLANKING_MASK                             ((uint8_t)0x10) /*!< CS data blanking on/off */
+#define ANT_SELECT_CONF_AS_MASK           			((uint8_t)0x08) /*!< Antenna diversity on/off */
+
+/**
+ * @}
+ */
+
+/** @defgroup DEVICE_INFO1_Register
+ * @{
+ */
+
+/**
+ *  \brief DEVICE_INFO1[7:0]  registers
+ *  \code
+ *   Default value: 0x01
+ *   Read
+ *
+ *   7:0       PARTNUM[7:0]:   Device part number
+ *   \endcode
+ */
+#define	DEVICE_INFO1_PARTNUM					((uint8_t)(0xF0)) /*!< Device part number [7:0] */
+
+/**
+ * @}
+ */
+
+/** @defgroup DEVICE_INFO0_Register
+ * @{
+ */
+
+/**
+ *  \brief DEVICE_INFO0[7:0]  registers
+ *  \code
+ *   Read
+ *
+ *   7:0       VERSION[7:0]:  Device version number
+ *   \endcode
+ */
+#define	DEVICE_INFO0_VERSION					((uint8_t)(0xF1)) /*!< Device version [7:0]; (0x55 in CUT1.0) */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup GPIO_Registers
+ * @{
+ */
+
+/** @defgroup GPIOx_CONF_Registers
+ * @{
+ */
+
+/**
+ *  \brief GPIOx registers
+ *  \code
+ *   Read Write
+ *   Default value: 0x03
+ *   7:3 GPIO_SELECT[4:0]: Specify the I/O signal.
+ *       GPIO_SELECT[4:0] |    I/O    |      Signal
+ *       ------------------------------------------------
+ *               0        |  Output   |  nIRQ
+ *               0        |  Input    |  TX command
+ *               1        |  Output   |  POR inverted
+ *               1        |  Input    |  RX command
+ *               2        |  Output   |  Wake-Up timer expiration
+ *               2        |  Input    |  TX data for direct modulation
+ *               3        |  Output   |  Low Battery Detection
+ *               3        |  Input    |  Wake-up from external input
+ *               4        |  Output   |  TX clock output
+ *               5        |  Output   |  TX state
+ *               6        |  Output   |  TX FIFO Almost Empty Flag
+ *               7        |  Output   |  TX FIFO ALmost Full Flag
+ *               8        |  Output   |  RX data output
+ *               9        |  Output   |  RX clock output
+ *               10       |  Output   |  RX state
+ *               11       |  Output   |  RX FIFO Almost Full Flag
+ *               12       |  Output   |  RX FIFO Almost Empty Flag
+ *               13       |  Output   |  Antenna switch
+ *               14       |  Output   |  Valid preamble detected
+ *               15       |  Output   |  Sync word detected
+ *               16       |  Output   |  RSSI above threshold
+ *               17       |  Output   |  MCU clock
+ *               18       |  Output   |  TX or RX mode indicator
+ *               19       |  Output   |  VDD
+ *               20       |  Output   |  GND
+ *               21       |  Output   |  External SMPS enable signal
+ *               22-31    |  Not Used |  Not Used
+ *   2 Reserved
+ *   1:0 GpioMode[1:0]: Specify the mode:
+ *        GPIO_MODE1  |  GPIO_MODE0  |               MODE
+ *       ------------------------------------------------------------
+ *             0      |      0       |    Analog (valid only for GPIO_0)
+ *             0      |      1       |    Digital Input
+ *             1      |      0       |    Digital Output Low Power
+ *             1      |      1       |    Digital Output High Power
+ *
+ *   Note: The Analog mode is used only for temperature sensor indication. This is available only
+ *         on GPIO_0 by setting the TS bit in the ANA_FUNC_CONF_0_Register.
+ *   \endcode
+ */
+
+
+#define GPIO3_CONF_BASE						((uint8_t)0x02) /*!< GPIO_3 register address */
+#define GPIO2_CONF_BASE						((uint8_t)0x03) /*!< GPIO_3 register address */
+#define GPIO1_CONF_BASE						((uint8_t)0x04) /*!< GPIO_3 register address */
+#define GPIO0_CONF_BASE						((uint8_t)0x05) /*!< GPIO_3 register address */
+
+#define CONF_GPIO_IN_TX_Command				        ((uint8_t)0x00) /*!< TX command direct from PIN (rising edge, width min=50ns) */
+#define CONF_GPIO_IN_RX_Command				        ((uint8_t)0x08) /*!< RX command direct from PIN (rising edge, width min=50ns)*/
+#define CONF_GPIO_IN_TX_Data				        ((uint8_t)0x10) /*!< TX data input for direct modulation */
+#define CONF_GPIO_IN_WKUP_Ext				        ((uint8_t)0x18) /*!< Wake up from external input */
+
+#define CONF_GPIO_OUT_nIRQ				        ((uint8_t)0x00) /*!< nIRQ (Interrupt Request, active low) , default configuration after POR */
+#define CONF_GPIO_OUT_POR_Inv				        ((uint8_t)0x08) /*!< POR inverted (active low) */
+#define CONF_GPIO_OUT_WUT_Exp				        ((uint8_t)0x10) /*!< Wake-Up Timer expiration: ‘1’ when WUT has expired */
+#define CONF_GPIO_OUT_LBD				        ((uint8_t)0x18) /*!< Low battery detection: ‘1’ when battery is below threshold setting */
+#define CONF_GPIO_OUT_TX_Data				        ((uint8_t)0x20) /*!< TX data internal clock output (TX data are sampled on the rising edge of it) */
+#define CONF_GPIO_OUT_TX_State				        ((uint8_t)0x28) /*!< TX state indication: ‘1’ when Spirit1 is transiting in the TX state */
+#define CONF_GPIO_OUT_TX_FIFO_Almost_Empty			((uint8_t)0x30) /*!< TX FIFO Almost Empty Flag */
+#define CONF_GPIO_OUT_TX_FIFO_Amost_Full			((uint8_t)0x38) /*!< TX FIFO Almost Full Flag */
+#define CONF_GPIO_OUT_RX_Data				        ((uint8_t)0x40) /*!< RX data output */
+#define CONF_GPIO_OUT_RX_Clock				        ((uint8_t)0x48) /*!< RX clock output (recovered from received data) */
+#define CONF_GPIO_OUT_RX_State				        ((uint8_t)0x50) /*!< RX state indication: ‘1’ when Spirit1 is transiting in the RX state */
+#define CONF_GPIO_OUT_RX_FIFO_Almost_Full			((uint8_t)0x58) /*!< RX FIFO Almost Full Flag */
+#define CONF_GPIO_OUT_RX_FIFO_Almost_Empty			((uint8_t)0x60) /*!< RX FIFO Almost Empty Flag */
+#define CONF_GPIO_OUT_Antenna_Switch				((uint8_t)0x68) /*!< Antenna switch used for antenna diversity */
+#define CONF_GPIO_OUT_Valid_Preamble				((uint8_t)0x70) /*!< Valid Preamble Detected Flag */
+#define CONF_GPIO_OUT_Sync_Detected				((uint8_t)0x78) /*!< Sync WordSync Word Detected Flag */
+#define CONF_GPIO_OUT_RSSI_Threshold				((uint8_t)0x80) /*!< CCA Assessment Flag */
+#define CONF_GPIO_OUT_MCU_Clock				        ((uint8_t)0x88) /*!< MCU Clock */
+#define CONF_GPIO_OUT_TX_RX_Mode				((uint8_t)0x90) /*!< TX or RX mode indicator (to enable an external range extender) */
+#define CONF_GPIO_OUT_VDD				        ((uint8_t)0x98) /*!< VDD (to emulate an additional GPIO of the MCU, programmable by SPI) */
+#define CONF_GPIO_OUT_GND				        ((uint8_t)0xA0) /*!< GND (to emulate an additional GPIO of the MCU, programmable by SPI) */
+#define CONF_GPIO_OUT_SMPS_Ext				        ((uint8_t)0xA8) /*!< External SMPS enable signal (active high) */
+
+#define CONF_GPIO_MODE_ANALOG				        ((uint8_t)0x00) /*!< Analog test BUS on GPIO; used only in test mode (except for temperature sensor) */
+#define CONF_GPIO_MODE_DIG_IN				        ((uint8_t)0x01) /*!< Digital Input on GPIO */
+#define CONF_GPIO_MODE_DIG_OUTL				        ((uint8_t)0x02) /*!< Digital Output on GPIO (low current) */
+#define CONF_GPIO_MODE_DIG_OUTH				        ((uint8_t)0x03) /*!< Digital Output on GPIO (high current) */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MCU_CK_CONF_Register
+ * @{
+ */
+
+/**
+ *  \brief MCU_CK_CONF  register
+ *  \code
+ *   Read Write
+ *   Default value: 0x00
+ *   7   Reserved.
+ *   6:5 CLOCK_TAIL[1:0]: Specifies the number of extra cylces provided before entering in STANDBY state.
+ *       CLOCK_TAIL1   |   CLOCK_TAIL0    |  Number of Extra Cycles
+ *       ------------------------------------------------------------
+ *            0        |        0         |           0
+ *            0        |        1         |           64
+ *            1        |        0         |           256
+ *            1        |        1         |           512
+ *   4:1 XO_RATIO[3:0]: Specifies the division ratio when XO oscillator is the clock source
+ *       XO_RATIO[3:0] |   Division Ratio
+ *       -----------------------------------
+ *               0     |        1
+ *               1     |       2/3
+ *               2     |       1/2
+ *               3     |       1/3
+ *               4     |       1/4
+ *               5     |       1/6
+ *               6     |       1/8
+ *               7     |       1/12
+ *               8     |       1/16
+ *               9     |       1/24
+ *               10    |       1/36
+ *               11    |       1/48
+ *               12    |       1/64
+ *               13    |       1/96
+ *               14    |       1/128
+ *               15    |       1/256
+ *   0   RCO_RATIO: Specifies the divsion ratio when RC oscillator is the clock source
+ *                0 - Division Ratio equal to 0
+ *                1 - Division Ratio equal to 1/128
+ *   \endcode
+ */
+
+
+#define MCU_CK_CONF_BASE					((uint8_t)0x06) /*!< MCU Clock Config register address */
+
+#define MCU_CK_ENABLE                                           ((uint8_t)0x80) /*!< MCU clock enable bit */
+
+#define MCU_CK_CONF_CLOCK_TAIL_0				((uint8_t)0x00) /*!< 0   extra clock cycles provided to the MCU before switching to STANDBY state */
+#define MCU_CK_CONF_CLOCK_TAIL_64				((uint8_t)0x20) /*!< 64  extra clock cycles provided to the MCU before switching to STANDBY state */
+#define MCU_CK_CONF_CLOCK_TAIL_256				((uint8_t)0x40) /*!< 256 extra clock cycles provided to the MCU before switching to STANDBY state */
+#define MCU_CK_CONF_CLOCK_TAIL_512				((uint8_t)0x60) /*!< 512 extra clock cycles provided to the MCU before switching to STANDBY state */
+#define MCU_CK_CONF_XO_RATIO_1					((uint8_t)0x00) /*!< XO Clock signal available on the GPIO divided by 1     */
+#define MCU_CK_CONF_XO_RATIO_2_3				((uint8_t)0x02) /*!< XO Clock signal available on the GPIO divided by 2/3   */
+#define MCU_CK_CONF_XO_RATIO_1_2				((uint8_t)0x04) /*!< XO Clock signal available on the GPIO divided by 1/2   */
+#define MCU_CK_CONF_XO_RATIO_1_3				((uint8_t)0x06) /*!< XO Clock signal available on the GPIO divided by 1/3   */
+#define MCU_CK_CONF_XO_RATIO_1_4				((uint8_t)0x08) /*!< XO Clock signal available on the GPIO divided by 1/4   */
+#define MCU_CK_CONF_XO_RATIO_1_6				((uint8_t)0x0A) /*!< XO Clock signal available on the GPIO divided by 1/6   */
+#define MCU_CK_CONF_XO_RATIO_1_8				((uint8_t)0x0C) /*!< XO Clock signal available on the GPIO divided by 1/8   */
+#define MCU_CK_CONF_XO_RATIO_1_12				((uint8_t)0x0E) /*!< XO Clock signal available on the GPIO divided by 1/12  */
+#define MCU_CK_CONF_XO_RATIO_1_16				((uint8_t)0x10) /*!< XO Clock signal available on the GPIO divided by 1/16  */
+#define MCU_CK_CONF_XO_RATIO_1_24				((uint8_t)0x12) /*!< XO Clock signal available on the GPIO divided by 1/24  */
+#define MCU_CK_CONF_XO_RATIO_1_36				((uint8_t)0x14) /*!< XO Clock signal available on the GPIO divided by 1/36  */
+#define MCU_CK_CONF_XO_RATIO_1_48				((uint8_t)0x16) /*!< XO Clock signal available on the GPIO divided by 1/48  */
+#define MCU_CK_CONF_XO_RATIO_1_64				((uint8_t)0x18) /*!< XO Clock signal available on the GPIO divided by 1/64  */
+#define MCU_CK_CONF_XO_RATIO_1_96				((uint8_t)0x1A) /*!< XO Clock signal available on the GPIO divided by 1/96  */
+#define MCU_CK_CONF_XO_RATIO_1_128				((uint8_t)0x1C) /*!< XO Clock signal available on the GPIO divided by 1/128 */
+#define MCU_CK_CONF_XO_RATIO_1_192				((uint8_t)0x1E) /*!< XO Clock signal available on the GPIO divided by 1/196 */
+#define MCU_CK_CONF_RCO_RATIO_1					((uint8_t)0x00) /*!< RCO Clock signal available on the GPIO divided by 1    */
+#define MCU_CK_CONF_RCO_RATIO_1_128				((uint8_t)0x01) /*!< RCO Clock signal available on the GPIO divided by 1/128*/
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Radio_Configuration_Registers
+ * @{
+ */
+
+
+
+/** @defgroup SYNT3_Register
+ * @{
+ */
+
+/**
+ *  \brief SYNT3  register
+ *  \code
+ *   Read Write
+ *   Default value: 0x0C
+ *
+ *   7:5 WCP[2:0]: Set the charge pump current according to the VCO frequency in RX mode.
+ *
+ *         VCO Frequency    |        WCP2      |       WCP1       |       WCP0        |    Charge Pump Current (uA)
+ *       ------------------------------------------------------------------------------------------------------------
+ *          4644-4678       |         0        |        0         |        0          |             378.4
+ *          4708-4772       |         0        |        0         |        1          |             368.9
+ *          4772-4836       |         0        |        1         |        0          |             359.5
+ *          4836-4902       |         0        |        1         |        1          |             350
+ *          4902-4966       |         1        |        0         |        0          |             340.5
+ *          4966-5030       |         1        |        0         |        1          |             331.1
+ *          5030-5095       |         1        |        1         |        0          |             321.6
+ *          5095-5161       |         1        |        1         |        1          |             312.2
+ *          5161-5232       |         0        |        0         |        0          |             378.4
+ *          5232-5303       |         0        |        0         |        1          |             368.9
+ *          5303-5375       |         0        |        1         |        0          |             359.5
+ *          5375-5448       |         0        |        1         |        1          |             350
+ *          5448-5519       |         1        |        0         |        0          |             340.5
+ *          5519-5592       |         1        |        0         |        1          |             331.1
+ *          5592-5663       |         1        |        1         |        0          |             321.6
+ *          5663-5736       |         1        |        1         |        1          |             312.2
+ *
+ *
+ *   4:0  SYNT[25:21]: highest 5 bits of the PLL programmable divider
+ *                     The valid range depends on fXO and REFDIV settings; for
+ *                     fXO=26MHz
+ *                     REFDIV = 0 - SYNT[25:21] = 11...13
+ *                     REFDIV = 1 - SYNT[25:21] = 22…27
+ *
+ *
+ *   \endcode
+ */
+#define	SYNT3_BASE						((uint8_t)0x08) /*!< [4:0] -> SYNT[25:21], highest 5 bits of the PLL programmable divider */
+
+#define WCP_CONF_WCP_378UA                                      ((uint8_t)0x00) /*!< Charge pump current nominal value = 378uA [VCO 4644-4708]&[VCO 5161-5232] */
+#define WCP_CONF_WCP_369UA                                      ((uint8_t)0x01) /*!< Charge pump current nominal value = 369uA [VCO 4708-4772]&[VCO 5232-5303] */
+#define WCP_CONF_WCP_359UA                                      ((uint8_t)0x02) /*!< Charge pump current nominal value = 359uA [VCO 4772-4836]&[VCO 5303-5375] */
+#define WCP_CONF_WCP_350UA                                      ((uint8_t)0x03) /*!< Charge pump current nominal value = 350uA [VCO 4836-4902]&[VCO 5375-5448] */
+#define WCP_CONF_WCP_340UA                                      ((uint8_t)0x04) /*!< Charge pump current nominal value = 340uA [VCO 4902-4966]&[VCO 5448-5519] */
+#define WCP_CONF_WCP_331UA                                      ((uint8_t)0x05) /*!< Charge pump current nominal value = 331uA [VCO 4966-5030]&[VCO 5519-5592] */
+#define WCP_CONF_WCP_321UA                                      ((uint8_t)0x06) /*!< Charge pump current nominal value = 321uA [VCO 5030-5095]&[VCO 5592-5563] */
+#define WCP_CONF_WCP_312UA                                      ((uint8_t)0x07) /*!< Charge pump current nominal value = 312uA [VCO 5095-5160]&[VCO 5563-5736] */
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup SYNT2_Register
+ * @{
+ */
+
+/**
+ *  \brief SYNT2  register
+ *  \code
+ *   Read Write
+ *   Default value: 0x84
+ *   7:0  SYNT[20:13]: intermediate bits of the PLL programmable divider.
+ *
+ *   \endcode
+ */
+
+#define	SYNT2_BASE						((uint8_t)0x09) /*!< SYNT[20:13], intermediate bits of the PLL programmable divider */
+
+/**
+ * @}
+ */
+
+/** @defgroup SYNT1_Register
+ * @{
+ */
+
+/**
+ *  \brief SYNT1  register
+ *  \code
+ *   Read Write
+ *   Default value: 0xEC
+ *   7:0  SYNT[12:5]: intermediate bits of the PLL programmable divider.
+ *
+ *   \endcode
+ */
+
+#define	SYNT1_BASE						((uint8_t)0x0A) /*!< SYNT[12:5], intermediate bits of the PLL programmable divider */
+
+/**
+ * @}
+ */
+
+/** @defgroup SYNT0_Register
+ * @{
+ */
+
+/**
+ *  \brief SYNT0  register
+ *  \code
+ *   Read Write
+ *   Default value: 0x51
+ *   7:3  SYNT[4:0]: lowest bits of the PLL programmable divider.
+ *   2:0  BS[2:0]:   Synthesizer band select. This parameter selects the out-of-loop divide factor of the synthesizer
+ *                   according to the formula fxo/(B/2)/D*SYNT/2^18
+ *
+ *              BS2        |       BS1       |       BS0        |     value of B
+ *       ---------------------------------------------------------------------------
+ *               0         |        0        |        1         |       6
+ *               0         |        1        |        0         |       8
+ *               0         |        1        |        1         |       12
+ *               1         |        0        |        0         |       16
+ *               1         |        0        |        1         |       32
+ *
+ *   \endcode
+ */
+#define	SYNT0_BASE						((uint8_t)0x0B) /*!< [7:3] -> SYNT[4:0], lowest bits of the PLL programmable divider */
+
+#define	SYNT0_BS_6						((uint8_t)0x01) /*!< Synthesizer band select (out-of-loop divide factor of the synthesizer)=6  (779-956MHz) */
+#define	SYNT0_BS_8						((uint8_t)0x02) /*!< Synthesizer band select (out-of-loop divide factor of the synthesizer)=8  (387-470MHz)*/
+#define	SYNT0_BS_12						((uint8_t)0x03) /*!< Synthesizer band select (out-of-loop divide factor of the synthesizer)=12 (387-470MHz)*/
+#define	SYNT0_BS_16						((uint8_t)0x04) /*!< Synthesizer band select (out-of-loop divide factor of the synthesizer)=16 (300-348MHz)*/
+#define	SYNT0_BS_32						((uint8_t)0x05) /*!< Synthesizer band select (out-of-loop divide factor of the synthesizer)=32 (150-174MHz)*/
+
+/**
+ * @}
+ */
+
+/** @defgroup CHSPACE_Register
+ * @{
+ */
+
+/**
+ *  \brief CHSPACE  register
+ *  \code
+ *   Read Write
+ *   Default value: 0xFC
+ *   7:0  CH_SPACING[7:0]: Channel spacing. From ~793Hz to ~200KHz in 793Hz steps
+ *                         (in general, frequency step is fXO/215=26MHz/215~793Hz).
+ *
+ *   \endcode
+ */
+
+#define	CHSPACE_BASE						((uint8_t)0x0C) /*!< Channel spacing. From ~0.8KHz to ~200KHz in (fXO/2^15)Hz (793Hz for 26MHz XO) steps */
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup IF_OFFSET_DIG_Register
+ * @{
+ */
+
+/**
+ *  \brief IF_OFFSET_DIG  register
+ *  \code
+ *   Read Write
+ *   Default value: 0xA3
+ *   7:0  IF_OFFSET_DIG[7:0]: Intermediate frequency setting for the digital shift-to-baseband circuits. According to the formula: fIF=fXO*(IF_OFFSET_ANA+64)/(12*2^10)=fCLK*(IF_OFFSET_DIG+64)/(12*2^10) Hz.
+ *
+ *   \endcode
+ */
+#define	IF_OFFSET_DIG_BASE						((uint8_t)0x0D) /*!< Intermediate frequency fIF=fXO*(IF_OFFSET_ANA+64)/(12*2^10)=fCLK*(IF_OFFSET_DIG+64)/(12*2^10) Hz */
+
+/**
+ * @}
+ */
+
+/** @defgroup IF_OFFSET_ANA_Register
+ * @{
+ */
+
+/**
+ *  \brief IF_OFFSET_ANA  register
+ *  \code
+ *   Read Write
+ *   Default value: 0xA3
+ *   7:0  IF_OFFSET_ANA[7:0]: Intermediate frequency setting for the digital shift-to-baseband circuits. According to the formula: fIF=fXO*(IF_OFFSET_ANA+64)/(12*2^10)=fCLK*(IF_OFFSET_DIG+64)/(12*2^10) Hz.
+ *
+ *   \endcode
+ */
+#define	IF_OFFSET_ANA_BASE						((uint8_t)0x07) /*!< Intermediate frequency fIF=fXO*(IF_OFFSET_ANA+64)/(12*2^10)=fCLK*(IF_OFFSET_DIG+64)/(12*2^10) Hz */
+
+
+/**
+ * @}
+ */
+
+/** @defgroup FC_OFFSET1_Register
+ * @{
+ */
+
+/**
+ *  \brief FC_OFFSET1  registers
+ *  \code
+ *   Read Write
+ *   Default value: 0xA3
+ *   7:4  Reserved.
+ *   3:0  FC_OFFSET[11:8]: Carrier offset. This value is the higher part of a 12-bit 2’s complement integer
+ *                         representing an offset in 99Hz(2) units added/subtracted to the
+ *                         carrier frequency set by registers SYNT3…SYNT0.
+ *                         This register can be used to set a fixed correction value
+ *                         obtained e.g. from crystal measurements.
+ *
+ *   \endcode
+ */
+#define	FC_OFFSET1_BASE						((uint8_t)0x0E) /*!< [3:0] -> [11:8] Carrier offset (upper part) */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup FC_OFFSET0_Register
+ * @{
+ */
+
+/**
+ *  \brief FC_OFFSET0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0  FC_OFFSET[7:0]: Carrier offset. This value is the lower part of a 12-bit 2’s complement integer
+ *                         representing an offset in 99Hz(2) units added/subtracted to the
+ *                         carrier frequency set by registers SYNT3…SYNT0.
+ *                         This register can be used to set a fixed correction value
+ *                         obtained e.g. from crystal measurements.
+ *
+ *   \endcode
+ */
+#define	FC_OFFSET0_BASE						((uint8_t)0x0F) /*!< [7:0] -> [7:0] Carrier offset (lower part). This value is a 12-bit 2’s complement integer
+																	representing an offset in fXO/2^18 (99Hz for 26 MHz XO) units added/subtracted to the carrier frequency
+															set by registers SYNT3…SYNT0. Range is +/-200kHz with 26 MHz XO */
+/**
+ * @}
+ */
+
+
+/** @defgroup PA_LEVEL_x_Registers
+ * @{
+ */
+
+/**
+ *  \brief PA_POWER_x[8:1]  registers
+ *  \code
+ *   Default values from 8 to 1: [0x03, 0x0E, 0x1A, 0x25, 0x35, 0x40, 0x4E, 0x00]
+ *   Read Write
+ *
+ *   7    Reserved.
+ *   6:0  PA_LEVEL_(x-1)[6:0]: Output power level for x-th slot.
+ *   \endcode
+ */
+
+#define	PA_POWER8_BASE						((uint8_t)0x10) /*!< PA Power level for 8th slot of PA ramping or ASK modulation */
+#define	PA_POWER7_BASE						((uint8_t)0x11) /*!< PA Power level for 7th slot of PA ramping or ASK modulation */
+#define	PA_POWER6_BASE						((uint8_t)0x12) /*!< PA Power level for 6th slot of PA ramping or ASK modulation */
+#define	PA_POWER5_BASE						((uint8_t)0x13) /*!< PA Power level for 5th slot of PA ramping or ASK modulation */
+#define	PA_POWER4_BASE						((uint8_t)0x14) /*!< PA Power level for 4th slot of PA ramping or ASK modulation */
+#define	PA_POWER3_BASE						((uint8_t)0x15) /*!< PA Power level for 3rd slot of PA ramping or ASK modulation */
+#define	PA_POWER2_BASE						((uint8_t)0x16) /*!< PA Power level for 2nd slot of PA ramping or ASK modulation */
+#define	PA_POWER1_BASE						((uint8_t)0x17) /*!< PA Power level for 1st slot of PA ramping or ASK modulation */
+
+/**
+ * @}
+ */
+
+/** @defgroup PA_POWER_CONF_Registers
+ * @{
+ */
+
+/**
+ *  \brief PA_POWER_CONF_Registers
+ *  \code
+ *   Default value:0x07
+ *   Read Write
+ *
+ *   7:6  CWC[1:0]: Output stage additional load capacitors bank (to be used to
+ *                      optimize the PA for different sub-bands).
+ *
+ *         CWC1       |        CWC0      |     Total capacity in pF
+ *       ---------------------------------------------------------
+ *          0         |         0        |        0
+ *          0         |         1        |        1.2
+ *          1         |         0        |        2.4
+ *          1         |         1        |        3.6
+ *
+ *   5   PA_RAMP_ENABLE:
+ *                       1 - Enable the power ramping
+ *                       0 - Disable the power ramping
+ *   4:3 PA_RAMP_STEP_WIDTH[1:0]: Step width in bit period
+ *
+ *         PA_RAMP_STEP_WIDTH1       |        PA_RAMP_STEP_WIDTH0       |     PA ramping time step
+ *       -------------------------------------------------------------------------------------------
+ *                 0                 |                0                 |        1/8 Bit period
+ *                 0                 |                1                 |        2/8 Bit period
+ *                 1                 |                0                 |        3/8 Bit period
+ *                 1                 |                1                 |        4/8 Bit period
+ *
+ *   2:0 PA_LEVEL_MAX_INDEX[2:0]: Fixes the MAX PA LEVEL in PA ramping or ASK modulation
+ *
+ *   \endcode
+ */
+#define	PA_POWER0_BASE						((uint8_t)0x18) /*!< PA ramping settings and additional load capacitor banks used
+																	for PA optimization in different sub bands*/
+#define PA_POWER0_CWC_MASK                                      ((uint8_t)0x20) /*!< Output stage additional load capacitors bank */
+#define PA_POWER0_CWC_0						((uint8_t)0x00) /*!< No additional PA load capacitor */
+#define PA_POWER0_CWC_1_2P					((uint8_t)0x40) /*!< 1.2pF additional PA load capacitor */
+#define PA_POWER0_CWC_2_4P					((uint8_t)0x80) /*!< 2.4pF additional PA load capacitor */
+#define PA_POWER0_CWC_3_6P					((uint8_t)0xC0) /*!< 3.6pF additional PA load capacitor */
+#define PA_POWER0_PA_RAMP_MASK  				((uint8_t)0x20) /*!< The PA power ramping */
+#define PA_POWER0_PA_RAMP_STEP_WIDTH_MASK                       ((uint8_t)0x20) /*!< The step width */
+#define PA_POWER0_PA_RAMP_STEP_WIDTH_TB_8			((uint8_t)0x00) /*!< PA ramping time step = 1/8 Bit period*/
+#define PA_POWER0_PA_RAMP_STEP_WIDTH_TB_4			((uint8_t)0x08) /*!< PA ramping time step = 2/8 Bit period*/
+#define PA_POWER0_PA_RAMP_STEP_WIDTH_3TB_8			((uint8_t)0x10) /*!< PA ramping time step = 3/8 Bit period*/
+#define PA_POWER0_PA_RAMP_STEP_WIDTH_TB_2			((uint8_t)0x18) /*!< PA ramping time step = 4/8 Bit period*/
+#define PA_POWER0_PA_LEVEL_MAX_INDEX                            ((uint8_t)0x20) /*!< Final level for power ramping */
+#define PA_POWER0_PA_LEVEL_MAX_INDEX_0				((uint8_t)0x00) /*!<                                                           */
+#define PA_POWER0_PA_LEVEL_MAX_INDEX_1				((uint8_t)0x01) /*!<  Fixes the MAX PA LEVEL in PA ramping or ASK modulation   */
+#define PA_POWER0_PA_LEVEL_MAX_INDEX_2				((uint8_t)0x02) /*!<                                                           */
+#define PA_POWER0_PA_LEVEL_MAX_INDEX_3				((uint8_t)0x03) /*!<                     _________                             */
+#define PA_POWER0_PA_LEVEL_MAX_INDEX_4				((uint8_t)0x04) /*!<     PA_LVL2       _|                 <--|                 */
+#define PA_POWER0_PA_LEVEL_MAX_INDEX_5				((uint8_t)0x05) /*!<                 _|                      |                 */
+#define PA_POWER0_PA_LEVEL_MAX_INDEX_6				((uint8_t)0x06) /*!<     PA_LVL1   _|                        |                 */
+#define PA_POWER0_PA_LEVEL_MAX_INDEX_7				((uint8_t)0x07) /*!<     PA_LVL0 _|                 MAX_INDEX-                 */
+
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MOD1_Register
+ * @{
+ */
+
+/**
+ *  \brief MOD1 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x83
+ *   7:0  DATARATE_M[7:0]: The Mantissa of the specified data rate
+ *
+ *   \endcode
+ */
+#define	MOD1_BASE					        ((uint8_t)0x1A) /*!< The Mantissa of the specified data rate */
+
+/**
+ * @}
+ */
+
+/** @defgroup MOD0_Register
+ * @{
+ */
+
+/**
+ *  \brief MOD0 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x1A
+ *   7  CW:              1 - CW Mode enabled - enables the generation of a continous wave carrier without any modulation
+ *                       0 - CW Mode disabled
+ *
+ *   6 BT_SEL:  Select BT value for GFSK
+ *                       1 - BT=0.5
+ *                       0 - BT=1
+ *
+ *   5:4 MOD_TYPE[1:0]: Modulation type
+ *
+ *
+ *         MOD_TYPE1       |        MOD_TYPE0      |     Modulation
+ *       ---------------------------------------------------------
+ *             0           |           0           |        2-FSK,MSK
+ *             0           |           1           |        GFSK,GMSK
+ *             1           |           0           |        ASK/OOK
+ *
+ *   3:0  DATARATE_E[3:0]: The Exponent of the specified data rate
+ *
+ *   \endcode
+ */
+#define	MOD0_BASE						((uint8_t)0x1B) /*!< Modulation Settings, Exponent of the specified data rate, CW mode*/
+
+#define MOD0_MOD_TYPE_2_FSK					((uint8_t)0x00) /*!< Modulation type 2-FSK (MSK if the frequency deviation is identical to a quarter of the data rate) */
+#define MOD0_MOD_TYPE_GFSK					((uint8_t)0x10) /*!< Modulation type GFSK (GMSK if the frequency deviation is identical to a quarter of the data rate) */
+#define MOD0_MOD_TYPE_ASK					((uint8_t)0x20) /*!< Modulation type ASK (OOK the PA is switched off for symbol "0") */
+#define MOD0_MOD_TYPE_MSK					((uint8_t)0x00) /*!< Modulation type MSK (the frequency deviation must be identical to a quarter of the data rate) */
+#define MOD0_MOD_TYPE_GMSK					((uint8_t)0x10) /*!< Modulation type GMSK (the frequency deviation must be identical to a quarter of the data rate) */
+#define MOD0_BT_SEL_BT_MASK       				((uint8_t)0x00) /*!< Select the BT = 1 or BT = 0.5 valid only for GFSK or GMSK modulation*/
+#define MOD0_CW							((uint8_t)0x80) /*!< Set the Continous Wave (no modulation) transmit mode */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup FDEV0_Register
+ * @{
+ */
+
+/**
+ *  \brief FDEV0 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x45
+ *   7:4  FDEV_E[3:0]:       Exponent of the frequency deviation (allowed values from 0 to 9)
+ *
+ *   3 CLOCK_REC_ALGO_SEL:  Select PLL or DLL mode for clock recovery
+ *                       1 - DLL mode
+ *                       0 - PLL mode
+ *
+ *   2:0 FDEV_M[1:0]: Mantissa of the frequency deviation (allowed values from 0 to 7)
+ *
+ *
+ *   \endcode
+ */
+#define	FDEV0_BASE						((uint8_t)0x1C) /*!< Sets the Mantissa and exponent of frequency deviation (frequency separation/2)
+																and PLL or DLL alogrithm from clock recovery in RX digital demod*/
+#define FDEV0_CLOCK_REG_ALGO_SEL_MASK			        ((uint8_t)0x08) /*!< Can be DLL or PLL algorithm for clock recovery in RX digital demod (see CLOCKREC reg) */
+#define FDEV0_CLOCK_REG_ALGO_SEL_PLL				((uint8_t)0x00) /*!< Sets PLL alogrithm for clock recovery in RX digital demod (see CLOCKREC reg) */
+#define FDEV0_CLOCK_REG_ALGO_SEL_DLL				((uint8_t)0x08) /*!< Sets DLL alogrithm for clock recovery in RX digital demod (see CLOCKREC reg) */
+   
+/**
+ * @}
+ */
+
+/** @defgroup CHFLT_Register
+ * @{
+ */
+
+/**
+ *  \brief CHFLT register
+ *  \code
+ *   Read Write
+ *   Default value: 0x23
+ *   7:4  CHFLT_M[3:0]:       Mantissa of the channel filter BW (allowed values from 0 to 8)
+ *
+ *   3:0  CHFLT_E[3:0]:       Exponent of the channel filter BW (allowed values from 0 to 9)
+ *
+ *         M\E |   0   |   1   |   2   |   3   |   4  |   5  |  6   |   7 |  8  |  9  |
+ *        -----+-------+-------+-------+-------+------+------+------+-----+-----+-----+
+ *         0   | 800.1 | 450.9 | 224.7 | 112.3 | 56.1 | 28.0 | 14.0 | 7.0 | 3.5 | 1.8 |
+ *         1   | 795.1 | 425.9 | 212.4 | 106.2 | 53.0 | 26.5 | 13.3 | 6.6 | 3.3 | 1.7 |
+ *         2   | 768.4 | 403.2 | 201.1 | 100.5 | 50.2 | 25.1 | 12.6 | 6.3 | 3.1 | 1.6 |
+ *         3   | 736.8 | 380.8 | 190.0 | 95.0  | 47.4 | 23.7 | 11.9 | 5.9 | 3.0 | 1.5 |
+ *         4   | 705.1 | 362.1 | 180.7 | 90.3  | 45.1 | 22.6 | 11.3 | 5.6 | 2.8 | 1.4 |
+ *         5   | 670.9 | 341.7 | 170.6 | 85.3  | 42.6 | 21.3 | 10.6 | 5.3 | 2.7 | 1.3 |
+ *         6   | 642.3 | 325.4 | 162.4 | 81.2  | 40.6 | 20.3 | 10.1 | 5.1 | 2.5 | 1.3 |
+ *         7   | 586.7 | 294.5 | 147.1 | 73.5  | 36.7 | 18.4 | 9.2  | 4.6 | 2.3 | 1.2 |
+ *         8   | 541.4 | 270.3 | 135.0 | 67.5  | 33.7 | 16.9 | 8.4  | 4.2 | 2.1 | 1.1 |
+ *
+ *   \endcode
+ */
+#define	CHFLT_BASE						((uint8_t)0x1D) /*!< RX Channel Filter Bandwidth */
+
+#define CHFLT_800_1						((uint8_t)0x00) /*!< RX Channel Filter Bandwidth = 800.1 kHz */
+#define CHFLT_795_1						((uint8_t)0x10) /*!< RX Channel Filter Bandwidth = 795.1 kHz */
+#define CHFLT_768_4						((uint8_t)0x20) /*!< RX Channel Filter Bandwidth = 768.4 kHz */
+#define CHFLT_736_8						((uint8_t)0x30) /*!< RX Channel Filter Bandwidth = 736.8 kHz */
+#define CHFLT_705_1						((uint8_t)0x40) /*!< RX Channel Filter Bandwidth = 705.1 kHz */
+#define CHFLT_670_9						((uint8_t)0x50) /*!< RX Channel Filter Bandwidth = 670.9 kHz */
+#define CHFLT_642_3						((uint8_t)0x60) /*!< RX Channel Filter Bandwidth = 642.3 kHz */
+#define CHFLT_586_7						((uint8_t)0x70) /*!< RX Channel Filter Bandwidth = 586.7 kHz */
+#define CHFLT_541_4						((uint8_t)0x80) /*!< RX Channel Filter Bandwidth = 541.4 kHz */
+#define CHFLT_450_9						((uint8_t)0x01) /*!< RX Channel Filter Bandwidth = 450.9 kHz */
+#define CHFLT_425_9						((uint8_t)0x11) /*!< RX Channel Filter Bandwidth = 425.9 kHz */
+#define CHFLT_403_2						((uint8_t)0x21) /*!< RX Channel Filter Bandwidth = 403.2 kHz */
+#define CHFLT_380_8						((uint8_t)0x31) /*!< RX Channel Filter Bandwidth = 380.8 kHz */
+#define CHFLT_362_1						((uint8_t)0x41) /*!< RX Channel Filter Bandwidth = 362.1 kHz */
+#define CHFLT_341_7						((uint8_t)0x51) /*!< RX Channel Filter Bandwidth = 341.7 kHz */
+#define CHFLT_325_4						((uint8_t)0x61) /*!< RX Channel Filter Bandwidth = 325.4 kHz */
+#define CHFLT_294_5						((uint8_t)0x71) /*!< RX Channel Filter Bandwidth = 294.5 kHz */
+#define CHFLT_270_3						((uint8_t)0x81) /*!< RX Channel Filter Bandwidth = 270.3 kHz */
+#define CHFLT_224_7						((uint8_t)0x02) /*!< RX Channel Filter Bandwidth = 224.7 kHz */
+#define CHFLT_212_4						((uint8_t)0x12) /*!< RX Channel Filter Bandwidth = 212.4 kHz */
+#define CHFLT_201_1						((uint8_t)0x22) /*!< RX Channel Filter Bandwidth = 201.1 kHz */
+#define CHFLT_190						((uint8_t)0x32) /*!< RX Channel Filter Bandwidth = 190.0 kHz */
+#define CHFLT_180_7						((uint8_t)0x42) /*!< RX Channel Filter Bandwidth = 180.7 kHz */
+#define CHFLT_170_6						((uint8_t)0x52) /*!< RX Channel Filter Bandwidth = 170.6 kHz */
+#define CHFLT_162_4						((uint8_t)0x62) /*!< RX Channel Filter Bandwidth = 162.4 kHz */
+#define CHFLT_147_1						((uint8_t)0x72) /*!< RX Channel Filter Bandwidth = 147.1 kHz */
+#define CHFLT_135						((uint8_t)0x82) /*!< RX Channel Filter Bandwidth = 135.0 kHz */
+#define CHFLT_112_3						((uint8_t)0x03) /*!< RX Channel Filter Bandwidth = 112.3 kHz */
+#define CHFLT_106_2						((uint8_t)0x13) /*!< RX Channel Filter Bandwidth = 106.2 kHz */
+#define CHFLT_100_5						((uint8_t)0x23) /*!< RX Channel Filter Bandwidth = 100.5 kHz */
+#define CHFLT_95						((uint8_t)0x33) /*!< RX Channel Filter Bandwidth = 95.0 kHz */
+#define CHFLT_90_3						((uint8_t)0x43) /*!< RX Channel Filter Bandwidth = 90.3 kHz */
+#define CHFLT_85_3						((uint8_t)0x53) /*!< RX Channel Filter Bandwidth = 85.3 kHz */
+#define CHFLT_81_2						((uint8_t)0x63) /*!< RX Channel Filter Bandwidth = 81.2 kHz */
+#define CHFLT_73_5						((uint8_t)0x73) /*!< RX Channel Filter Bandwidth = 73.5 kHz */
+#define CHFLT_67_5						((uint8_t)0x83) /*!< RX Channel Filter Bandwidth = 67.5 kHz */
+#define CHFLT_56_1						((uint8_t)0x04) /*!< RX Channel Filter Bandwidth = 56.1 kHz */
+#define CHFLT_53						((uint8_t)0x14) /*!< RX Channel Filter Bandwidth = 53.0 kHz */
+#define CHFLT_50_2						((uint8_t)0x24) /*!< RX Channel Filter Bandwidth = 50.2 kHz */
+#define CHFLT_47_4						((uint8_t)0x34) /*!< RX Channel Filter Bandwidth = 47.4 kHz */
+#define CHFLT_45_1						((uint8_t)0x44) /*!< RX Channel Filter Bandwidth = 45.1 kHz */
+#define CHFLT_42_6						((uint8_t)0x54) /*!< RX Channel Filter Bandwidth = 42.6 kHz */
+#define CHFLT_40_6						((uint8_t)0x64) /*!< RX Channel Filter Bandwidth = 40.6 kHz */
+#define CHFLT_36_7						((uint8_t)0x74) /*!< RX Channel Filter Bandwidth = 36.7 kHz */
+#define CHFLT_33_7						((uint8_t)0x84) /*!< RX Channel Filter Bandwidth = 33.7 kHz */
+#define CHFLT_28						((uint8_t)0x05) /*!< RX Channel Filter Bandwidth = 28.0 kHz */
+#define CHFLT_26_5						((uint8_t)0x15) /*!< RX Channel Filter Bandwidth = 26.5 kHz */
+#define CHFLT_25_1						((uint8_t)0x25) /*!< RX Channel Filter Bandwidth = 25.1 kHz */
+#define CHFLT_23_7						((uint8_t)0x35) /*!< RX Channel Filter Bandwidth = 23.7 kHz */
+#define CHFLT_22_6						((uint8_t)0x45) /*!< RX Channel Filter Bandwidth = 22.6 kHz */
+#define CHFLT_21_3						((uint8_t)0x55) /*!< RX Channel Filter Bandwidth = 21.3 kHz */
+#define CHFLT_20_3						((uint8_t)0x65) /*!< RX Channel Filter Bandwidth = 20.3 kHz */
+#define CHFLT_18_4						((uint8_t)0x75) /*!< RX Channel Filter Bandwidth = 18.4 kHz */
+#define CHFLT_16_9						((uint8_t)0x85) /*!< RX Channel Filter Bandwidth = 16.9 kHz */
+#define CHFLT_14						((uint8_t)0x06) /*!< RX Channel Filter Bandwidth = 14.0 kHz */
+#define CHFLT_13_3						((uint8_t)0x16) /*!< RX Channel Filter Bandwidth = 13.3 kHz */
+#define CHFLT_12_6						((uint8_t)0x26) /*!< RX Channel Filter Bandwidth = 12.6 kHz */
+#define CHFLT_11_9						((uint8_t)0x36) /*!< RX Channel Filter Bandwidth = 11.9 kHz */
+#define CHFLT_11_3						((uint8_t)0x46) /*!< RX Channel Filter Bandwidth = 11.3 kHz */
+#define CHFLT_10_6						((uint8_t)0x56) /*!< RX Channel Filter Bandwidth = 10.6 kHz */
+#define CHFLT_10_1						((uint8_t)0x66) /*!< RX Channel Filter Bandwidth = 10.1 kHz */
+#define CHFLT_9_2						((uint8_t)0x76) /*!< RX Channel Filter Bandwidth = 9.2 kHz */
+#define CHFLT_8_4						((uint8_t)0x86) /*!< RX Channel Filter Bandwidth = 8.4 kHz */
+#define CHFLT_7							((uint8_t)0x07) /*!< RX Channel Filter Bandwidth = 7.0 kHz */
+#define CHFLT_6_6						((uint8_t)0x17) /*!< RX Channel Filter Bandwidth = 6.6 kHz */
+#define CHFLT_6_3						((uint8_t)0x27) /*!< RX Channel Filter Bandwidth = 6.3 kHz */
+#define CHFLT_5_9						((uint8_t)0x37) /*!< RX Channel Filter Bandwidth = 5.9 kHz */
+#define CHFLT_5_6						((uint8_t)0x47) /*!< RX Channel Filter Bandwidth = 5.6 kHz */
+#define CHFLT_5_3						((uint8_t)0x57) /*!< RX Channel Filter Bandwidth = 5.3 kHz */
+#define CHFLT_5_1						((uint8_t)0x67) /*!< RX Channel Filter Bandwidth = 5.1 kHz */
+#define CHFLT_4_6						((uint8_t)0x77) /*!< RX Channel Filter Bandwidth = 4.6 kHz */
+#define CHFLT_4_2						((uint8_t)0x87) /*!< RX Channel Filter Bandwidth = 4.2 kHz */
+#define CHFLT_3_5						((uint8_t)0x08) /*!< RX Channel Filter Bandwidth = 3.5 kHz */
+#define CHFLT_3_3						((uint8_t)0x18) /*!< RX Channel Filter Bandwidth = 3.3 kHz */
+#define CHFLT_3_1						((uint8_t)0x28) /*!< RX Channel Filter Bandwidth = 3.1 kHz */
+#define CHFLT_3							((uint8_t)0x38) /*!< RX Channel Filter Bandwidth = 3.0 kHz */
+#define CHFLT_2_8						((uint8_t)0x48) /*!< RX Channel Filter Bandwidth = 2.8 kHz */
+#define CHFLT_2_7						((uint8_t)0x58) /*!< RX Channel Filter Bandwidth = 2.7 kHz */
+#define CHFLT_2_5						((uint8_t)0x68) /*!< RX Channel Filter Bandwidth = 2.5 kHz */
+#define CHFLT_2_3						((uint8_t)0x78) /*!< RX Channel Filter Bandwidth = 2.3 kHz */
+#define CHFLT_2_1						((uint8_t)0x88) /*!< RX Channel Filter Bandwidth = 2.1 kHz */
+#define CHFLT_1_8						((uint8_t)0x09) /*!< RX Channel Filter Bandwidth = 1.8 kHz */
+#define CHFLT_1_7						((uint8_t)0x19) /*!< RX Channel Filter Bandwidth = 1.7 kHz */
+#define CHFLT_1_6						((uint8_t)0x29) /*!< RX Channel Filter Bandwidth = 1.6 kHz */
+#define CHFLT_1_5						((uint8_t)0x39) /*!< RX Channel Filter Bandwidth = 1.5 kHz */
+#define CHFLT_1_4						((uint8_t)0x49) /*!< RX Channel Filter Bandwidth = 1.4 kHz */
+#define CHFLT_1_3a						((uint8_t)0x59) /*!< RX Channel Filter Bandwidth = 1.3 kHz */
+#define CHFLT_1_3						((uint8_t)0x69) /*!< RX Channel Filter Bandwidth = 1.3 kHz */
+#define CHFLT_1_2						((uint8_t)0x79) /*!< RX Channel Filter Bandwidth = 1.2 kHz */
+#define CHFLT_1_1						((uint8_t)0x89) /*!< RX Channel Filter Bandwidth = 1.1 kHz */
+
+/**
+ * @}
+ */
+
+/** @defgroup AFC2_Register
+ * @{
+ */
+
+/**
+ *  \brief AFC2 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x48
+ *   7  AFC Freeze on Sync: Freeze AFC correction upon sync word detection.
+ *                       1 - AFC Freeze enabled
+ *                       0 - AFC Freeze disabled
+ *
+ *   6  AFC Enabled:  Enable AFC
+ *                       1 - AFC enabled
+ *                       0 - AFC disabled
+ *
+ *   5  AFC Mode:    Select AFC mode
+ *                       1 - AFC Loop closed on 2nd conversion stage.
+ *                       0 - AFC Loop closed on slicer
+ *
+ *   4:0  AFC PD leakage[4:0]: Peak detector leakage. This parameter sets the decay speed of the min/max frequency peak detector (AFC2 register),
+ *                             the range allowed is 0..31 (0 - no leakage, 31 - high leakage). The recommended value for this parameter is 4.
+ *
+ *   \endcode
+ */
+#define	AFC2_BASE						((uint8_t)0x1E) /*!< Automatic frequency compensation algorithm parameters (FSK/GFSK/MSK)*/
+
+#define AFC2_AFC_FREEZE_ON_SYNC_MASK				((uint8_t)0x80) /*!< The frequency correction value is frozen when SYNC word is detected */
+#define AFC2_AFC_MASK			        		((uint8_t)0x40) /*!< Mask of Automatic Frequency Correction */
+#define AFC2_AFC_MODE_MASK					((uint8_t)0x20) /*!< Automatic Frequency Correction can be in Main MODE or Auxiliary MODE*/
+#define AFC2_AFC_MODE_SLICER					((uint8_t)0x00) /*!< Automatic Frequency Correction Main MODE */
+#define AFC2_AFC_MODE_MIXER					((uint8_t)0x20) /*!< Automatic Frequency Correction Auxiliary MODE */
+   
+/**
+ * @}
+ */
+
+/** @defgroup AFC1_Register
+ * @{
+ */
+
+/**
+ *  \brief AFC1 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x18
+ *   7:0  AFC_FAST_PERIOD: Length of the AFC fast period. this parameter sets the length of the fast period in number of samples (AFC1 register), the range allowed
+ *                         is 0..255. The recommended setting for this parameter is such that the fast period equals the preamble length. Since the
+ *                         algorithm operates typically on 2 samples per symbol, the programmed value should be twice the number of preamble
+ *                         symbols.
+ *
+ *   \endcode
+ */
+#define	AFC1_BASE						((uint8_t)0x1F) /*!< Length of the AFC fast period */
+
+/**
+ * @}
+ */
+
+/** @defgroup AFC0_Register
+ * @{
+ */
+
+/**
+ *  \brief AFC0 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x25
+ *   7:4  AFC_FAST_GAIN_LOG2[3:0]: AFC loop gain in fast mode (2's log)
+ *
+ *   3:0  AFC_SLOW_GAIN_LOG2[3:0]: AFC loop gain in slow mode (2's log)
+ *
+ *   \endcode
+ */
+#define	AFC0_BASE						((uint8_t)0x20) /*!< AFC loop gain in fast and slow modes (2's log) */
+
+/**
+ * @}
+ */
+
+/** @defgroup CLOCKREC_Register
+ * @{
+ */
+
+/**
+ *  \brief CLOCKREC register
+ *  \code
+ *   Read Write
+ *   Default value: 0x58
+ *
+ *   7:5 CLK_REC_P_GAIN [2:0]: Clock recovery loop gain (log2)
+ *
+ *   4   PSTFLT_LEN: Set Postfilter length
+ *                       1 - 16 symbols
+ *                       0 - 8 symbols
+ *
+ *   3:0 CLK_REC_I_GAIN[3:0]: Integral gain for the clock recovery loop
+ *   \endcode
+ */
+
+#define	CLOCKREC_BASE						((uint8_t)0x23) /*!< Gain of clock recovery loop - Postfilter length 0-8 symbols, 1-16 symbols */
+
+/**
+ * @}
+ */
+
+/** @defgroup AGCCTRL2_Register
+ * @{
+ */
+
+/**
+ *  \brief AGCCTRL2 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x22
+ *
+ *   7   Reserved
+ *
+ *   6   FREEZE_ON_STEADY: Enable freezing on steady state
+ *                       1 - Enable
+ *                       0 - Disable
+ *
+ *   5   FREEZE_ON_SYNC: Enable freezing on sync detection
+ *                       1 - Enable
+ *                       0 - Disable
+ *
+ *   4   START_MAX_ATTENUATION: Start with max attenuation
+ *                       1 - Enable
+ *                       0 - Disable
+ *
+ *   3:0  MEAS_TIME[3:0]: Measure time during which the signal peak is detected (according to the formula 12/fxo*2^MEAS_TIME)
+ *   \endcode
+ */
+#define	AGCCTRL2_BASE						((uint8_t)0x24) /*!< AGC freeze strategy, AGC attenuation  strategy, AGC measure time */
+
+#define AGCCTRL2_FREEZE_ON_STEADY_MASK			        ((uint8_t)0x40) /*!< The attenuation settings will be frozen as soon as signal level
+										     is betweeen min and max treshold (see AGCCTRL1) */
+#define AGCCTRL2_FREEZE_ON_SYNC_MASK				((uint8_t)0x20) /*!< The attenuation settings will be frozen as soon sync word is detected */
+#define AGCCTRL2_START_MAX_ATTENUATION_MASK			((uint8_t)0x10) /*!< The AGC algorithm can start with MAX attenuation or MIN attenuation */
+
+/**
+ * @}
+ */
+
+/** @defgroup AGCCTRL1_Register
+ * @{
+ */
+
+/**
+ *  \brief AGCCTRL1 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x65
+ *
+ *   7:4   THRESHOLD_HIGH[3:0]: High threshold for the AGC
+ *
+ *   3:0   THRESHOLD_LOW[3:0]: Low threshold for the AGC
+ *   \endcode
+ */
+#define	AGCCTRL1_BASE						((uint8_t)0x25) /*!< Sets low and high threshold for AGC */
+
+/**
+ * @}
+ */
+
+/** @defgroup AGCCTRL0_Register
+ * @{
+ */
+
+/**
+ *  \brief AGCCTRL0 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x8A
+ *
+ *   7   AGC S_ENABLE: Enable AGC
+ *                       1 - Enable
+ *                       0 - Disable
+ *
+ *   6   AGC_MODE: Set linear-Binary AGC mode
+ *                       1 - Enable
+ *                       0 - Disable
+ *
+ *   5:0 HOLD_TIME[5:0]: Hold time after gain adjustment according to formula 12/fxo*HOLD_TIME
+ *   \endcode
+ */
+#define	AGCCTRL0_BASE						((uint8_t)0x26) /*!< Enables AGC, set AGC algo between linear/binary mode, set hold time
+																	to account signal propagation through RX chain */
+#define AGCCTRL0_AGC_MASK				        ((uint8_t)0x80) /*!< AGC on/off */
+#define AGCCTRL0_AGC_MODE_MASK  				((uint8_t)0x40) /*!< AGC search correct attenuation in binary mode or sequential mode */
+#define AGCCTRL0_AGC_MODE_LINEAR				((uint8_t)0x00) /*!< AGC search correct attenuation in sequential mode (recommended) */
+#define AGCCTRL0_AGC_MODE_BINARY				((uint8_t)0x40) /*!< AGC search correct attenuation in binary mode */
+
+/**
+ * @}
+ */
+
+/** @defgroup CHNUM_Register
+ * @{
+ */
+
+/**
+ *  \brief CHNUM  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0     CH_NUM[7:0]: Channel number. This value is multiplied by the channel spacing and added to the
+ *                        synthesizer base frequency to generate the actual RF carrier frequency.
+ *   \endcode
+ */
+#define	CHNUM_BASE						((uint8_t)0x6C) /*!< Channel number. This value is multiplied by the channel
+										spacing and added to the synthesizer base frequency to generate the actual RF carrier frequency */
+/**
+ * @}
+ */
+
+/** @defgroup AFC_CORR_Register
+ * @{
+ */
+
+/**
+ *  \brief AFC_CORR  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   AFC_CORR[7:0]: AFC word of the received packet
+ *   \endcode
+ */
+#define	AFC_CORR_BASE						((uint8_t)(0xC4)) /*!< AFC word of the received packet */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Packet_Configuration_Registers
+ * @{
+ */
+
+/** @defgroup PCKTCTRL4_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKTCTRL4 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x00
+ *
+ *   7:5   NOT_USED.
+ *
+ *   4:3   ADDRESS_LEN[1:0]: length of address field in bytes
+ *
+ *   2:0   control_len[2:0]: length of control field in bytes
+ *   \endcode
+ */
+#define	PCKTCTRL4_BASE						((uint8_t)0x30) /*!< lenghts of address and control field */
+
+#define PCKTCTRL4_ADDRESS_LEN_MASK                              ((uint8_t)0x18)
+#define PCKTCTRL4_CONTROL_LEN_MASK                              ((uint8_t)0x07)
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKTCTRL3_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKTCTRL3 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x07
+ *
+ *   7:6   PCKT_FRMT[1:0]: format of packet
+ *
+ *          PCKT_FRMT1       |        PCKT_FRMT0       |        Format
+ *       ----------------------------------------------------------------------
+ *             0             |           0             |        BASIC
+ *             1             |           0             |        MBUS
+ *             1             |           1             |        STACK
+ *
+ *   5:4   RX_MODE[1:0]: length of address 0x30 field in bytes
+ *
+ *          RX_MODE1       |        RX_MODE0       |            Rx Mode
+ *       --------------------------------------------------------------------
+ *             0           |           0           |              normal
+ *             0           |           1           |       direct through FIFO
+ *             1           |           0           |       direct through GPIO
+ *
+ *   3:0   LEN_WID[3:0]: length of length field in bits
+ *   \endcode
+ */
+#define	PCKTCTRL3_BASE						((uint8_t)0x31) /*!< packet format, RX mode, lenght of length field */
+
+#define	PCKTCTRL3_PCKT_FRMT_BASIC				((uint8_t)0x00) /*!< Basic Packet Format */
+#define	PCKTCTRL3_PCKT_FRMT_MBUS				((uint8_t)0x80) /*!< Wireless M-BUS Packet Format */
+#define	PCKTCTRL3_PCKT_FRMT_STACK				((uint8_t)0xC0) /*!< STack Packet Format */
+
+#define	PCKTCTRL3_RX_MODE_NORMAL				((uint8_t)0x00) /*!< Normal RX Mode */
+#define	PCKTCTRL3_RX_MODE_DIRECT_FIFO				((uint8_t)0x10) /*!< RX Direct Mode; data available through FIFO */
+#define	PCKTCTRL3_RX_MODE_DIRECT_GPIO				((uint8_t)0x20) /*!< RX Direct Mode; data available through selected GPIO */
+
+#define PCKTCTRL3_PKT_FRMT_MASK                                 ((uint8_t)0xC0)
+#define PCKTCTRL3_RX_MODE_MASK                                  ((uint8_t)0x30)
+#define PCKTCTRL3_LEN_WID_MASK                                  ((uint8_t)0x0F)
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKTCTRL2_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKTCTRL2 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x1E
+ *
+ *   7:3   PREAMBLE_LENGTH[4:0]: length of preamble field in bytes (0..31)
+ *
+ *
+ *   2:1   SYNC_LENGTH[1:0]: length of sync field in bytes
+ *
+ *
+ *   0     FIX_VAR_LEN: fixed/variable packet length
+ *                       1 - Variable
+ *                       0 - Fixed
+ *   \endcode
+ */
+#define	PCKTCTRL2_BASE						((uint8_t)0x32) /*!< length of preamble and sync fields (in bytes), fix or variable packet length */
+   
+#define	PCKTCTRL2_FIX_VAR_LEN_MASK				((uint8_t)0x01) /*!< Enable/disable the length mode */
+#define PCKTCTRL2_PREAMBLE_LENGTH_MASK                          ((uint8_t)0xF8)
+#define PCKTCTRL2_SYNC_LENGTH_MASK                              ((uint8_t)0x06)
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKTCTRL1_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKTCTRL1 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x20
+ *
+ *   7:5   CRC_MODE[2:0]: CRC type (0, 8, 16, 24 bits)
+ *
+ *          CRC_MODE2     |       CRC_MODE1     |        CRC_MODE0     |       CRC Mode  (n. bits - poly)
+ *       -------------------------------------------------------------------------------------------------
+ *             0           |         0          |          1           |       8 - 0x07
+ *             0           |         1          |          0           |       16 -  0x8005
+ *             0           |         1          |          1           |       16 - 0x1021
+ *             1           |         0          |          0           |       24 - 0x864CBF
+ *
+ *   4     WHIT_EN[0]: Enable Whitening
+ *                       1 - Enable
+ *                       0 - Disable
+ *
+ *   3:2   TX_SOURCE[1:0]: length of sync field in bytes
+ *
+ *          TX_SOURCE1     |        TX_SOURCE0     |        Tx Mode
+ *       --------------------------------------------------------------------
+ *             0           |           0           |       normal
+ *             0           |           1           |       direct through FIFO
+ *             1           |           0           |       direct through GPIO
+ *             1           |           1           |       pn9
+ *
+ *   1   NOT_USED
+ *
+ *   0   FEC_EN: enable FEC
+ *                       1 - FEC in TX , Viterbi decoding in RX
+ *                       0 - Disabled
+ *   \endcode
+ */
+#define	PCKTCTRL1_BASE						((uint8_t)0x33) /*!< CRC type, whitening enable, TX mode */
+
+#define	PCKTCTRL1_FEC_MASK					((uint8_t)0x01) /*!< Enable/disable the Forward Error Correction */
+#define PCKTCTRL1_TX_SOURCE_MASK                                ((uint8_t)0x0C) /*!< TX source mode */
+#define PCKTCTRL1_CRC_MODE_MASK                                 ((uint8_t)0xE0) /*!< CRC type */
+#define PCKTCTRL1_WHIT_MASK                                     ((uint8_t)0x10) /*!< Enable/disable the Whitening */
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup PCKTLEN1_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKTLEN1 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x00
+ *
+ *   7:0   pktlen1[7:0]: lenght of packet in bytes (upper field) LENGHT/256
+ *   \endcode
+ */
+#define	PCKTLEN1_BASE						((uint8_t)0x34) /*!< lenght of packet in bytes (upper field) */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKTLEN0_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKTLEN0 register
+ *  \code
+ *   Read Write
+ *   Default value: 0x14
+ *
+ *   7:0   pktlen0[7:0]: lenght of packet in bytes (lower field) LENGHT%256
+ *   \endcode
+ */
+#define	PCKTLEN0_BASE						((uint8_t)0x35) /*!< lenght of packet in bytes (lower field) [PCKTLEN=PCKTLEN1x256+PCKTLEN0]*/
+
+/**
+ * @}
+ */
+
+/** @defgroup SYNCx_Registers
+ * @{
+ */
+/**
+ *  \brief SYNCx[4:1] Registers
+ *  \code
+ *   Read Write
+ *   Default value: 0x88
+ *
+ *   7:0   SYNCx[7:0]: xth sync word
+ *   \endcode
+ */
+#define	SYNC4_BASE						((uint8_t)0x36) /*!< Sync word 4 */
+#define	SYNC3_BASE						((uint8_t)0x37) /*!< Sync word 3 */
+#define	SYNC2_BASE						((uint8_t)0x38) /*!< Sync word 2 */
+#define	SYNC1_BASE						((uint8_t)0x39) /*!< Sync word 1 */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MBUS_PRMBL_Register
+ * @{
+ */
+
+/**
+ *  \brief MBUS_PRMBL register
+ *  \code
+ *   Read Write
+ *   Default value: 0x20
+ *
+ *   7:0 MBUS_PRMBL[7:0]: MBUS preamble control
+ *   \endcode
+ */
+#define	MBUS_PRMBL_BASE						((uint8_t)0x3B) /*!< MBUS preamble lenght (in 01 bit pairs) */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MBUS_PSTMBL_Register
+ * @{
+ */
+
+/**
+ *  \brief MBUS_PSTMBL register
+ *  \code
+ *   Read Write
+ *   Default value: 0x20
+ *
+ *   7:0 MBUS_PSTMBL[7:0]: MBUS postamble control
+ *   \endcode
+ */
+#define	MBUS_PSTMBL_BASE					((uint8_t)0x3C) /*!< MBUS postamble length (in 01 bit pairs) */
+
+/**
+ * @}
+ */
+
+/** @defgroup MBUS_CTRL_Register
+ * @{
+ */
+
+/**
+ *  \brief MBUS_CTRL register
+ *  \code
+ *   Read Write
+ *   Default value: 0x00
+ *
+ *   7:4   NOT_USED
+ *
+ *   3:1   MBUS_SUBMODE[2:0]: MBUS submode (allowed values are 0,1,3,5)
+ *
+ *   0     NOT_USED
+ *   \endcode
+ */
+#define	MBUS_CTRL_BASE						((uint8_t)0x3D) /*!< MBUS sub-modes (S1, S2 short/long header, T1, T2, R2) */
+
+#define	MBUS_CTRL_MBUS_SUBMODE_S1_S2L				((uint8_t)0x00) /*!< MBUS sub-modes S1 & S2L, header lenght min 279, sync 0x7696, Manchester */
+#define	MBUS_CTRL_MBUS_SUBMODE_S2_S1M_T2_OTHER			((uint8_t)0x02) /*!< MBUS sub-modes S2, S1-m, T2 (only other to meter) short header, header lenght min 15, sync 0x7696, Manchester */
+#define	MBUS_CTRL_MBUS_SUBMODE_T1_T2_METER			((uint8_t)0x06) /*!< MBUS sub-modes T1, T2 (only meter to other), header lenght min 19, sync 0x3D, 3 out of 6 */
+#define	MBUS_CTRL_MBUS_SUBMODE_R2				((uint8_t)0x0A) /*!< MBUS sub-mode R2, header lenght min 39, sync 0x7696, Manchester */
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup PCKT_FLT_GOALS_CONTROLx_MASK_Registers
+ * @{
+ */
+
+/**
+ *  \brief PCKT_FLT_GOALS_CONTROLx_MASK  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0    CONTROLx_MASK[7:0]:   All 0s - no filtering
+ *
+ *   \endcode
+ */
+#define	PCKT_FLT_GOALS_CONTROL0_MASK_BASE			((uint8_t)0x42) /*!< Packet control field #3 mask, all 0s -> no filtering */
+
+#define	PCKT_FLT_GOALS_CONTROL1_MASK_BASE			((uint8_t)0x43) /*!< Packet control field #2 mask, all 0s -> no filtering */
+
+#define	PCKT_FLT_GOALS_CONTROL2_MASK_BASE			((uint8_t)0x44) /*!< Packet control field #1 mask, all 0s -> no filtering */
+
+#define	PCKT_FLT_GOALS_CONTROL3_MASK_BASE			((uint8_t)0x45) /*!< Packet control field #0 mask, all 0s -> no filtering */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKT_FLT_GOALS_CONTROLx_FIELD_Registers
+ * @{
+ */
+
+/**
+ *  \brief PCKT_FLT_GOALS_CONTROLx_FIELD  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0    CONTROLx_FIELD[7:0]:   Control field (byte x) to be used as reference
+ *
+ *   \endcode
+ */
+#define	PCKT_FLT_GOALS_CONTROL0_FIELD_BASE			((uint8_t)0x46) /*!< Control field (byte #3) */
+
+#define	PCKT_FLT_GOALS_CONTROL1_FIELD_BASE			((uint8_t)0x47) /*!< Control field (byte #2) */
+
+#define	PCKT_FLT_GOALS_CONTROL2_FIELD_BASE			((uint8_t)0x48) /*!< Control field (byte #1) */
+
+#define	PCKT_FLT_GOALS_CONTROL3_FIELD_BASE			((uint8_t)0x49) /*!< Control field (byte #0) */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKT_FLT_GOALS_SOURCE_MASK_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKT_FLT_GOALS_SOURCE_MASK  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0    RX_SOURCE_MASK[7:0]:   For received packet only: all 0s - no filtering
+ *
+ *   \endcode
+ */
+#define	PCKT_FLT_GOALS_SOURCE_MASK_BASE				((uint8_t)0x4A) /*!< Source address mask, valid in RX mode */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKT_FLT_GOALS_SOURCE_ADDR_Register
+ * @{
+ */
+/**
+ *  \brief PCKT_FLT_GOALS_SOURCE_ADDR  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0    RX_SOURCE_ADDR[7:0]:  RX packet source / TX packet destination fields
+ *
+ *   \endcode
+ */
+#define	PCKT_FLT_GOALS_SOURCE_ADDR_BASE				((uint8_t)0x4B) /*!< Source address */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKT_FLT_GOALS_BROADCAST_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKT_FLT_GOALS_BROADCAST  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0    BROADCAST[7:0]:  Address shared for broadcast communication link
+ *
+ *   \endcode
+ */
+#define	PCKT_FLT_GOALS_BROADCAST_BASE				((uint8_t)0x4C) /*!< Address shared for broadcast communication links */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKT_FLT_GOALS_MULTICAST_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKT_FLT_GOALS_MULTICAST  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0    MULTICAST[7:0]:  Address shared for multicast communication links
+ *
+ *   \endcode
+ */
+#define	PCKT_FLT_GOALS_MULTICAST_BASE				((uint8_t)0x4D) /*!< Address shared for multicast communication links */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKT_FLT_GOALS_TX_SOURCE_ADDR_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKT_FLT_GOALS_TX_SOURCE_ADDR  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0    TX_SOURCE_ADDR[7:0]:  TX packet source / RX packet destination fields
+ *
+ *   \endcode
+ */
+#define	PCKT_FLT_GOALS_TX_ADDR_BASE				((uint8_t)0x4E) /*!< Address of the destination (also device own address) */
+
+/**
+ * @}
+ */
+
+/** @defgroup PCKT_FLT_OPTIONS_Register
+ * @{
+ */
+
+/**
+ *  \brief PCKT_FLT_OPTIONS  register
+ *  \code
+ *   Default value: 0x70
+ *   Read Write
+ *   7   Reserved.
+ *
+ *   6   RX_TIMEOUT_AND_OR_SELECT[0]:  1 - ‘OR’ logical function applied to CS/SQI/PQI
+ *                                     values (masked by 7:5 bits in PROTOCOL register)
+ *   5   CONTROL_FILTERING[0]:         1 - RX packet accepted if its control fields matches
+ *                                     with masked CONTROLx_FIELD registers.
+ *   4   SOURCE_FILTERING[0]:          1 - RX packet accepted if its source field
+ *                                     matches w/ masked RX_SOURCE_ADDR register.
+ *   3   DEST_VS_ SOURCE _ADDR[0]:   1 - RX packet accepted if its destination
+ *                                   address matches with TX_SOURCE_ADDR reg.
+ *   2   DEST_VS_MULTICAST_ADDR[0]:  1 - RX packet accepted if its destination
+ *                                   address matches with MULTICAST register
+ *   1   DEST_VS_BROADCAST_ADDR[0]:  1 - RX packet accepted if its destination
+ *                                   address matches with BROADCAST register.
+ *   0   CRC_CHECK[0]:               1 - packet discarded if CRC not valid.
+ *
+ *   \endcode
+ */
+#define	PCKT_FLT_OPTIONS_BASE					((uint8_t)0x4F) /*!< Options relative to packet filtering */
+
+#define	PCKT_FLT_OPTIONS_CRC_CHECK_MASK 			((uint8_t)0x01) /*!< Enable/disable of CRC check: packet is discarded if CRC is not valid [RX] */
+#define	PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK		((uint8_t)0x02) /*!< Packet discarded if destination address differs from BROADCAST register [RX] */
+#define	PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK		((uint8_t)0x04) /*!< Packet discarded if destination address differs from MULTICAST register [RX] */
+#define	PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK			((uint8_t)0x08) /*!< Packet discarded if destination address differs from TX_ADDR register [RX] */
+#define	PCKT_FLT_OPTIONS_SOURCE_FILTERING_MASK		        ((uint8_t)0x10) /*!< Packet discarded if source address (masked by the SOURCE_MASK register)
+                                                                                     differs from SOURCE_ADDR register [RX] */
+#define	PCKT_FLT_OPTIONS_CONTROL_FILTERING_MASK		        ((uint8_t)0x20) /*!< Packet discarded if the x-byte (x=1¸4) control field  (masked by the CONTROLx_MASK register)
+                                                                                     differs from CONTROLx_FIELD register [RX] */
+#define	PCKT_FLT_OPTIONS_RX_TIMEOUT_AND_OR_SELECT		((uint8_t)0x40) /*!< Logical function applied to CS/SQI/PQI values (masked by [7:5] bits in PROTOCOL[2]
+                                                                                     register) */
+
+/**
+ * @}
+ */
+
+/** @defgroup TX_CTRL_FIELD_Registers
+ * @{
+ */
+
+/**
+ *  \brief TX_CTRL_FIELDx  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0     TX_CTRLx[7:0]: Control field value to be used in TX packet as byte n.x
+ *   \endcode
+ */
+#define	TX_CTRL_FIELD3_BASE					((uint8_t)0x68) /*!< Control field value to be used in TX packet as byte n.3 */
+
+#define	TX_CTRL_FIELD2_BASE					((uint8_t)0x69) /*!< Control field value to be used in TX packet as byte n.2 */
+
+#define	TX_CTRL_FIELD1_BASE					((uint8_t)0x6A) /*!< Control field value to be used in TX packet as byte n.1 */
+
+#define	TX_CTRL_FIELD0_BASE					((uint8_t)0x6B) /*!< Control field value to be used in TX packet as byte n.0 */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup TX_PCKT_INFO_Register
+ * @{
+ */
+
+/**
+ *  \brief TX_PCKT_INFO  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:6     Not used.
+ *
+ *   5:4     TX_SEQ_NUM:   Current TX packet sequence number
+ *
+ *   0       N_RETX[3:0]:  Number of retransmissions done on the
+ *                        last TX packet
+ *   \endcode
+ */
+#define	TX_PCKT_INFO_BASE					((uint8_t)(0xC2)) /*!< Current TX packet sequence number [5:4];
+                                                                                        Number of retransmissions done on the last TX packet [3:0]*/
+/**
+ * @}
+ */
+
+/** @defgroup RX_PCKT_INFO_Register
+ * @{
+ */
+
+/**
+ *  \brief RX_PCKT_INFO  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:3     Not used.
+ *
+ *   2       NACK_RX:   NACK field of the received packet
+ *
+ *   1:0     RX_SEQ_NUM[1:0]:  Sequence number of the received packet
+ *   \endcode
+ */
+#define	RX_PCKT_INFO_BASE					((uint8_t)(0xC3)) /*!< NO_ACK field of the received packet [2];
+                                                                                       sequence number of the received packet [1:0]*/
+
+#define	TX_PCKT_INFO_NACK_RX					((uint8_t)(0x04)) /*!< NACK field of the received packet */
+
+/**
+ * @}
+ */
+
+/** @defgroup RX_PCKT_LEN1
+ * @{
+ */
+
+/**
+ *  \brief RX_PCKT_LEN1  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   RX_PCKT_LEN1[7:0]:  Length (number of bytes) of the received packet: RX_PCKT_LEN=RX_PCKT_LEN1 × 256 + RX_PCKT_LEN0
+ *                             This value is packet_length/256
+ *   \endcode
+ */
+#define	RX_PCKT_LEN1_BASE					((uint8_t)(0xC9)) /*!< Length (number of  bytes) of the received packet: */
+
+/**
+ * @}
+ */
+
+/** @defgroup RX_PCKT_LEN0
+ * @{
+ */
+
+/**
+ *  \brief RX_PCKT_LEN0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   RX_PCKT_LEN0[7:0]:  Length (number of bytes) of the received packet: RX_PCKT_LEN=RX_PCKT_LEN1 × 256 + RX_PCKT_LEN0
+ *                             This value is packet_length%256
+ *   \endcode
+ */
+#define	RX_PCKT_LEN0_BASE					((uint8_t)(0xCA)) /*!< RX_PCKT_LEN=RX_PCKT_LEN1 × 256 + RX_PCKT_LEN0 */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup CRC_FIELD_Register
+ * @{
+ */
+
+/**
+ *  \brief CRC_FIELD[2:0]  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   CRC_FIELDx[7:0]:    upper(x=2), middle(x=1) and lower(x=0) part of the crc field of the received packet
+ *  \endcode
+ */
+#define	CRC_FIELD2_BASE						((uint8_t)(0xCB)) /*!< CRC2 field of the received packet */
+
+#define	CRC_FIELD1_BASE						((uint8_t)(0xCC)) /*!< CRC1 field of the received packet */
+
+#define	CRC_FIELD0_BASE						((uint8_t)(0xCD)) /*!< CRC0 field of the received packet */
+
+/**
+ * @}
+ */
+
+/** @defgroup RX_CTRL_FIELD_Register
+ * @{
+ */
+
+/**
+ *  \brief RX_CTRL_FIELD[3:0]  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   RX_CTRL_FIELDx[7:0]:    upper(x=3), middle(x=2), middle(x=1) and lower(x=0) part of the control field of the received packet
+ *   \endcode
+ */
+#define	RX_CTRL_FIELD0_BASE					((uint8_t)(0xCE)) /*!< CRTL3 Control field of the received packet */
+
+#define	RX_CTRL_FIELD1_BASE					((uint8_t)(0xCF)) /*!< CRTL2 Control field of the received packet */
+
+#define	RX_CTRL_FIELD2_BASE					((uint8_t)(0xD0)) /*!< CRTL1 Control field of the received packet */
+
+#define	RX_CTRL_FIELD3_BASE					((uint8_t)(0xD1)) /*!< CRTL0 Control field of the received packet */
+
+/**
+ * @}
+ */
+
+/** @defgroup RX_ADDR_FIELD_Register
+ * @{
+ */
+
+/**
+ *  \brief RX_ADDR_FIELD[1:0]  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   RX_ADDR_FIELDx[7:0]:    source(x=1) and destination(x=0) address field of the received packet
+ *   \endcode
+ */
+#define	RX_ADDR_FIELD1_BASE					((uint8_t)(0xD2)) /*!< ADDR1 Address field of the received packet */
+
+#define	RX_ADDR_FIELD0_BASE					((uint8_t)(0xD3)) /*!< ADDR0 Address field of the received packet */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Protocol_Registers
+ * @{
+ */
+
+/** @defgroup PROTOCOL2_Register
+ * @{
+ */
+
+/**
+ *  \brief PROTOCOL2  register
+ *  \code
+ *   Default value: 0x06
+ *   Read Write
+ *   7   CS_TIMEOUT_MASK:              1 - CS value contributes to timeout disabling
+ *
+ *   6   SQI_TIMEOUT_MASK:             1 - SQI value contributes to timeout disabling
+ *
+ *   5   PQI_TIMEOUT_MASK:             1 - PQI value contributes to timeout disabling
+ *
+ *   4:3  TX_SEQ_NUM_RELOAD[1:0]:      TX sequence number to be used when counting reset is required using the related command.
+ *
+ *   2   RCO_CALIBRATION[0]:           1 - Enables the automatic RCO calibration
+ *
+ *   1   VCO_CALIBRATION[0]:           1 - Enables the automatic VCO calibration
+ *
+ *   0   LDCR_MODE[0]:                 1 - LDCR mode enabled
+ *
+ *   \endcode
+ */
+#define	PROTOCOL2_BASE						((uint8_t)0x50) /*!< Protocol2 regisetr address */
+
+#define	PROTOCOL2_LDC_MODE_MASK				        ((uint8_t)0x01) /*!< Enable/disable Low duty Cycle mode */
+#define	PROTOCOL2_VCO_CALIBRATION_MASK			        ((uint8_t)0x02) /*!< Enable/disable VCO automatic calibration */
+#define	PROTOCOL2_RCO_CALIBRATION_MASK			        ((uint8_t)0x04) /*!< Enable/disable RCO automatic calibration */
+#define	PROTOCOL2_PQI_TIMEOUT_MASK			        ((uint8_t)0x20) /*!< PQI value contributes to timeout disabling */
+#define	PROTOCOL2_SQI_TIMEOUT_MASK			        ((uint8_t)0x40) /*!< SQI value contributes to timeout disabling */
+#define	PROTOCOL2_CS_TIMEOUT_MASK			        ((uint8_t)0x80) /*!< CS value contributes to timeout disabling */
+  
+/**
+ * @}
+ */
+
+/** @defgroup PROTOCOL1_Register
+ * @{
+ */
+
+/**
+ *  \brief PROTOCOL1  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7   LDCR_RELOAD_ON_SYNC:          1 - LDCR timer will be reloaded with the value stored in the LDCR_RELOAD registers
+ *
+ *   6   PIGGYBACKING:                 1 - PIGGYBACKING enabled
+ *
+ *   5:4   Reserved.
+ *
+ *   3   SEED_RELOAD[0]:               1 - Reload the back-off random generator
+ *                                        seed using the value written in the
+ *                                        BU_COUNTER_SEED_MSByte / LSByte registers
+ *
+ *   2   CSMA_ON   [0]:                1 - CSMA channel access mode enabled
+ *
+ *   1   CSMA_PERS_ON[0]:              1 - CSMA persistent (no back-off) enabled
+ *
+ *   0   AUTO_PCKT_FLT[0]:             1 - automatic packet filtering mode enabled
+ *
+ *   \endcode
+ */
+#define	PROTOCOL1_BASE						((uint8_t)0x51) /*!< Protocol1 regisetr address */
+
+#define	PROTOCOL1_AUTO_PCKT_FLT_MASK				((uint8_t)0x01) /*!< Enable/disable automatic packet filtering mode */
+#define	PROTOCOL1_CSMA_PERS_ON_MASK				((uint8_t)0x02) /*!< Enable/disable CSMA persistent (no back-off)  */
+#define	PROTOCOL1_CSMA_ON_MASK				        ((uint8_t)0x04) /*!< Enable/disable CSMA channel access mode */
+#define	PROTOCOL1_SEED_RELOAD_MASK				((uint8_t)0x08) /*!< Reloads the seed of the PN generator for CSMA procedure */
+#define	PROTOCOL1_PIGGYBACKING_MASK				((uint8_t)0x40) /*!< Enable/disable Piggybacking */
+#define	PROTOCOL1_LDC_RELOAD_ON_SYNC_MASK			((uint8_t)0x80) /*!< LDC timer will be reloaded with the value stored in the LDC_RELOAD registers */
+
+/**
+ * @}
+ */
+
+/** @defgroup PROTOCOL0_Register
+ * @{
+ */
+
+/**
+ *  \brief PROTOCOL0  register
+ *  \code
+ *   Default value: 0x08
+ *   Read Write
+ *   7:4   NMAX_RETX[3:0]:             Max number of re-TX.  0 - re-transmission is not performed
+ *
+ *   3     NACK_TX[0]:                 1 - field NO_ACK=1 on transmitted packet
+ *
+ *   2     AUTO_ACK[0]:                1 - automatic ack after RX
+ *
+ *   1     PERS_RX[0]:                 1 - persistent reception enabled
+ *
+ *   0     PERS_TX[0]:                 1 - persistent transmission enabled
+ *
+ *   \endcode
+ */
+#define	PROTOCOL0_BASE						((uint8_t)0x52) /*!< Persistent RX/TX, autoack, Max number of retransmissions */
+
+#define	PROTOCOL0_PERS_TX_MASK				        ((uint8_t)0x01) /*!< Enables persistent transmission */
+#define	PROTOCOL0_PERS_RX_MASK				        ((uint8_t)0x02) /*!< Enables persistent reception */
+#define	PROTOCOL0_AUTO_ACK_MASK				        ((uint8_t)0x04) /*!< Enables auto acknowlegment */
+#define	PROTOCOL0_NACK_TX_MASK				        ((uint8_t)0x08) /*!< Writes field NO_ACK=1 on transmitted packet */
+#define	PROTOCOL0_NMAX_RETX_MASK                                ((uint8_t)0xF0) /*!< Retransmission mask */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMERS5_Register
+ * @{
+ */
+
+/**
+ *  \brief TIMERS5  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0   RX_TIMEOUT_PRESCALER[7:0] :             RX operation timeout: prescaler value
+ *   \endcode
+ */
+#define	TIMERS5_RX_TIMEOUT_PRESCALER_BASE			((uint8_t)0x53) /*!< RX operation timeout: prescaler value */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMERS4_Register
+ * @{
+ */
+
+/**
+ *  \brief TIMERS4  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0   RX_TIMEOUT_COUNTER[7:0] :               RX operation timeout: counter value
+ *   \endcode
+ */
+#define	TIMERS4_RX_TIMEOUT_COUNTER_BASE				((uint8_t)0x54) /*!< RX operation timeout: counter value */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMERS3_Register
+ * @{
+ */
+
+/**
+ *  \brief TIMERS3  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0   LDCR_PRESCALER[7:0] :                   LDC Mode: Prescaler part of the wake-up value
+ *   \endcode
+ */
+#define	TIMERS3_LDC_PRESCALER_BASE				((uint8_t)0x55) /*!< LDC Mode: Prescaler of the wake-up timer */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMERS2_Register
+ * @{
+ */
+
+/**
+ *  \brief TIMERS2  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0   LDCR_COUNTER[7:0] :                    LDC Mode: counter part of the wake-up value
+ *   \endcode
+ */
+#define	TIMERS2_LDC_COUNTER_BASE				((uint8_t)0x56) /*!< LDC Mode: counter of the wake-up timer */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMERS1_Register
+ * @{
+ */
+
+/**
+ *  \brief TIMERS1  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0   LDCR_RELOAD_PRESCALER[7:0] :           LDC Mode: Prescaler part of the reload value
+ *   \endcode
+ */
+#define	TIMERS1_LDC_RELOAD_PRESCALER_BASE			((uint8_t)0x57) /*!< LDC Mode: Prescaler part of the reload value */
+
+/**
+ * @}
+ */
+
+/** @defgroup TIMERS0_Register
+ * @{
+ */
+
+/**
+ *  \brief TIMERS0  register
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0   LDCR_RELOAD_COUNTER[7:0] :           LDC Mode: Counter part of the reload value
+ *   \endcode
+ */
+#define	TIMERS0_LDC_RELOAD_COUNTER_BASE				((uint8_t)0x58) /*!< LDC Mode: Counter part of the reload value */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup CSMA_CONFIG3_Register
+ * @{
+ */
+
+/**
+ *  \brief CSMA_CONFIG3  registers
+ *  \code
+ *   Default value: 0xFF
+ *   Read Write
+ *   7:0     BU_COUNTER_SEED_MSByte: Seed of the random number generator used to apply the BEB (Binary Exponential Backoff) algorithm (MSB)
+ *   \endcode
+ */
+#define	CSMA_CONFIG3_BASE		                      ((uint8_t)0x64) /*!< CSMA/CA: Seed of the random number generator used to apply the BEB (Binary Exponential Backoff) algorithm (MSB) */
+
+/**
+ * @}
+ */
+
+/** @defgroup CSMA_CONFIG2_Register
+ * @{
+ */
+
+/**
+ *  \brief CSMA_CONFIG2  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:0     BU_COUNTER_SEED_LSByte: Seed of the random number generator used to apply the BEB (Binary Exponential Backoff) algorithm (LSB)
+ *   \endcode
+ */
+#define	CSMA_CONFIG2_BASE		                      ((uint8_t)0x65) /*!< CSMA/CA: Seed of the random number generator used to apply the BEB (Binary Exponential Backoff) algorithm (LSB) */
+
+/**
+ * @}
+ */
+
+/** @defgroup CSMA_CONFIG1_Register
+ * @{
+ */
+
+/**
+ *  \brief CSMA_CONFIG1  registers
+ *  \code
+ *   Default value: 0x04
+ *   Read Write
+ *   7:2     BU_PRESCALER[5:0]: Used to program the back-off unit BU
+ *
+ *   1:0     CCA_PERIOD[1:0]: Used to program the Tcca time (64 / 128 /256 / 512 × Tbit.
+ *   \endcode
+ */
+#define	CSMA_CONFIG1_BASE				      ((uint8_t)0x66) /*!< CSMA/CA: Prescaler of the back-off time unit (BU); CCA period */
+
+#define	CSMA_CCA_PERIOD_64TBIT				      ((uint8_t)0x00) /*!< CSMA/CA: Sets CCA period to 64*TBIT */
+#define	CSMA_CCA_PERIOD_128TBIT				      ((uint8_t)0x01) /*!< CSMA/CA: Sets CCA period to 128*TBIT */
+#define	CSMA_CCA_PERIOD_256TBIT				      ((uint8_t)0x02) /*!< CSMA/CA: Sets CCA period to 256*TBIT */
+#define	CSMA_CCA_PERIOD_512TBIT				      ((uint8_t)0x03) /*!< CSMA/CA: Sets CCA period to 512*TBIT */
+
+/**
+ * @}
+ */
+
+/** @defgroup CSMA_CONFIG0_Register
+ * @{
+ */
+
+/**
+ *  \brief CSMA_CONFIG0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *   7:4     CCA_LENGTH[3:0]: Used to program the Tlisten time
+ *
+ *   3       Reserved.
+ *
+ *   2:0     NBACKOFF_MAX[2:0]: Max number of back-off cycles.
+ *   \endcode
+ */
+#define	CSMA_CONFIG0_BASE				      ((uint8_t)0x67) /*!< CSMA/CA: CCA lenght; Max number of backoff cycles */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Link_Quality_Registers
+ * @{
+ */
+
+/** @defgroup QI_Register
+ * @{
+ */
+
+/**
+ *  \brief QI register
+ *  \code
+ *   Read Write
+ *   Default value: 0x02
+ *
+ *   7:6   SQI_TH[1:0]: SQI threshold according to the formula: 8*SYNC_LEN - 2*SQI_TH
+ *
+ *   5:2   PQI_TH[3:0]: PQI threshold according to the formula: 4*PQI_THR
+ *
+ *
+ *   1     SQI_EN[0]:  SQI enable
+ *                 1 - Enable
+ *                 0 - Disable
+ *
+ *   0     PQI_EN[0]: PQI enable
+ *                 1 - Enable
+ *                 0 - Disable
+ *   \endcode
+ */
+#define	QI_BASE							((uint8_t)0x3A) /*!< QI register */
+
+#define	QI_PQI_MASK					        ((uint8_t)0x01) /*!< PQI enable/disable  */
+#define	QI_SQI_MASK					        ((uint8_t)0x02) /*!< SQI enable/disable  */
+
+/**
+ * @}
+ */
+
+/** @defgroup LINK_QUALIF2
+ * @{
+ */
+
+/**
+ *  \brief LINK_QUALIF2  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   PQI[7:0]: PQI value of the received packet
+ *   \endcode
+ */
+#define	LINK_QUALIF2_BASE					((uint8_t)(0xC5)) /*!< PQI value of the received packet */
+
+/**
+ * @}
+ */
+
+/** @defgroup LINK_QUALIF1
+ * @{
+ */
+
+/**
+ *  \brief LINK_QUALIF1  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7 CS:  Carrier Sense indication
+ *
+ *   6:0   SQI[6:0]: SQI value of the received packet
+ *   \endcode
+ */
+#define	LINK_QUALIF1_BASE					((uint8_t)(0xC6)) /*!< Carrier sense indication [7]; SQI value of the received packet */
+
+#define	LINK_QUALIF1_CS						((uint8_t)(0x80)) /*!< Carrier sense indication [7] */
+
+/**
+ * @}
+ */
+
+/** @defgroup LINK_QUALIF0
+ * @{
+ */
+
+/**
+ *  \brief LINK_QUALIF0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:4   LQI [3:0]:  LQI value of the received packet
+ *
+ *   3:0   AGC_WORD[3:0]: AGC word of the received packet
+ *   \endcode
+ */
+#define	LINK_QUALIF0_BASE					((uint8_t)(0xC7)) /*!< LQI value of the received packet [7:4]; AGC word of the received packet [3:0] */
+
+/**
+ * @}
+ */
+
+/** @defgroup RSSI_LEVEL
+ * @{
+ */
+
+/**
+ *  \brief RSSI_LEVEL  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   RSSI_LEVEL[7:0]:  RSSI level of the received packet
+ *   \endcode
+ */
+#define	RSSI_LEVEL_BASE						((uint8_t)(0xC8)) /*!< RSSI level of the received packet */
+
+/**
+ * @}
+ */
+
+/** @defgroup RSSI_FLT_Register
+ * @{
+ */
+
+/**
+ *  \brief RSSI register
+ *  \code
+ *   Read Write
+ *   Default value: 0xF3
+ *   7:4  RSSI_FLT[3:0]: Gain of the RSSI filter
+ *
+ *   3:2  CS_MODE[1:0]: AFC loop gain in slow mode (2's log)
+ *
+ *          CS_MODE1       |        CS_MODE0       |                     CS Mode
+ *       -----------------------------------------------------------------------------------------
+ *             0           |           0           |        Static CS
+ *             0           |           1           |        Dynamic CS with 6dB dynamic threshold
+ *             1           |           0           |        Dynamic CS with 12dB dynamic threshold
+ *             1           |           1           |        Dynamic CS with 18dB dynamic threshold
+ *
+ *   1:0   OOK_PEAK_DECAY[1:0]: Peak decay control for OOK: 3 slow decay; 0 fast decay
+ *
+ *   \endcode
+ */
+#define	RSSI_FLT_BASE						((uint8_t)0x21) /*!< Gain of the RSSI filter; lower value is fast but inaccurate,
+																	higher value is slow and more accurate */
+#define RSSI_FLT_CS_MODE_MASK					((uint8_t)0x0C) /*!< Carrier sense mode mask */
+#define RSSI_FLT_CS_MODE_STATIC					((uint8_t)0x00) /*!< Carrier sense mode;  static carrier sensing */
+#define RSSI_FLT_CS_MODE_DYNAMIC_6				((uint8_t)0x04) /*!< Carrier sense mode;  dynamic carrier sensing with 6dB threshold */
+#define RSSI_FLT_CS_MODE_DYNAMIC_12				((uint8_t)0x08) /*!< Carrier sense mode;  dynamic carrier sensing with 12dB threshold */
+#define RSSI_FLT_CS_MODE_DYNAMIC_18				((uint8_t)0x0C) /*!< Carrier sense mode;  dynamic carrier sensing with 18dB threshold */
+#define RSSI_FLT_OOK_PEAK_DECAY_MASK			        ((uint8_t)0x03) /*!< Peak decay control for OOK mask */
+#define RSSI_FLT_OOK_PEAK_DECAY_FAST			        ((uint8_t)0x00) /*!< Peak decay control for OOK: fast decay */
+#define RSSI_FLT_OOK_PEAK_DECAY_MEDIUM_FAST		        ((uint8_t)0x01) /*!< Peak decay control for OOK: medium_fast decay */
+#define RSSI_FLT_OOK_PEAK_DECAY_MEDIUM_SLOW		        ((uint8_t)0x02) /*!< Peak decay control for OOK: medium_fast decay */
+#define RSSI_FLT_OOK_PEAK_DECAY_SLOW			        ((uint8_t)0x03) /*!< Peak decay control for OOK: slow decay */
+
+/**
+ * @}
+ */
+
+/** @defgroup RSSI_TH_Register
+ * @{
+ */
+
+/**
+ *  \brief RSSI_TH register
+ *  \code
+ *   Read Write
+ *   Default value: 0x24
+ *
+ *   7:0 RSSI_THRESHOLD [7:0]:    Signal detect threshold in 0.5dB.  -120dBm corresponds to 20
+ *   \endcode
+ */
+#define	RSSI_TH_BASE						((uint8_t)0x22) /*!< Signal detect threshold in 0.5dB stp. 20 correspond to -120 dBm */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup FIFO_Registers
+ * @{
+ */
+
+/** @defgroup FIFO_CONFIG3_Register
+ * @{
+ */
+
+/**
+ *  \brief FIFO_CONFIG3  registers
+ *  \code
+ *   Default value: 0x30
+ *   Read Write
+ *   7    Reserved.
+ *
+ *   6:0  rxafthr [6:0]: FIFO Almost Full threshold for rx fifo.
+ *
+ *   \endcode
+ */
+#define	FIFO_CONFIG3_RXAFTHR_BASE				((uint8_t)0x3E) /*!< FIFO Almost Full threshold for rx fifo [6:0] */
+
+/**
+ * @}
+ */
+
+/** @defgroup FIFO_CONFIG2_Register
+ * @{
+ */
+
+/**
+ *  \brief FIFO_CONFIG2  registers
+ *  \code
+ *   Default value: 0x30
+ *   Read Write
+ *   7    Reserved.
+ *
+ *   6:0  rxaethr [6:0]: FIFO Almost Empty threshold for rx fifo.
+ *
+ *   \endcode
+ */
+#define	FIFO_CONFIG2_RXAETHR_BASE				((uint8_t)0x3F) /*!< FIFO Almost Empty threshold for rx fifo [6:0] */
+
+/**
+ * @}
+ */
+
+/** @defgroup FIFO_CONFIG1_Register
+ * @{
+ */
+
+/**
+ *  \brief FIFO_CONFIG1  registers
+ *  \code
+ *   Default value: 0x30
+ *   Read Write
+ *   7    Reserved.
+ *
+ *   6:0  txafthr [6:0]: FIFO Almost Full threshold for tx fifo.
+ *
+ *   \endcode
+ */
+#define	FIFO_CONFIG1_TXAFTHR_BASE				((uint8_t)0x40) /*!< FIFO Almost Full threshold for tx fifo [6:0] */
+
+/**
+ * @}
+ */
+
+/** @defgroup FIFO_CONFIG0_Register
+ * @{
+ */
+
+/**
+ *  \brief FIFO_CONFIG0  registers
+ *  \code
+ *   Default value: 0x30
+ *   Read Write
+ *   7    Reserved.
+ *
+ *   6:0  txaethr [6:0]: FIFO Almost Empty threshold for tx fifo.
+ *
+ *   \endcode
+ */
+#define	FIFO_CONFIG0_TXAETHR_BASE				((uint8_t)0x41) /*!< FIFO Almost Empty threshold for tx fifo [6:0] */
+
+/**
+ * @}
+ */
+
+/** @defgroup LINEAR_FIFO_STATUS1_Register
+ * @{
+ */
+
+/**
+ *  \brief LINEAR_FIFO_STATUS1  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7     Reserved.
+ *
+ *   6:0   elem_txfifo[6:0]:     Number of elements in the linear TXFIFO (<=96)
+ *   \endcode
+ */
+#define	LINEAR_FIFO_STATUS1_BASE				((uint8_t)(0xE6)) /*!< Number of elements in the linear TX FIFO [6:0] (<=96) */
+
+/**
+ * @}
+ */
+
+/** @defgroup LINEAR_FIFO_STATUS0_Register
+ * @{
+ */
+
+/**
+ *  \brief LINEAR_FIFO_STATUS0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7     Reserved.
+ *
+ *   6:0   elem_rxfifo[6:0]:     Number of elements in the linear RXFIFO (<=96)
+ *   \endcode
+ */
+#define	LINEAR_FIFO_STATUS0_BASE				((uint8_t)(0xE7)) /*!< Number of elements in the linear RX FIFO [6:0] (<=96) */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Calibration_Registers
+ * @{
+ */
+
+/** @defgroup RCO_VCO_CALIBR_IN2_Register
+ * @{
+ */
+
+/**
+ *  \brief RCO_VCO_CALIBR_IN2  registers
+ *  \code
+ *   Default value: 0x70
+ *   Read Write
+ *   7:4     RWT_IN[3:0]: RaWThermometric word value for the RCO [7:4]
+ *
+ *   3:0     RFB_IN[4:1]: ResistorFineBit word value for the RCO (first 4 bits)
+ *   \endcode
+ */
+#define	RCO_VCO_CALIBR_IN2_BASE					((uint8_t)0x6D) /*!< RaWThermometric word value for the RCO [7:4]; ResistorFineBit word value for the RCO [3:0] */
+
+/**
+ * @}
+ */
+
+/** @defgroup RCO_VCO_CALIBR_IN1_Register
+ * @{
+ */
+
+/**
+ *  \brief RCO_VCO_CALIBR_IN1  registers
+ *  \code
+ *   Default value: 0x48
+ *   Read Write
+ *
+ *   7     RFB_IN[0]: ResistorFineBit word value for the RCO (LSb)
+ *
+ *   6:0   VCO_CALIBR_TX[6:0]:  Word value for the VCO to be used in TX mode
+ *   \endcode
+ */
+#define	RCO_VCO_CALIBR_IN1_BASE					((uint8_t)0x6E) /*!< ResistorFineBit word value for the RCO [7]; Word value for the VCO to be used in TX mode  [6:0]*/
+
+/**
+ * @}
+ */
+
+/** @defgroup RCO_VCO_CALIBR_IN0_Register
+ * @{
+ */
+
+/**
+ *  \brief RCO_VCO_CALIBR_IN0  registers
+ *  \code
+ *   Default value: 0x48
+ *   Read Write
+ *
+ *   7     Reserved.
+ *
+ *   6:0   VCO_CALIBR_RX[6:0]:  Word value for the VCO to be used in RX mode
+ *   \endcode
+ */
+#define	RCO_VCO_CALIBR_IN0_BASE					((uint8_t)0x6F) /*!< Word value for the VCO to be used in RX mode [6:0] */
+
+/**
+ * @}
+ */
+
+/** @defgroup RCO_VCO_CALIBR_OUT1_Register
+ * @{
+ */
+
+/**
+ *  \brief RCO_VCO_CALIBR_OUT1  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:4   RWT_OUT[3:0]:    RWT word from internal RCO calibrator
+ *
+ *   3:0   RFB_OUT[4:1]:     RFB word from internal RCO calibrator (upper part)
+ *   \endcode
+ */
+#define	RCO_VCO_CALIBR_OUT1_BASE				((uint8_t)(0xE4)) /*!< RaWThermometric RWT word from internal RCO calibrator [7];
+                                                                                       ResistorFineBit RFB word from internal RCO oscillator [6:0] */
+/**
+ * @}
+ */
+
+/** @defgroup RCO_VCO_CALIBR_OUT0_Register
+ * @{
+ */
+
+/**
+ *  \brief RCO_VCO_CALIBR_OUT0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7     RFB_OUT[0]:    RFB word from internal RCO calibrator (last bit LSB)
+ *
+ *   6:0   VCO_CALIBR_DATA[6:0]:     Output word from internal VCO calibrator
+ *   \endcode
+ */
+#define	RCO_VCO_CALIBR_OUT0_BASE				((uint8_t)(0xE5)) /*!< ResistorFineBit RFB word from internal RCO oscillator [0];
+                                                                                       Output word from internal calibrator [6:0]; */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup AES_Registers
+ * @{
+ */
+
+/** @defgroup AES_KEY_IN_Register
+ * @{
+ */
+
+/**
+ *  \brief AES_KEY_INx  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   AES_KEY_INx[7:0]:  AES engine key input (total - 128 bits)
+ *   \endcode
+ */
+#define	AES_KEY_IN_15_BASE					((uint8_t)0x70) /*!< AES engine key input 15 */
+   
+#define	AES_KEY_IN_14_BASE					((uint8_t)0x71) /*!< AES engine key input 14 */
+
+#define	AES_KEY_IN_13_BASE					((uint8_t)0x72) /*!< AES engine key input 13 */
+
+#define	AES_KEY_IN_12_BASE					((uint8_t)0x73) /*!< AES engine key input 12 */
+
+#define	AES_KEY_IN_11_BASE					((uint8_t)0x74) /*!< AES engine key input 11 */
+
+#define	AES_KEY_IN_10_BASE					((uint8_t)0x75) /*!< AES engine key input 10 */
+
+#define	AES_KEY_IN_9_BASE					((uint8_t)0x76) /*!< AES engine key input 9 */
+
+#define	AES_KEY_IN_8_BASE					((uint8_t)0x77) /*!< AES engine key input 8 */
+
+#define	AES_KEY_IN_7_BASE					((uint8_t)0x78) /*!< AES engine key input 7 */
+
+#define	AES_KEY_IN_6_BASE					((uint8_t)0x79) /*!< AES engine key input 6 */
+
+#define	AES_KEY_IN_5_BASE					((uint8_t)0x7A) /*!< AES engine key input 5 */
+
+#define	AES_KEY_IN_4_BASE					((uint8_t)0x7B) /*!< AES engine key input 4 */
+
+#define	AES_KEY_IN_3_BASE					((uint8_t)0x7C) /*!< AES engine key input 3 */
+
+#define	AES_KEY_IN_2_BASE					((uint8_t)0x7D) /*!< AES engine key input 2 */
+
+#define	AES_KEY_IN_1_BASE					((uint8_t)0x7E) /*!< AES engine key input 1 */
+
+#define	AES_KEY_IN_0_BASE					((uint8_t)0x7F) /*!< AES engine key input 0 */
+
+/**
+ * @}
+ */
+
+/** @defgroup AES_DATA_IN_Register
+ * @{
+ */
+
+/**
+ *  \brief AES_DATA_INx  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   AES_DATA_INx[7:0]:  AES engine data input (total - 128 bits)
+ *   \endcode
+ */
+#define	AES_DATA_IN_15_BASE					((uint8_t)0x80) /*!< AES engine data input 15
+                                                                                     Take care: Address is in reverse order respect data numbering; eg.: 0x81 -> AES_data14[7:0] */
+#define	AES_DATA_IN_14_BASE					((uint8_t)0x81) /*!< AES engine data input 14 */
+
+#define	AES_DATA_IN_13_BASE					((uint8_t)0x82) /*!< AES engine data input 13 */
+
+#define	AES_DATA_IN_12_BASE					((uint8_t)0x83) /*!< AES engine data input 12 */
+
+#define	AES_DATA_IN_11_BASE					((uint8_t)0x84) /*!< AES engine data input 11 */
+
+#define	AES_DATA_IN_10_BASE					((uint8_t)0x85) /*!< AES engine data input 10 */
+
+#define	AES_DATA_IN_9_BASE					((uint8_t)0x86) /*!< AES engine data input 9 */
+
+#define	AES_DATA_IN_8_BASE					((uint8_t)0x87) /*!< AES engine data input 8 */
+
+#define	AES_DATA_IN_7_BASE					((uint8_t)0x88) /*!< AES engine data input 7 */
+
+#define	AES_DATA_IN_6_BASE					((uint8_t)0x89) /*!< AES engine data input 6 */
+
+#define	AES_DATA_IN_5_BASE					((uint8_t)0x8A) /*!< AES engine data input 5 */
+
+#define	AES_DATA_IN_4_BASE					((uint8_t)0x8B) /*!< AES engine data input 4 */
+
+#define	AES_DATA_IN_3_BASE					((uint8_t)0x8C) /*!< AES engine data input 3 */
+
+#define	AES_DATA_IN_2_BASE					((uint8_t)0x8D) /*!< AES engine data input 2 */
+
+#define	AES_DATA_IN_1_BASE					((uint8_t)0x8E) /*!< AES engine data input 1 */
+
+#define	AES_DATA_IN_0_BASE					((uint8_t)0x8F) /*!< AES engine data input 0 */
+
+/**
+ * @}
+ */
+
+/** @defgroup AES_DATA_OUT_Register
+ * @{
+ */
+
+/**
+ *  \brief AES_DATA_OUT[15:0]  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:0   AES_DATA_OUTx[7:0]:    AES engine data output (128 bits)
+ *   \endcode
+ */
+#define	AES_DATA_OUT_15_BASE					((uint8_t)(0xD4)) /*!< AES engine data output 15 */
+
+#define	AES_DATA_OUT_14_BASE					((uint8_t)(0xD5)) /*!< AES engine data output 14 */
+
+#define	AES_DATA_OUT_13_BASE					((uint8_t)(0xD6)) /*!< AES engine data output 13 */
+
+#define	AES_DATA_OUT_12_BASE					((uint8_t)(0xD7)) /*!< AES engine data output 12 */
+
+#define	AES_DATA_OUT_11_BASE					((uint8_t)(0xD8)) /*!< AES engine data output 11 */
+
+#define	AES_DATA_OUT_10_BASE					((uint8_t)(0xD9)) /*!< AES engine data output 10 */
+
+#define	AES_DATA_OUT_9_BASE					((uint8_t)(0xDA)) /*!< AES engine data output 9 */
+
+#define	AES_DATA_OUT_8_BASE					((uint8_t)(0xDB)) /*!< AES engine data output 8 */
+
+#define	AES_DATA_OUT_7_BASE					((uint8_t)(0xDC)) /*!< AES engine data output 7 */
+
+#define	AES_DATA_OUT_6_BASE					((uint8_t)(0xDD)) /*!< AES engine data output 6 */
+
+#define	AES_DATA_OUT_5_BASE					((uint8_t)(0xDE)) /*!< AES engine data output 5 */
+
+#define	AES_DATA_OUT_4_BASE					((uint8_t)(0xDF)) /*!< AES engine data output 4 */
+
+#define	AES_DATA_OUT_3_BASE					((uint8_t)(0xE0)) /*!< AES engine data output 3 */
+
+#define	AES_DATA_OUT_2_BASE					((uint8_t)(0xE1)) /*!< AES engine data output 2 */
+
+#define	AES_DATA_OUT_1_BASE					((uint8_t)(0xE2)) /*!< AES engine data output 1 */
+
+#define	AES_DATA_OUT_0_BASE					((uint8_t)(0xE3)) /*!< AES engine data output 0 */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRQ_Registers
+ * @{
+ */
+
+/** @defgroup IRQ_MASK0_Register
+ * @{
+ */
+
+/**
+ *  \brief IRQ_MASK0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   INT_MASK0:  IRQ mask, if the correspondent bit is set and IRQ can be generated (according to the next table)
+ *
+ *            Bit |     Events Group Interrupt Event
+ *           -------------------------------------------------------
+ *            0   |       RX data ready
+ *            1   |       RX data discarded (upon filtering)
+ *            2   |       TX data sent
+ *            3   |       Max re-TX reached
+ *            4   |       CRC error
+ *            5   |       TX FIFO underflow/overflow error
+ *            6   |       RX FIFO underflow/overflow error
+ *            7   |       TX FIFO almost full
+ *    \endcode
+ */
+
+
+#define	IRQ_MASK0_BASE						((uint8_t)0x93) /*!< IRQ_MASK is split into 4 registers*/
+
+#define IRQ_MASK0_RX_DATA_READY					((uint8_t)0x01) /*!< IRQ: RX data ready */
+#define IRQ_MASK0_RX_DATA_DISC					((uint8_t)0x02) /*!< IRQ: RX data discarded (upon filtering) */
+#define IRQ_MASK0_TX_DATA_SENT					((uint8_t)0x04) /*!< IRQ: TX data sent */
+#define IRQ_MASK0_MAX_RE_TX_REACH				((uint8_t)0x08) /*!< IRQ: Max re-TX reached */
+#define IRQ_MASK0_CRC_ERROR					((uint8_t)0x10) /*!< IRQ: CRC error */
+#define IRQ_MASK0_TX_FIFO_ERROR					((uint8_t)0x20) /*!< IRQ: TX FIFO underflow/overflow error */
+#define IRQ_MASK0_RX_FIFO_ERROR					((uint8_t)0x40) /*!< IRQ: RX FIFO underflow/overflow error */
+#define IRQ_MASK0_TX_FIFO_ALMOST_FULL				((uint8_t)0x80) /*!< IRQ: TX FIFO almost full */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRQ_MASK1_Register
+ * @{
+ */
+
+/**
+ *  \brief IRQ_MASK1  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   INT_MASK1:  IRQ mask, if the correspondent bit is set and IRQ can be generated (according to the next table)
+ *
+ *            Bit |     Events Group Interrupt Event
+ *           -------------------------------------------------------
+ *            8   |       TX FIFO almost empty
+ *            9   |       RX FIFO almost full
+ *            10  |       RX FIFO almost empty
+ *            11  |       Max number of back-off during CCA
+ *            12  |       Valid preamble detected
+ *            13  |       Sync word detected
+ *            14  |       RSSI above threshold (Carrier Sense)
+ *            15  |       Wake-up timeout in LDCR mode13
+ *     \endcode
+ */
+
+#define	IRQ_MASK1_BASE						((uint8_t)0x92) /*!< IRQ_MASK is split into 4 registers*/
+
+#define IRQ_MASK1_TX_FIFO_ALMOST_EMPTY				((uint8_t)0x01) /*!< IRQ: TX FIFO almost empty */
+#define IRQ_MASK1_RX_FIFO_ALMOST_FULL				((uint8_t)0x02) /*!< IRQ: RX FIFO almost full */
+#define IRQ_MASK1_RX_FIFO_ALMOST_EMPTY				((uint8_t)0x04) /*!< IRQ: RX FIFO almost empty  */
+#define IRQ_MASK1_MAX_BO_CCA_REACH				((uint8_t)0x08) /*!< IRQ: Max number of back-off during CCA */
+#define IRQ_MASK1_VALID_PREAMBLE				((uint8_t)0x10) /*!< IRQ: Valid preamble detected */
+#define IRQ_MASK1_VALID_SYNC					((uint8_t)0x20) /*!< IRQ: Sync word detected */
+#define IRQ_MASK1_RSSI_ABOVE_TH					((uint8_t)0x40) /*!< IRQ: RSSI above threshold */
+#define IRQ_MASK1_WKUP_TOUT_LDC					((uint8_t)0x80) /*!< IRQ: Wake-up timeout in LDC mode */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRQ_MASK2_Register
+ * @{
+ */
+
+/**
+ *  \brief IRQ_MASK2  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   INT_MASK2:  IRQ mask, if the correspondent bit is set and IRQ can be generated (according to the next table)
+ *
+ *            Bit |     Events Group Interrupt Event
+ *           -------------------------------------------------------
+ *            16  |       READY state in steady condition14
+ *            17  |       STANDBY state switching in progress
+ *            18  |       Low battery level
+ *            19  |       Power-On reset
+ *            20  |       Brown-Out event
+ *            21  |       LOCK state in steady condition
+ *            22  |       PM start-up timer expiration
+ *            23  |       XO settling timeout
+ *   \endcode
+ */
+#define	IRQ_MASK2_BASE						((uint8_t)0x91) /*!< IRQ_MASK is split into 4 registers*/
+
+#define IRQ_MASK2_READY						((uint8_t)0x01) /*!< IRQ: READY state */
+#define IRQ_MASK2_STANDBY_DELAYED				((uint8_t)0x02) /*!< IRQ: STANDBY state after MCU_CK_CONF_CLOCK_TAIL_X clock cycles */
+#define IRQ_MASK2_LOW_BATT_LVL					((uint8_t)0x04) /*!< IRQ: Battery level below threshold*/
+#define IRQ_MASK2_POR						((uint8_t)0x08) /*!< IRQ: Power On Reset */
+#define IRQ_MASK2_BOR						((uint8_t)0x10) /*!< IRQ: Brown out event (both accurate and inaccurate)*/
+#define IRQ_MASK2_LOCK						((uint8_t)0x20) /*!< IRQ: LOCK state */
+#define IRQ_MASK2_PM_COUNT_EXPIRED				((uint8_t)0x40) /*!< IRQ: only for debug; Power Management startup timer expiration (see reg PM_START_COUNTER, 0xB5) */
+#define IRQ_MASK2_XO_COUNT_EXPIRED				((uint8_t)0x80) /*!< IRQ: only for debug; Crystal oscillator settling time counter expired */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRQ_MASK3_Register
+ * @{
+ */
+
+/**
+ *  \brief IRQ_MASK3  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   INT_MASK3:  IRQ mask, if the correspondent bit is set and IRQ can be generated (according to the next table)
+ *
+ *            Bit |     Events Group Interrupt Event
+ *           -------------------------------------------------------
+ *            24  |       SYNTH locking timeout
+ *            25  |       SYNTH calibration start-up time
+ *            26  |       SYNTH calibration timeout
+ *            27  |       TX circuitry start-up time
+ *            28  |       RX circuitry start-up time
+ *            29  |       RX operation timeout
+ *            30  |       Others AES End–of –Operation
+ *            31  |       Reserved
+ *   \endcode
+ */
+#define	IRQ_MASK3_BASE						((uint8_t)0x90) /*!< IRQ_MASK is split into 4 registers*/
+
+#define IRQ_MASK3_SYNTH_LOCK_TIMEOUT			        ((uint8_t)0x01) /*!< IRQ: only for debug; LOCK state timeout */
+#define IRQ_MASK3_SYNTH_LOCK_STARTUP			        ((uint8_t)0x02) /*!< IRQ: only for debug; see CALIBR_START_COUNTER */
+#define IRQ_MASK3_SYNTH_CAL_TIMEOUT				((uint8_t)0x04) /*!< IRQ: only for debug; SYNTH calibration timeout */
+#define IRQ_MASK3_TX_START_TIME					((uint8_t)0x08) /*!< IRQ: only for debug; TX circuitry startup time; see TX_START_COUNTER */
+#define IRQ_MASK3_RX_START_TIME					((uint8_t)0x10) /*!< IRQ: only for debug; RX circuitry startup time; see TX_START_COUNTER */
+#define IRQ_MASK3_RX_TIMEOUT					((uint8_t)0x20) /*!< IRQ: RX operation timeout */
+#define IRQ_MASK3_AES_END					((uint8_t)0x40) /*!< IRQ: AES End of operation */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup IRQ_STATUS0_Register
+ * @{
+ */
+
+/**
+ *  \brief IRQ_STATUS0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   INT_STATUS0:  IRQ status, if the correspondent bit is set and IRQ has been generated (according to the next table)
+ *
+ *            Bit |     Events Group Interrupt Event
+ *           -------------------------------------------------------
+ *            0   |       RX data ready
+ *            1   |       RX data discarded (upon filtering)
+ *            2   |       TX data sent
+ *            3   |       Max re-TX reached
+ *            4   |       CRC error
+ *            5   |       TX FIFO underflow/overflow error
+ *            6   |       RX FIFO underflow/overflow error
+ *            7   |       TX FIFO almost full
+ *   \endcode
+ */
+
+#define IRQ_STATUS0_BASE					((uint8_t)(0xFD)) /*!< IRQ Events(RR, split into 4 registers) */
+
+#define IRQ_STATUS0_SYNTH_LOCK_TIMEOUT				((uint8_t)(0x01)) /*!< IRQ: LOCK state timeout */
+#define IRQ_STATUS0_SYNTH_LOCK_STARTUP				((uint8_t)(0x02)) /*!< IRQ: only for debug; see CALIBR_START_COUNTER */
+#define IRQ_STATUS0_SYNTH_CAL_TIMEOUT				((uint8_t)(0x04)) /*!< IRQ: SYNTH locking timeout */
+#define IRQ_STATUS0_TX_START_TIME				((uint8_t)(0x08)) /*!< IRQ: only for debug; TX circuitry startup time; see TX_START_COUNTER */
+#define IRQ_STATUS0_RX_START_TIME				((uint8_t)(0x10)) /*!< IRQ: only for debug; RX circuitry startup time; see TX_START_COUNTER */
+#define IRQ_STATUS0_RX_TIMEOUT					((uint8_t)(0x20)) /*!< IRQ: RX operation timeout expiration */
+#define IRQ_STATUS0_AES_END					((uint8_t)(0x40)) /*!< IRQ: AES End of operation */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRQ_STATUS1_Register
+ * @{
+ */
+
+/**
+ *  \brief IRQ_STATUS1  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   INT_STATUS1:  IRQ status, if the correspondent bit is set and IRQ has been generated (according to the next table)
+ *
+ *            Bit |     Events Group Interrupt Event
+ *           -------------------------------------------------------
+ *            8   |       TX FIFO almost empty
+ *            9   |       RX FIFO almost full
+ *            10  |       RX FIFO almost empty
+ *            11  |       Max number of back-off during CCA
+ *            12  |       Valid preamble detected
+ *            13  |       Sync word detected
+ *            14  |       RSSI above threshold (Carrier Sense)
+ *            15  |       Wake-up timeout in LDCR mode13
+ *   \endcode
+ */
+
+#define IRQ_STATUS1_BASE					((uint8_t)(0xFC)) /*!< IRQ Events(RR, split into 4 registers) */
+
+#define IRQ_STATUS1_READY					((uint8_t)(0x01)) /*!< IRQ: READY state in steady condition*/
+#define IRQ_STATUS1_STANDBY_DELAYED				((uint8_t)(0x02)) /*!< IRQ: STANDBY state after MCU_CK_CONF_CLOCK_TAIL_X clock cycles */
+#define IRQ_STATUS1_LOW_BATT_LVL				((uint8_t)(0x04)) /*!< IRQ: Battery level below threshold*/
+#define IRQ_STATUS1_POR						((uint8_t)(0x08)) /*!< IRQ: Power On Reset */
+#define IRQ_STATUS1_BOR						((uint8_t)(0x10)) /*!< IRQ: Brown out event (both accurate and inaccurate)*/
+#define IRQ_STATUS1_LOCK					((uint8_t)(0x20)) /*!< IRQ: LOCK state in steady condition */
+#define IRQ_STATUS1_PM_COUNT_EXPIRED				((uint8_t)(0x40)) /*!< IRQ: Power Management startup timer expiration (see reg PM_START_COUNTER, 0xB5) */
+#define IRQ_STATUS1_XO_COUNT_EXPIRED				((uint8_t)(0x80)) /*!< IRQ: Crystal oscillator settling time counter expired */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRQ_STATUS2_Register
+ * @{
+ */
+
+/**
+ *  \brief IRQ_STATUS2  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   INT_STATUS2:  IRQ status, if the correspondent bit is set and IRQ has been generated (according to the next table)
+ *
+ *            Bit |     Events Group Interrupt Event
+ *           -------------------------------------------------------
+ *            16  |       READY state in steady condition14
+ *            17  |       STANDBY state switching in progress
+ *            18  |       Low battery level
+ *            19  |       Power-On reset
+ *            20  |       Brown-Out event
+ *            21  |       LOCK state in steady condition
+ *            22  |       PM start-up timer expiration
+ *            23  |       XO settling timeout
+ *   \endcode
+ */
+
+#define IRQ_STATUS2_BASE					((uint8_t)0xFB) /*!< IRQ Events(RR, split into 4 registers) */
+
+#define IRQ_STATUS2_TX_FIFO_ALMOST_EMPTY			((uint8_t)0x01) /*!< IRQ: TX FIFO almost empty */
+#define IRQ_STATUS2_RX_FIFO_ALMOST_FULL				((uint8_t)0x02) /*!< IRQ: RX FIFO almost full */
+#define IRQ_STATUS2_RX_FIFO_ALMOST_EMPTY			((uint8_t)0x04) /*!< IRQ: RX FIFO almost empty */
+#define IRQ_STATUS2_MAX_BO_CCA_REACH				((uint8_t)0x08) /*!< IRQ: Max number of back-off during CCA */
+#define IRQ_STATUS2_VALID_PREAMBLE				((uint8_t)0x10) /*!< IRQ: Valid preamble detected */
+#define IRQ_STATUS2_VALID_SYNC					((uint8_t)0x20) /*!< IRQ: Sync word detected */
+#define IRQ_STATUS2_RSSI_ABOVE_TH				((uint8_t)(0x40)) /*!< IRQ: RSSI above threshold */
+#define IRQ_STATUS2_WKUP_TOUT_LDC				((uint8_t)(0x80)) /*!< IRQ: Wake-up timeout in LDC mode */
+
+/**
+ * @}
+ */
+
+/** @defgroup IRQ_STATUS3_Register
+ * @{
+ */
+
+/**
+ *  \brief IRQ_STATUS3  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read Write
+ *
+ *   7:0   INT_STATUS3:  IRQ status, if the correspondent bit is set and IRQ has been generated (according to the next table)
+ *
+ *            Bit |     Events Group Interrupt Event
+ *           -------------------------------------------------------
+ *            24  |       SYNTH locking timeout
+ *            25  |       SYNTH calibration start-up time
+ *            26  |       SYNTH calibration timeout
+ *            27  |       TX circuitry start-up time
+ *            28  |       RX circuitry start-up time
+ *            29  |       RX operation timeout
+ *            30  |       Others AES End–of –Operation
+ *            31  |       Reserved
+ *    \endcode
+ */
+#define IRQ_STATUS3_BASE					((uint8_t)0xFA) /*!< IRQ Events(RR, split into 4 registers) */
+
+#define IRQ_STATUS3_RX_DATA_READY				((uint8_t)0x01) /*!< IRQ: RX data ready */
+#define IRQ_STATUS3_RX_DATA_DISC				((uint8_t)0x02) /*!< IRQ: RX data discarded (upon filtering) */
+#define IRQ_STATUS3_TX_DATA_SENT				((uint8_t)0x04) /*!< IRQ: TX data sent */
+#define IRQ_STATUS3_MAX_RE_TX_REACH				((uint8_t)0x08) /*!< IRQ: Max re-TX reached */
+#define IRQ_STATUS3_CRC_ERROR					((uint8_t)0x10) /*!< IRQ: CRC error */
+#define IRQ_STATUS3_TX_FIFO_ERROR				((uint8_t)0x20) /*!< IRQ: TX FIFO underflow/overflow error */
+#define IRQ_STATUS3_RX_FIFO_ERROR				((uint8_t)0x40) /*!< IRQ: RX FIFO underflow/overflow error */
+#define IRQ_STATUS3_TX_FIFO_ALMOST_FULL				((uint8_t)0x80) /*!< IRQ: TX FIFO almost full */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MC_STATE_Registers
+ * @{
+ */
+
+/** @defgroup MC_STATE1_Register
+ * @{
+ */
+
+/**
+ *  \brief MC_STATE1  registers
+ *  \code
+ *   Default value: 0x50
+ *   Read
+ *
+ *   7:4     Reserved.
+ *
+ *   3       ANT_SELECT:  Currently selected antenna
+ *
+ *   2       TX_FIFO_Full:     1 - TX FIFO is full
+ *
+ *   1       RX_FIFO_Empty:    1 - RX FIFO is empty
+ *
+ *   0       ERROR_LOCK:       1 - RCO calibrator error
+ *   \endcode
+ */
+#define	MC_STATE1_BASE						((uint8_t)(0xC0)) /*!< MC_STATE1 register address (see the SpiritStatus struct */
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup MC_STATE0_Register
+ * @{
+ */
+
+/**
+ *  \brief MC_STATE0  registers
+ *  \code
+ *   Default value: 0x00
+ *   Read
+ *
+ *   7:1     STATE[6:0]: Current MC state.
+ *
+ *      REGISTER VALUE |         STATE
+ *   --------------------------------------------
+ *            0x40     |         STANDBY
+ *            0x36     |         SLEEP
+ *            0x03     |         READY
+ *            0x3B     |         PM setup
+ *            0x23     |         XO settling
+ *            0x53     |         SYNTH setup
+ *            0x1F     |         PROTOCOL
+ *            0x4F     |         SYNTH calibration
+ *            0x0F     |         LOCK
+ *            0x33     |         RX
+ *            0x5F     |         TX
+ *
+ *   0       XO_ON:       1 - XO is operating
+ *   \endcode
+ */
+#define	MC_STATE0_BASE						((uint8_t)(0xC1)) /*!< MC_STATE0 register address. In this version ALL existing states have been inserted
+                                                                                       and are still to be verified */
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+   
+/** @defgroup Engineering-Test_Registers
+ * @{
+ */
+
+#define	SYNTH_CONFIG1_BASE					((uint8_t)(0x9E)) /*!< Synthesizier registers: M, A, K data sync on positive/negative clock edges [4],
+                                                                                       Enable Linearization of the charge pump [3], split time 1.75/3.45ns [2], VCO calibration window 16,32,64,128 clock cycles [1:0]*/
+#define	SYNTH_CONFIG0_BASE					((uint8_t)(0x9F)) /*!< Enable DSM randomizer [7], Window width 1.2-7.5ns (Down-up) of lock detector*/
+#define	VCOTH_BASE						((uint8_t)(0xA0)) /*!< Controls the threshold frequency between VCO low and VCO high [7:0]
+                                                                                       VCOth frequency=2*fXO*(96+VCO_TH/16), fmin=4992 MHz, fmax=5820 MHz*/
+#define	PM_CONFIG2_BASE						((uint8_t)(0xA4)) /*!< Enables high current buffer on Temperature sensor, sets SMPS options */
+#define	PM_CONFIG1_BASE						((uint8_t)(0xA5)) /*!< Set SMPS options */
+#define	PM_CONFIG0_BASE						((uint8_t)(0xA6)) /*!< Set SMPS options */
+#define	VCO_CONFIG_BASE						((uint8_t)(0xA1)) /*!< Set VCO current [5:2]part and [1:0] part */
+#define	XO_CONFIG_BASE						((uint8_t)(0xA7)) /*!< Clock management options from XO to digital part */
+
+#define	XO_RCO_TEST_BASE					((uint8_t)(0xB4)) /*!< Test of XO and RCO */
+
+/**
+ * @}
+ */
+
+
+/** @addtogroup Commands
+ * @{
+ */
+
+#define	COMMAND_TX						((uint8_t)(0x60)) /*!< Start to transmit; valid only from READY */
+#define	COMMAND_RX						((uint8_t)(0x61)) /*!< Start to receive; valid only from READY */
+#define	COMMAND_READY					        ((uint8_t)(0x62)) /*!< Go to READY; valid only from STANDBY or SLEEP or LOCK */
+#define	COMMAND_STANDBY					        ((uint8_t)(0x63)) /*!< Go to STANDBY; valid only from READY */
+#define	COMMAND_SLEEP					        ((uint8_t)(0x64)) /*!< Go to SLEEP; valid only from READY */
+#define	COMMAND_LOCKRX					        ((uint8_t)(0x65)) /*!< Go to LOCK state by using the RX configuration of the synth; valid only from READY */
+#define	COMMAND_LOCKTX					        ((uint8_t)(0x66)) /*!< Go to LOCK state by using the TX configuration of the synth; valid only from READY */
+#define	COMMAND_SABORT					        ((uint8_t)(0x67)) /*!< Force exit form TX or RX states and go to READY state; valid only from TX or RX */
+#define	COMMAND_LDC_RELOAD				        ((uint8_t)(0x68)) /*!< LDC Mode: Reload the LDC timer with the value stored in the  LDC_PRESCALER / COUNTER
+                                                                                       registers; valid from all states  */
+#define	COMMAND_SEQUENCE_UPDATE			                ((uint8_t)(0x69)) /*!< Autoretransmission: Reload the Packet sequence counter with the value stored in the PROTOCOL[2] register
+                                                                                       valid from all states */
+#define	COMMAND_AES_ENC					        ((uint8_t)(0x6A)) /*!< AES: Start the encryption routine; valid from all states; valid from all states */
+#define	COMMAND_AES_KEY					        ((uint8_t)(0x6B)) /*!< AES: Start the procedure to compute the key for the decryption; valid from all states */
+#define	COMMAND_AES_DEC					        ((uint8_t)(0x6C)) /*!< AES: Start the decryption routine using the current key; valid from all states */
+#define	COMMAND_AES_KEY_DEC				        ((uint8_t)(0x6D)) /*!< AES: Compute the key and start the decryption; valid from all states */
+#define	COMMAND_SRES					        ((uint8_t)(0x70)) /*!< Reset of all digital part, except SPI registers */
+#define	COMMAND_FLUSHRXFIFO				        ((uint8_t)(0x71)) /*!< Clean the RX FIFO; valid from all states */
+#define	COMMAND_FLUSHTXFIFO				        ((uint8_t)(0x72)) /*!< Clean the TX FIFO; valid from all states */
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Timer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Timer.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,239 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Timer.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT timers.
+ * @details
+ *
+ * This module provides API to configure the Spirit timing mechanisms.
+ * They allow the user to set the timer registers using raw values or
+ * compute them since the desired timer value is expressed in ms.
+ * Moreover the management of the Spirit LDCR mode can be done using
+ * these API.
+ *
+ * <b>Example:</b>
+ * @code
+ *   ...
+ *
+ *   SpiritTimerSetRxTimeoutMs(50.0);
+ *   SpiritTimerSetWakeUpTimerMs(150.0);
+ *
+ *   // IRQ configuration for RX_TIMEOUT and WAKEUP_TIMEOUT
+ *   ...
+ *
+ *   SpiritTimerLdcrMode(S_ENABLE);
+ *
+ *   ...
+ *
+ * @endcode
+ *
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT1_TIMER_H
+#define __SPIRIT1_TIMER_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "SPIRIT_Regs.h"
+#include "SPIRIT_Types.h"
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_Timer               Timer
+ * @brief Configuration and management of SPIRIT Timers.
+ * @details See the file <i>@ref SPIRIT_Timer.h</i> for more details.
+ * @{
+ */
+
+
+/**
+ * @defgroup Timer_Exported_Types       Timer Exported Types
+ * @{
+ */
+
+/**
+ * @brief  All the possible RX timeout stop conditions enumeration.
+ */
+typedef enum{
+
+     NO_TIMEOUT_STOP = 0x00,                /*!< Timeout never stopped */
+     TIMEOUT_ALWAYS_STOPPED = 0x08,         /*!< Timeout always stopped (default) */
+     RSSI_ABOVE_THRESHOLD = 0x04,           /*!< Timeout stopped on RSSI above threshold */
+     SQI_ABOVE_THRESHOLD = 0x02,            /*!< Timeout stopped on SQI above threshold */
+     PQI_ABOVE_THRESHOLD = 0x01,            /*!< Timeout stopped on PQI above threshold */
+     RSSI_AND_SQI_ABOVE_THRESHOLD = 0x06,   /*!< Timeout stopped on both RSSI and SQI above threshold */
+     RSSI_AND_PQI_ABOVE_THRESHOLD = 0x05,   /*!< Timeout stopped on both RSSI and PQI above threshold */
+     SQI_AND_PQI_ABOVE_THRESHOLD = 0x03,    /*!< Timeout stopped on both SQI and PQI above threshold */
+     ALL_ABOVE_THRESHOLD = 0x07,            /*!< Timeout stopped only if RSSI, SQI and PQI are above threshold */
+     RSSI_OR_SQI_ABOVE_THRESHOLD = 0x0E,    /*!< Timeout stopped if one between RSSI or SQI are above threshold */
+     RSSI_OR_PQI_ABOVE_THRESHOLD = 0x0D,    /*!< Timeout stopped if one between RSSI or PQI are above threshold */
+     SQI_OR_PQI_ABOVE_THRESHOLD = 0x0B,     /*!< Timeout stopped if one between SQI or PQI are above threshold */
+     ANY_ABOVE_THRESHOLD = 0x0F             /*!< Timeout stopped if one among RSSI, SQI or SQI are above threshold */
+
+} RxTimeoutStopCondition;
+
+
+#define IS_RX_TIMEOUT_STOP_CONDITION(COND)  ( COND == NO_TIMEOUT_STOP || \
+                                                COND == TIMEOUT_ALWAYS_STOPPED || \
+                                                COND == RSSI_ABOVE_THRESHOLD || \
+                                                COND == SQI_ABOVE_THRESHOLD || \
+                                                COND == PQI_ABOVE_THRESHOLD || \
+                                                COND == RSSI_AND_SQI_ABOVE_THRESHOLD || \
+                                                COND == RSSI_AND_PQI_ABOVE_THRESHOLD || \
+                                                COND == SQI_AND_PQI_ABOVE_THRESHOLD || \
+                                                COND == ALL_ABOVE_THRESHOLD || \
+                                                COND == RSSI_OR_SQI_ABOVE_THRESHOLD || \
+                                                COND == RSSI_OR_PQI_ABOVE_THRESHOLD || \
+                                                COND == SQI_OR_PQI_ABOVE_THRESHOLD || \
+                                                COND == ANY_ABOVE_THRESHOLD )
+
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Timer_Exported_Constants   Timer Exported Constants
+ * @{
+ */
+
+/**
+ * @brief  It represents the Time Step for RX_Timeout timer in case of 24 MHz Crystal, expressed in us.
+ *         It is equal to 1210/(24*10^6). With this time step it is possible to fix the RX_Timeout to
+ *         a minimum value of 50.417us to a maximum value of about 3.278 s.
+ *         Remember that it is possible to have infinite RX_Timeout writing 0 in the RX_Timeout_Counter and/or RX_Timeout_Prescaler registers.
+ */
+#define      RX_TCLK_24MHz           50.417f
+#define      IS_RX_TIMEOUT_24MHz(TIMEOUT)        (TIMEOUT*1000)>=RX_TCLK_24MHz
+
+/**
+ * @brief  It represents the Time Step for RX_Timeout timer in case of 26 MHz Crystal, expressed in us.
+ *         It is equal to 1210/(26*10^6). With this time step it is possible to fix the RX_Timeout to
+ *         a minimum value of 46.538us to a maximum value of about 3.026 s.
+ *         Remember that it is possible to have infinite RX_Timeout writing 0 in the RX_Timeout_Counter register.
+ */
+#define      RX_TCLK_26MHz           46.538f
+#define      IS_RX_TIMEOUT_26MHz(TIMEOUT)        (TIMEOUT*1000)>=RX_TCLK_26MHz
+
+/**
+ * @brief  It represents the Time Step for RX_Wakeup timer expressed in us. This timer is based on RCO (about 34.7 kHZ).
+ *         With this time step it is possible to fix the Wakeup_Timeout to a minimum value of 28.818us to a maximum
+ *         value of about 1.888 s.
+ */
+#define      WAKEUP_TCLK            28.818f
+#define      IS_WKUP_TIMEOUT(TIMEOUT)        (TIMEOUT*1000)>=WAKEUP_TCLK
+
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Timer_Exported_Macros              Timer Exported Macros
+ * @{
+ */
+
+#define SET_INFINITE_RX_TIMEOUT()     SpiritTimerSetRxTimeoutCounter(0)
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Timer_Exported_Functions           Timer Exported Functions
+ * @{
+ */
+
+void SpiritTimerLdcrMode(SpiritFunctionalState xNewState);
+void SpiritTimerLdcrAutoReload(SpiritFunctionalState xNewState);
+SpiritFunctionalState SpiritTimerLdcrGetAutoReload(void);
+void SpiritTimerSetRxTimeout(uint8_t cCounter , uint8_t cPrescaler);
+void SpiritTimerSetRxTimeoutMs(float fDesiredMsec);
+void SpiritTimerSetRxTimeoutCounter(uint8_t cCounter);
+void SpiritTimerSetRxTimeoutPrescaler(uint8_t cPrescaler);
+void SpiritTimerGetRxTimeout(float* pfTimeoutMsec, uint8_t* pcCounter , uint8_t* pcPrescaler);
+void SpiritTimerSetWakeUpTimer(uint8_t cCounter , uint8_t cPrescaler);
+void SpiritTimerSetWakeUpTimerMs(float fDesiredMsec);
+void SpiritTimerSetWakeUpTimerCounter(uint8_t cCounter);
+void SpiritTimerSetWakeUpTimerPrescaler(uint8_t cPrescaler);
+void SpiritTimerSetWakeUpTimerReloadMs(float fDesiredMsec);
+void SpiritTimerGetWakeUpTimer(float* pfWakeUpMsec, uint8_t* pcCounter , uint8_t* pcPrescaler);
+void SpiritTimerSetWakeUpTimerReload(uint8_t cCounter , uint8_t cPrescaler);
+void SpiritTimerSetWakeUpTimerReloadCounter(uint8_t cCounter);
+void SpiritTimerSetWakeUpTimerReloadPrescaler(uint8_t cPrescaler);
+void SpiritTimerGetWakeUpTimerReload(float* pfWakeUpReloadMsec, uint8_t* pcCounter , uint8_t* pcPrescaler);
+void SpiritTimerComputeWakeUpValues(float fDesiredMsec , uint8_t* pcCounter , uint8_t* pcPrescaler);
+void SpiritTimerComputeRxTimeoutValues(float fDesiredMsec , uint8_t* pcCounter , uint8_t* pcPrescaler);
+void SpiritTimerSetRxTimeoutStopCondition(RxTimeoutStopCondition xStopCondition);
+void SpiritTimerReloadStrobe(void);
+uint16_t SpiritTimerGetRcoFrequency(void);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Types.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Types.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,276 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Types.h
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Header file for SPIRIT types.
+ * @details
+ *
+ * This module provide some types definitions which will be used in
+ * all the modules of this library. Here is defined also the global
+ * variable @ref g_xStatus which contains the status of Spirit and
+ * is updated every time an SPI transaction occurs.
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __SPIRIT_GENERICTYPES_H
+#define __SPIRIT_GENERICTYPES_H
+
+
+/* Includes ------------------------------------------------------------------*/
+
+/* Include all integer types definitions */
+#include <stdint.h>
+#include <stdio.h>
+#include "SPIRIT_Regs.h"
+
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @defgroup SPIRIT_Types       Types
+ * @brief Module for SPIRIT types definition.
+ * * @details See the file <i>@ref SPIRIT_Types.h</i> for more details.
+ * @{
+ */
+
+/**
+ * @defgroup Types_Exported_Types       Types Exported Types
+ * @{
+ */
+
+/**
+ * @brief  Spirit Functional state. Used to enable or disable a specific option.
+ */
+typedef enum
+{
+  S_DISABLE = 0,
+  S_ENABLE = !S_DISABLE
+
+} SpiritFunctionalState;
+
+#define IS_SPIRIT_FUNCTIONAL_STATE(STATE)   (STATE == S_DISABLE || STATE == S_ENABLE)
+
+/**
+ * @brief  Spirit Flag status. Used to control the state of a flag.
+ */
+typedef enum
+{
+  S_RESET = 0,
+  S_SET = !S_RESET
+
+} SpiritFlagStatus;
+
+#define IS_SPIRIT_FLAG_STATUS(STATUS)   (STATUS == S_RESET || STATUS == S_SET)
+
+
+/**
+ * @brief  boolean type enumeration.
+ */
+typedef enum
+{
+  S_FALSE = 0,
+  S_TRUE  = !S_FALSE
+
+} SpiritBool;
+
+
+/**
+ * @brief  SPIRIT States enumeration.
+ */
+typedef enum
+{
+  MC_STATE_STANDBY           =0x40,	/*!< STANDBY */
+  MC_STATE_SLEEP             =0x36,	/*!< SLEEP */
+  MC_STATE_READY             =0x03,	/*!< READY */
+  MC_STATE_PM_SETUP          =0x3D,	/*!< PM_SETUP */
+  MC_STATE_XO_SETTLING       =0x23,	/*!< XO_SETTLING */
+  MC_STATE_SYNTH_SETUP       =0x53,	/*!< SYNT_SETUP */
+  MC_STATE_PROTOCOL          =0x1F,	/*!< PROTOCOL */
+  MC_STATE_SYNTH_CALIBRATION =0x4F,	/*!< SYNTH */
+  MC_STATE_LOCK              =0x0F,	/*!< LOCK */
+  MC_STATE_RX                =0x33,	/*!< RX */
+  MC_STATE_TX                =0x5F	/*!< TX */
+
+} SpiritState;
+
+
+
+/**
+ * @brief SPIRIT Status. This definition represents the single field of the SPIRIT
+ *        status returned on each SPI transaction, equal also to the MC_STATE registers.
+ *        This field-oriented structure allows user to address in simple way the single
+ *        field of the SPIRIT status.
+ *        The user shall define a variable of SpiritStatus type to access on SPIRIT status fields.
+ * @note  The fields order in the structure depends on used endianness (little or big
+ *        endian). The actual definition is valid ONLY for LITTLE ENDIAN mode. Be sure to
+ *        change opportunely the fields order when use a different endianness.
+ */
+
+typedef struct
+{
+  uint8_t XO_ON:1;		/*!< This one bit field notifies if XO is operating
+  	  	  	  	     (XO_ON is 1) or not (XO_On is 0) */
+  SpiritState MC_STATE: 7;	/*!< This 7 bits field indicates the state of the
+   	   	   	   	     Main Controller of SPIRIT. The possible states
+   	   	   	   	     and their corresponding values are defined in
+   	   	   	   	     @ref SpiritState */
+  uint8_t ERROR_LOCK: 1;       /*!< This one bit field notifies if there is an
+   	   	   	   	     error on RCO calibration (ERROR_LOCK is 1) or
+   	   	   	   	     not (ERROR_LOCK is 0) */
+  uint8_t RX_FIFO_EMPTY: 1;    /*!< This one bit field notifies if RX FIFO is empty
+   	   	   	   	     (RX_FIFO_EMPTY is 1) or not (RX_FIFO_EMPTY is 0) */
+  uint8_t TX_FIFO_FULL: 1;	/*!< This one bit field notifies if TX FIFO is full
+  	  	  	  	     (TX_FIFO_FULL is 1) or not (TX_FIFO_FULL is 0) */
+  uint8_t ANT_SELECT: 1;       /*!< This one bit field notifies the currently selected
+   	   	   	   	     antenna */
+  uint8_t : 4;			/*!< This 4 bits field are reserved and equal to 5 */
+
+}SpiritStatus;
+
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Types_Exported_Constants   Types Exported Constants
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup Types_Exported_Variables   Types Exported Variables
+ * @{
+ */
+
+extern volatile SpiritStatus g_xStatus;
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup Types_Exported_Macros              Types Exported Macros
+ * @{
+ */
+
+#ifdef  SPIRIT_USE_FULL_ASSERT
+ /**
+   * @brief  The s_assert_param macro is used for function's parameters check.
+   * @param  expr If expr is false, it calls assert_failed function which reports
+   *         the name of the source file and the source line number of the call
+   *         that failed. If expr is true, it returns no value.
+   * @retval None
+   */
+  #define s_assert_param(expr) ((expr) ? (void)0 : s_assert_failed((uint8_t *)__FILE__, __LINE__))
+  void s_assert_failed(uint8_t* file, uint32_t line);
+#elif  SPIRIT_USE_VCOM_ASSERT
+  /**
+   * @brief  The s_assert_param macro is used for function's parameters check.
+   * @param  expr  If expr is false, it calls assert_failed function which reports
+   *         the name of the source file and the source line number of the call
+   *         that failed. If expr is true, it returns no value.
+   * @retval None
+   */
+  #define s_assert_param(expr) ((expr) ? (void)0 : s_assert_failed((uint8_t *)__FILE__, __LINE__,#expr))
+  void s_assert_failed(uint8_t* file, uint32_t line, char* expression);
+
+#elif SPIRIT_USE_FRAME_ASSERT
+   /**
+   * @brief  The s_assert_param macro is used for function's parameters check.
+   * @param  expr  If expr is false, it calls assert_failed function which reports
+   *         the name of the source file and the source line number of the call
+   *         that failed. If expr is true, it returns no value.
+   * @retval None
+   */
+#define s_assert_param(expr) ((expr) ? (void)0 : s_assert_failed(#expr))
+  void s_assert_failed(char* expression);
+#else
+#define s_assert_param(expr)        {}
+#endif
+
+/**
+ * @brief  Returns the absolute value.
+ */
+#define S_ABS(a) ((a)>0?(a):-(a))
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Types_Exported_Functions   Types Exported Functions
+ * @{
+ */
+
+void SpiritRefreshStatus(void);
+
+/**
+ *@}
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Aes.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Aes.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,319 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Aes.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT AES Engine.
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Aes.h"
+#include "MCU_Interface.h"
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_Aes
+ * @{
+ */
+
+
+/**
+ * @defgroup Aes_Private_TypesDefinitions       AES Private Types Definitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Aes_Private_Defines                AES Private Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Aes_Private_Macros                 AES Private Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Aes_Private_Variables              AES Private Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Aes_Private_FunctionPrototypes     AES Private Function Prototypes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup Aes_Private_Functions              AES Private Functions
+ * @{
+ */
+
+
+/**
+ * @brief  Enables or Disables the AES engine.
+ * @param  xNewState new state for AES engine.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None
+ */
+void SpiritAesMode(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Modifies the register value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= AES_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~AES_MASK;
+  }
+
+  /* Writes the ANA_FUNC_CONF0 register to enable or disable the AES engine */
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Writes the data to encrypt or decrypt, or the encryption key for the 
+ *         derive decryption key operation into the AES_DATA_IN registers.
+ * @param  pcBufferDataIn pointer to the user data buffer. The first byte of the array
+ * 	   shall be the MSB byte and it will be put in the AES_DATA_IN[0] register, while
+ * 	   the last one shall be the LSB and it will be put in the AES_DATA_IN[cDataLength-1]
+ * 	   register. If data to write are less than 16 bytes the remaining AES_DATA_IN registers
+ * 	   will be filled with bytes equal to 0. This parameter is an uint8_t*.
+ * @param  cDataLength length of data in bytes.
+ *         This parameter is an uint8_t.
+ * @retval None
+ */
+void SpiritAesWriteDataIn(uint8_t* pcBufferDataIn, uint8_t cDataLength)
+{
+  uint8_t i, dataInArray[16];
+
+  /* Verifies that there are no more than 16 bytes */
+  (cDataLength>16) ? (cDataLength=16) : cDataLength;
+
+  /* Fill the dataInArray with the data buffer, using padding */
+  for(i=0;i<16;i++)
+  {
+    (i<(16 - cDataLength)) ? (dataInArray[i]=0):(dataInArray[i]=pcBufferDataIn[15-i]);
+
+  }
+
+  /* Writes the AES_DATA_IN registers */
+  g_xStatus = SpiritSpiWriteRegisters(AES_DATA_IN_15_BASE, 16, dataInArray);
+
+}
+
+
+/**
+ * @brief  Returns the encrypted or decrypted data or the decription key from the AES_DATA_OUT register.
+ * @param  pcBufferDataOut pointer to the user data buffer. The AES_DATA_OUT[0]
+ *         register value will be put as first element of the buffer (MSB), while the
+ *         AES_DAT_OUT[cDataLength-1] register value will be put as last element of the buffer (LSB).
+ * 	   This parameter is a uint8_t*.
+ * @param  cDataLength length of data to read in bytes.
+ *         This parameter is a uint8_t.
+ * @retval None
+ */
+void SpiritAesReadDataOut(uint8_t* pcBufferDataOut, uint8_t cDataLength)
+{
+  uint8_t address, dataOutArray[16];
+
+  /* Verifies that there are no more than 16 bytes */
+  (cDataLength>16) ? (cDataLength=16) : cDataLength;
+
+  /* Evaluates the address of AES_DATA_OUT from which start to read */
+  address = AES_DATA_OUT_15_BASE+16-cDataLength;
+
+  /* Reads the exact number of AES_DATA_OUT registers */
+  g_xStatus = (SpiritSpiReadRegisters(address, cDataLength, dataOutArray));
+
+  /* Copy in the user buffer the read values changing the order */
+  for(int i = (cDataLength-1); i>=0; i--)
+  {
+    *pcBufferDataOut = dataOutArray[i];
+    pcBufferDataOut++;
+  }
+
+}
+
+
+/**
+ * @brief  Writes the encryption key into the AES_KEY_IN register.
+ * @param  pcKey pointer to the buffer of 4 words containing the AES key.
+ *         The first byte of the buffer shall be the most significant byte AES_KEY_0 of the AES key.
+ *         The last byte of the buffer shall be the less significant byte AES_KEY_15 of the AES key.
+ * 	   This parameter is an uint8_t*.
+ * @retval None
+ */
+void SpiritAesWriteKey(uint8_t* pcKey)
+{
+  uint8_t pcTempKey[16]; 
+  for (uint8_t i = 0; i < 16; i++)
+  {
+    pcTempKey[15-i] = pcKey[i];
+  }
+  
+  /* Writes the AES_DATA_IN registers */
+  g_xStatus = SpiritSpiWriteRegisters(AES_KEY_IN_15_BASE, 16, pcTempKey);
+
+}
+
+/**
+ * @brief  Returns the encryption/decryption key from the AES_KEY_IN register.
+ * @param  pcKey  pointer to the buffer of 4 words (16 bytes) containing the AES key.
+ *         The first byte of the buffer shall be the most significant byte AES_KEY_0 of the AES key.
+ *         The last byte of the buffer shall be the less significant byte AES_KEY_15 of the AES key.
+ *         This parameter is an uint8_t*.
+ * @retval None
+ */
+void SpiritAesReadKey(uint8_t* pcKey)
+{
+  uint8_t pcTempKey[16];
+
+  /* Reads the AES_DATA_IN registers */
+  g_xStatus = SpiritSpiReadRegisters(AES_KEY_IN_15_BASE, 16, pcTempKey);
+
+
+  for (uint8_t i = 0; i < 16; i++)
+    pcKey[i] = pcTempKey[15-i];
+
+}
+
+
+
+/**
+ * @brief  Derives the decryption key from a given encryption key.
+ * @param  None.
+ * @retval None.
+ */
+void SpiritAesDeriveDecKeyFromEnc(void)
+{
+  /* Sends the COMMAND_AES_KEY command */
+  g_xStatus = SpiritSpiCommandStrobes(COMMAND_AES_KEY);
+
+}
+
+
+/**
+ * @brief  Executes the encryption operation.
+ * @param  None.
+ * @retval None.
+ */
+void SpiritAesExecuteEncryption(void)
+{
+  /* Sends the COMMAND_AES_ENC command */
+  g_xStatus = SpiritSpiCommandStrobes(COMMAND_AES_ENC);
+
+}
+
+
+/**
+ * @brief  Executes the decryption operation.
+ * @param  None.
+ * @retval None.
+ */
+void SpiritAesExecuteDecryption(void)
+{
+  /* Sends the COMMAND_AES_DEC command */
+  g_xStatus = SpiritSpiCommandStrobes(COMMAND_AES_DEC);
+
+}
+
+
+/**
+ * @brief  Executes the key derivation and the decryption operation.
+ * @param  None.
+ * @retval None.
+ */
+void SpiritAesDeriveDecKeyExecuteDec(void)
+{
+  /* Sends the COMMAND_AES_KEY_DEC command */
+  g_xStatus = SpiritSpiCommandStrobes(COMMAND_AES_KEY_DEC);
+
+}
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Calibration.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Calibration.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,491 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Calibration.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Configuration and management of SPIRIT VCO-RCO calibration.
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Calibration.h"
+#include "MCU_Interface.h"
+
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_Calibration
+ * @{
+ */
+
+
+/**
+ * @defgroup Calibration_Private_TypesDefinitions       Calibration Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Calibration_Private_Defines                Calibration Private Defines
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Calibration_Private_Macros                 Calibration Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Calibration_Private_Variables              Calibration Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+
+/**
+ * @defgroup Calibration_Private_FunctionPrototypes     Calibration Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Calibration_Private_Functions              Calibration Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Enables or Disables the RCO calibration.
+ * @param  xNewState new state for RCO calibration.
+           This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritCalibrationRco(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+  /* Build new value for the register */
+  if(xNewState==S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL2_RCO_CALIBRATION_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL2_RCO_CALIBRATION_MASK;
+  }
+
+  /* Writes register to enable or disable the RCO calibration */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Enables or Disables the VCO calibration.
+ * @param  xNewState new state for VCO calibration.
+           This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritCalibrationVco(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+   /* Build new value for the register */
+  if(xNewState==S_ENABLE)
+    tempRegValue |= PROTOCOL2_VCO_CALIBRATION_MASK;
+  else
+    tempRegValue &= ~PROTOCOL2_VCO_CALIBRATION_MASK;
+
+  /* Writes register to enable or disable the VCO calibration */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the RCO calibration words.
+ * @param  cRwt RWT word for RCO calibration.
+ *         This parameter can be a value of uint8_t.
+ * @param  cRfb RFB word for RCO calibration.
+ *         This parameter can be a value of uint8_t.
+ * @retval None.
+ */
+void SpiritCalibrationSetRcoCalWords(uint8_t cRwt, uint8_t cRfb)
+{
+  uint8_t tempRegValue[2];
+
+  /* Build the value of RWT and the MSbits of the RFB word */
+  tempRegValue[0] = (cRwt << 4) | (cRfb >> 1);
+
+  /* Reads the register value to update the LSbit of RFB */
+  g_xStatus = SpiritSpiReadRegisters(RCO_VCO_CALIBR_IN1_BASE, 1, &tempRegValue[1]);
+
+  /* Build new value for the register */
+  tempRegValue[1] = (tempRegValue[1] & 0x7F) | (cRfb<<7);
+
+  /* Writes the new value for RCO calibration words */
+  g_xStatus = SpiritSpiWriteRegisters(RCO_VCO_CALIBR_IN2_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the RCO calibration words.
+ * @param  pcRwt pointer to the variable in which the RWT word has to be stored.
+ *         This parameter is a variable of uint8_t*.
+ * @param  pcRfb pointer to the variable in which the RFB word has to be stored.
+ *         This parameter is a variable of uint8_t*.
+ * @retval None.
+ */
+void SpiritCalibrationGetRcoCalWords(uint8_t* pcRwt, uint8_t* pcRfb)
+{
+  uint8_t tempRegValue[2];
+
+  /* Reads the registers values */
+  g_xStatus = SpiritSpiReadRegisters(RCO_VCO_CALIBR_OUT1_BASE, 2, tempRegValue);
+
+  /* Build the RWT value */
+  (*pcRwt) = tempRegValue[0] >> 4;
+  /* Build the RFB value */
+  (*pcRfb) = (tempRegValue[0] & 0x0F)<<1 | (tempRegValue[1]>>7);
+
+}
+
+
+/**
+ * @brief  Returns the VCO calibration data from internal VCO calibrator.
+ * @param  None.
+ * @retval uint8_t VCO calibration data word.
+ */
+uint8_t SpiritCalibrationGetVcoCalData(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(RCO_VCO_CALIBR_OUT0_BASE, 1, &tempRegValue);
+
+  /* Build and returns the VCO calibration data value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ * @brief  Sets the VCO calibration data to be used in TX mode.
+ * @param  cVcoCalData calibration data word to be set.
+ *         This parameter is a variable of uint8_t.
+ * @retval None.
+ */
+void SpiritCalibrationSetVcoCalDataTx(uint8_t cVcoCalData)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(RCO_VCO_CALIBR_IN1_BASE, 1, &tempRegValue);
+
+  /* Build the value to be written */
+  tempRegValue &= 0x80;
+  tempRegValue |= cVcoCalData;
+
+  /* Writes the new value of calibration data in TX */
+  g_xStatus = SpiritSpiWriteRegisters(RCO_VCO_CALIBR_IN1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the actual VCO calibration data used in TX mode.
+ * @param  None.
+ * @retval uint8_t Calibration data word used in TX mode.
+ */
+uint8_t SpiritCalibrationGetVcoCalDataTx(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register containing the calibration data word used in TX mode */
+  g_xStatus = SpiritSpiReadRegisters(RCO_VCO_CALIBR_IN1_BASE, 1, &tempRegValue);
+
+  /* Mask the VCO_CALIBR_TX field and returns the value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ * @brief  Sets the VCO calibration data to be used in RX mode.
+ * @param  cVcoCalData calibration data word to be set.
+ *         This parameter is a variable of uint8_t.
+ * @retval None.
+ */
+void SpiritCalibrationSetVcoCalDataRx(uint8_t cVcoCalData)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(RCO_VCO_CALIBR_IN0_BASE, 1, &tempRegValue);
+
+  /* Build the value to be written */
+  tempRegValue &= 0x80;
+  tempRegValue |= cVcoCalData;
+
+  /* Writes the new value of calibration data in RX */
+  g_xStatus = SpiritSpiWriteRegisters(RCO_VCO_CALIBR_IN0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the actual VCO calibration data used in RX mode.
+ * @param  None.
+ * @retval uint8_t Calibration data word used in RX mode.
+ */
+uint8_t SpiritCalibrationGetVcoCalDataRx(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register containing the calibration data word used in TX mode */
+  g_xStatus = SpiritSpiReadRegisters(RCO_VCO_CALIBR_IN0_BASE, 1, &tempRegValue);
+
+  /* Mask the VCO_CALIBR_RX field and returns the value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ * @brief  Sets the VCO calibration window.
+ * @param  xRefWord value of REFWORD corresponding to the Ref_period according to the formula: CALIBRATION_WIN = 11*Ref_period/fxo.
+           This parameter can be a value of @ref VcoWin.
+ * @retval None.
+ */
+void SpiritCalibrationSetVcoWindow(VcoWin xRefWord)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_VCO_WIN(xRefWord));
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue);
+
+  /* Build the values to be written */
+  tempRegValue &= 0xFC;
+  tempRegValue |= xRefWord;
+
+  /* Writes the new value of VCO calibration window */
+  g_xStatus = SpiritSpiWriteRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the VCO calibration window.
+ * @param  None.
+ * @retval VcoWin Value of REFWORD corresponding to the Ref_period according to the formula: CALIBRATION_WIN = 11*Ref_period/fxo.
+ *         This parameter can be a value of @ref VcoWin.
+ */
+VcoWin SpiritCalibrationGetVcoWindow(void)
+{
+  uint8_t tempRegValue1, tempRegValue2;
+  VcoWin refWord;
+
+  /* Reads the register containing the REFWORD value */
+  g_xStatus = SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue1);
+
+  /* Reads the Xtal configuration */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue2);
+
+  /* Mask the REFWORD field */
+  tempRegValue1 &= 0x03;
+
+  /* Mask the 24_26_MHz_SELECT field */
+  tempRegValue2 = ((tempRegValue2 & 0x40)>>6);
+
+  /* In case of 26 MHz crystal */
+  if(tempRegValue2)
+  {
+    switch(tempRegValue1)
+    {
+    case 0:
+      refWord = CALIB_TIME_6_77_US_26MHZ;
+      break;
+    case 1:
+      refWord = CALIB_TIME_13_54_US_26MHZ;
+      break;
+    case 2:
+      refWord = CALIB_TIME_27_08_US_26MHZ;
+      break;
+    case 3:
+      refWord = CALIB_TIME_54_15_US_26MHZ;
+      break;
+    }
+  }
+
+  /* In case of 24 MHz crystal */
+  else
+  {
+    switch(tempRegValue1)
+    {
+    case 0:
+      refWord = CALIB_TIME_7_33_US_24MHZ;
+      break;
+    case 1:
+      refWord = CALIB_TIME_14_67_US_24MHZ;
+      break;
+    case 2:
+      refWord = CALIB_TIME_29_33_US_24MHZ;
+      break;
+    case 3:
+      refWord = CALIB_TIME_58_67_US_24MHZ;
+      break;
+    }
+  }
+
+  return refWord;
+
+}
+
+/**
+ * @brief  Selects a VCO.
+ * @param  xVco can be VCO_H or VCO_L according to which VCO select.
+ *         This parameter can be a value of @ref VcoSel.
+ * @retval None.
+ */
+void SpiritCalibrationSelectVco(VcoSel xVco)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_VCO_SEL(xVco));
+  
+  SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue);
+  
+  tempRegValue &= 0xF9;
+  
+  if(xVco == VCO_H)
+  {
+    tempRegValue |= 0x02;
+    
+  }
+  else
+  {
+    tempRegValue |= 0x04;
+  }
+  SpiritSpiWriteRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue);  
+  
+}
+
+
+
+/**
+ * @brief  Returns the VCO selected.
+ * @param  void.
+ * @retval VCO_H or VCO_L according to which VCO selected.
+ *         This parameter can be a value of @ref VcoSel.
+ */
+VcoSel SpiritCalibrationGetVcoSelecttion(void)
+{
+  uint8_t tempRegValue;
+  
+  SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue);
+  
+  tempRegValue = (tempRegValue>>1)&0x3;
+  
+  if(tempRegValue == 0x01)
+  {
+    return VCO_H;
+    
+  }
+  else
+  {
+    return VCO_L;
+  }
+  
+}
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Commands.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Commands.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,144 @@
+/**
+  ******************************************************************************
+ * @file    SPIRIT_Commands.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+ * @brief   Management of SPIRIT Commands.
+ *
+  * @attention
+ *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+ *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Commands.h"
+#include "MCU_Interface.h"
+
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_Commands
+ * @{
+ */
+
+
+/**
+ * @defgroup Commands_Private_TypesDefinitions  Commands Private TypesDefinitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Commands_Private_Defines           Commands Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+/**
+ * @defgroup Commands_Private_Macros            Commands Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Commands_Private_Variables         Commands Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+
+/**
+ * @defgroup Commands_Private_FunctionPrototypes        Commands Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Commands_Private_Functions                 Commands Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Sends a specific command to SPIRIT.
+ * @param  xCommandCode code of the command to send.
+           This parameter can be any value of @ref SpiritCmd.
+ * @retval None.
+ */
+void SpiritCmdStrobeCommand(SpiritCmd xCommandCode)
+{
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_CMD(xCommandCode));
+
+  g_xStatus = SpiritSpiCommandStrobes((uint8_t) xCommandCode);
+}
+
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Csma.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Csma.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,600 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_Csma.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT CSMA.
+  * @details
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Csma.h"
+#include "MCU_Interface.h"
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_Csma
+ * @{
+ */
+
+
+/**
+ * @defgroup Csma_Private_TypesDefinitions      CSMA Private TypesDefinitions
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Csma_Private_Defines               CSMA Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Csma_Private_Macros               CSMA Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Csma_Private_Variables             CSMA Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+
+/**
+ * @defgroup Csma_Private_FunctionPrototypes    CSMA Private FunctionPrototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Csma_Private_Functions             CSMA Private Functions
+ * @{
+ */
+
+
+/**
+ * @brief  Initializes the SPIRIT CSMA according to the specified parameters in the CsmaInit.
+ * @param  pxCsmaInit Csma init structure.
+ *         This parameter is a pointer to @ref CsmaInit.
+ * @retval None.
+ */
+void SpiritCsmaInit(CsmaInit* pxCsmaInit)
+{
+  uint8_t tempRegValue[5];
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxCsmaInit->xCsmaPersistentMode));
+  s_assert_param(IS_CCA_PERIOD(pxCsmaInit->xMultiplierTbit));
+  s_assert_param(IS_CSMA_LENGTH(pxCsmaInit->xCcaLength));
+  s_assert_param(IS_BU_COUNTER_SEED(pxCsmaInit->nBuCounterSeed));
+  s_assert_param(IS_BU_PRESCALER(pxCsmaInit->cBuPrescaler));
+  s_assert_param(IS_CMAX_NB(pxCsmaInit->cMaxNb));
+
+  /* CSMA BU counter seed (MSB) config */
+  tempRegValue[0] = (uint8_t)(pxCsmaInit->nBuCounterSeed >> 8);
+
+  /* CSMA BU counter seed (LSB) config */
+  tempRegValue[1] = (uint8_t) pxCsmaInit->nBuCounterSeed;
+
+  /* CSMA BU prescaler config and CCA period config */
+  tempRegValue[2] = (pxCsmaInit->cBuPrescaler << 2) | pxCsmaInit->xMultiplierTbit;
+
+  /* CSMA CCA length config and max number of back-off */
+  tempRegValue[3] = (pxCsmaInit->xCcaLength | pxCsmaInit->cMaxNb);
+
+  /* Reads the PROTOCOL1_BASE register value, to write the SEED_RELOAD and CSMA_PERS_ON fields */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue[4]);
+
+  /* Writes the new value for persistent mode */
+  if(pxCsmaInit->xCsmaPersistentMode==S_ENABLE)
+  {
+    tempRegValue[4] |= PROTOCOL1_CSMA_PERS_ON_MASK;
+  }
+  else
+  {
+    tempRegValue[4] &= ~PROTOCOL1_CSMA_PERS_ON_MASK;
+  }
+
+  /* Writes PROTOCOL1_BASE register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue[4]);
+
+  /* Writes CSMA_CONFIGx_BASE registers */
+  g_xStatus = SpiritSpiWriteRegisters(CSMA_CONFIG3_BASE, 4, tempRegValue);
+
+}
+
+
+ /**
+  * @brief  Returns the fitted structure CsmaInit starting from the registers values.
+  * @param  pxCsmaInit Csma structure to be fitted.
+  *         This parameter is a pointer to @ref CsmaInit.
+  * @retval None.
+  */
+void SpiritCsmaGetInfo(CsmaInit* pxCsmaInit)
+{
+   uint8_t tempRegValue[5];
+
+   /* Reads PROTOCOL1_BASE register */
+   g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue[4]);
+
+   /* Reads CSMA_CONFIGx_BASE registers */
+   g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG3_BASE, 4, tempRegValue);
+
+   /* Reads the bu counter seed */
+   pxCsmaInit->nBuCounterSeed = (uint16_t)tempRegValue[1] | ((uint16_t)(tempRegValue[0] << 8));
+
+   /* Reads the bu prescaler */
+   pxCsmaInit->cBuPrescaler = tempRegValue[2]>>2;
+
+   /* Reads the Cca period */
+   pxCsmaInit->xMultiplierTbit = (CcaPeriod)(tempRegValue[2] & 0x03);
+
+   /* Reads the Cca length */
+   pxCsmaInit->xCcaLength = (CsmaLength)(tempRegValue[3]&0xF0);
+
+   /* Reads the max number of back off */
+   pxCsmaInit->cMaxNb = tempRegValue[3] & 0x07;
+
+   /* Reads the persistent mode enable bit */
+   pxCsmaInit->xCsmaPersistentMode = (SpiritFunctionalState)((tempRegValue[4]>>1) & 0x01);
+
+}
+
+
+/**
+ * @brief  Enables or Disables the CSMA.
+ * @param  xNewState the state of the CSMA mode.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritCsma(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PROTOCOL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Sets or resets the CSMA enable bit */
+  if(xNewState==S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL1_CSMA_ON_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL1_CSMA_ON_MASK;
+  }
+
+  /* Writes the new value on the PROTOCOL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+}
+
+/**
+ * @brief  Gets the CSMA mode. Says if it is enabled or disabled.
+ * @param  None.
+ * @retval SpiritFunctionalState: CSMA mode.
+ */
+SpiritFunctionalState SpiritCsmaGetCsma(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PROTOCOL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Return if set or reset */
+  if(tempRegValue & PROTOCOL1_CSMA_ON_MASK)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+
+}
+
+/**
+ * @brief  Enables or Disables the persistent CSMA mode.
+ * @param  xNewState the state of the persistent CSMA mode.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritCsmaPersistentMode(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PROTOCOL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Enables/disables the CSMA persistent mode */
+  if(xNewState==S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL1_CSMA_PERS_ON_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL1_CSMA_PERS_ON_MASK;
+  }
+
+  /* Writes the new vaue on the PROTOCOL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Gets the persistent CSMA mode.
+ * @param  None.
+ * @retval SpiritFunctionalState: CSMA persistent mode.
+ */
+SpiritFunctionalState SpiritCsmaGetPersistentMode(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PROTOCOL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Return if set or reset */
+  if(tempRegValue & PROTOCOL1_CSMA_PERS_ON_MASK)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+
+}
+
+
+/**
+ * @brief  Enables or Disables the seed reload mode (if enabled it reloads the back-off generator seed using the value written in the BU_COUNTER_SEED register).
+ * @param  xNewState the state of the seed reload mode.
+ *	   This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritCsmaSeedReloadMode(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PROTOCOL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Enables/disables the seed reload mode */
+  if(xNewState==S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL1_SEED_RELOAD_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL1_SEED_RELOAD_MASK;
+  }
+
+  /* Writes the new value on the PROTOCOL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Gets the seed reload mode.
+ * @param  None.
+ * @retval SpiritFunctionalState: CSMA seed reload mode.
+ */
+SpiritFunctionalState SpiritCsmaGetSeedReloadMode(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PROTOCOL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Return if set or reset */
+  if(tempRegValue & PROTOCOL1_SEED_RELOAD_MASK)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+}
+
+
+/**
+ * @brief  Sets the BU counter seed (BU_COUNTER_SEED register). The CSMA back off time is given by the formula: BO = rand(2^NB)*BU.
+ * @param  nBuCounterSeed seed of the random number generator used to apply the BBE algorithm.
+ *	   This parameter is an uint16_t.
+ * @retval None.
+ */
+void SpiritCsmaSetBuCounterSeed(uint16_t nBuCounterSeed)
+{
+  uint8_t tempRegValue[2];
+
+  /* Check parameters */
+  s_assert_param(IS_BU_COUNTER_SEED(nBuCounterSeed));
+
+  /* Build value (MSB)*/
+  tempRegValue[0]=(uint8_t)(nBuCounterSeed>>8);
+  /* Build value (LSB) */
+  tempRegValue[1]=(uint8_t)nBuCounterSeed;
+
+  /* Writes the CSMA_CONFIG3 registers */
+  g_xStatus = SpiritSpiWriteRegisters(CSMA_CONFIG3_BASE, 2, tempRegValue);
+
+}
+
+/**
+ * @brief  Returns the BU counter seed (BU_COUNTER_SEED register).
+ * @param  None.
+ * @retval uint16_t Seed of the random number generator used to apply the BBE algorithm.
+ */
+uint16_t SpiritCsmaGetBuCounterSeed(void)
+{
+  uint8_t tempRegValue[2];
+
+  /* Reads the CSMA_CONFIGx registers value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG3_BASE, 2, tempRegValue);
+
+  /* Build the counter seed and return it */
+  return ((uint16_t)tempRegValue[1] + (((uint16_t)tempRegValue[0])<<8));
+
+}
+
+
+/**
+ * @brief  Sets the BU prescaler. The CSMA back off time is given by the formula: BO = rand(2^NB)*BU.
+ * @param  cBuPrescaler used to program the back-off unit BU.
+ * 	   This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritCsmaSetBuPrescaler(uint8_t cBuPrescaler)
+{
+  uint8_t tempRegValue;
+
+  /* Check parameters */
+  s_assert_param(IS_BU_PRESCALER(cBuPrescaler));
+
+  /* Reads the CSMA_CONFIG1 register value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG1_BASE, 1, &tempRegValue);
+
+  /* Build the new value for the BU prescaler */
+  tempRegValue &= 0x03;
+  tempRegValue |= (cBuPrescaler<<2);
+
+  /* Writes the new value on the CSMA_CONFIG1_BASE register */
+  g_xStatus = SpiritSpiWriteRegisters(CSMA_CONFIG1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the BU prescaler.
+ * @param  None.
+ * @retval uint8_t Value back-off unit (BU).
+ */
+uint8_t SpiritCsmaGetBuPrescaler(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the CSMA_CONFIG1 register value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG1_BASE, 1, &tempRegValue);
+
+  /* Build and return the BU prescaler value */
+  return (tempRegValue >> 2);
+
+}
+
+
+/**
+ * @brief  Sets the CCA period.
+ * @param  xMultiplierTbit value of CCA period to store.
+ * 	   This parameter can be a value of @ref CcaPeriod.
+ * @retval None.
+ */
+void SpiritCsmaSetCcaPeriod(CcaPeriod xMultiplierTbit)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_CCA_PERIOD(xMultiplierTbit));
+
+  /* Reads the CSMA_CONFIG1 register value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG1_BASE, 1, &tempRegValue);
+
+  /* Build the new value setting the the CCA period */
+  tempRegValue &= 0xFC;
+  tempRegValue |= xMultiplierTbit;
+
+  /* Writes the new value on the CSMA_CONFIG1 register */
+  g_xStatus = SpiritSpiWriteRegisters(CSMA_CONFIG1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the CCA period.
+ * @param  None.
+ * @retval CcaPeriod CCA period.
+ */
+CcaPeriod SpiritCsmaGetCcaPeriod(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the CSMA_CONFIG1 register value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG1_BASE, 1, &tempRegValue);
+
+  /* Build and return the CCA period value */
+  return (CcaPeriod)(tempRegValue & 0x03);
+
+}
+
+
+/**
+ * @brief  Sets the CCA length.
+ * @param  xCcaLength the CCA length (a value between 1 and 15 that multiplies the CCA period).
+ *	   This parameter can be any value of @ref CsmaLength.
+ * @retval None.
+ */
+void SpiritCsmaSetCcaLength(CsmaLength xCcaLength)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_CSMA_LENGTH(xCcaLength));
+
+  /* Reads the CSMA_CONFIG0 register value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG0_BASE, 1, &tempRegValue);
+
+  /* Build the value of CCA length to be set */
+  tempRegValue &= 0x0F;
+  tempRegValue |= xCcaLength;
+
+  /* Writes the new value on the CSMA_CONFIG0 register */
+  g_xStatus = SpiritSpiWriteRegisters(CSMA_CONFIG0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the CCA length.
+ * @param  None.
+ * @retval uint8_t CCA length.
+ */
+uint8_t SpiritCsmaGetCcaLength(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the CSMA_CONFIG0 register value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG0_BASE, 1, &tempRegValue);
+
+  /* Build and return the CCA length */
+  return tempRegValue >> 4;
+
+}
+
+
+/**
+ * @brief  Sets the max number of back-off. If reached Spirit stops the transmission.
+ * @param  cMaxNb the max number of back-off.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritCsmaSetMaxNumberBackoff(uint8_t cMaxNb)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_CMAX_NB(cMaxNb));
+
+  /* Reads the CSMA_CONFIG0 register value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG0_BASE, 1, &tempRegValue);
+
+  /* Build the value of max back off to be set */
+  tempRegValue &= 0xF8;
+  tempRegValue |= cMaxNb;
+
+  /* Writes the new value on the CSMA_CONFIG0 register */
+  g_xStatus = SpiritSpiWriteRegisters(CSMA_CONFIG0_BASE, 1, &tempRegValue);
+}
+
+/**
+ * @brief  Returns the max number of back-off.
+ * @param  None.
+ * @retval uint8_t Max number of back-off.
+ */
+uint8_t SpiritCsmaGetMaxNumberBackoff(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the CSMA_CONFIG0 register value */
+  g_xStatus = SpiritSpiReadRegisters(CSMA_CONFIG0_BASE, 1, &tempRegValue);
+
+  /* Build and return the max number of back-off */
+  return (tempRegValue & 0x07);
+
+}
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_DirectRF.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_DirectRF.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,215 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_DirectRF.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT direct transmission / receive modes.
+  * @details
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_DirectRF.h"
+#include "MCU_Interface.h"
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_DirectRf
+ * @{
+ */
+
+
+/**
+ * @defgroup DirectRf_Private_TypesDefinitions          Direct RF Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup DirectRf_Private_Defines                   Direct RF Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup DirectRf_Private_Macros                    Direct RF Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup DirectRf_Private_Variables                 Direct RF Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+
+/**
+ * @defgroup DirectRf_Private_FunctionPrototypes        Direct RF Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup DirectRf_Private_Functions                 Direct RF Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Sets the DirectRF RX mode of SPIRIT.
+ * @param  xDirectRx code of the desired mode.
+ *         This parameter can be any value of @ref DirectRx.
+ * @retval None.
+ */
+void SpiritDirectRfSetRxMode(DirectRx xDirectRx)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_DIRECT_RX(xDirectRx));
+
+  /* Reads the register value */
+  SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Build the value to be stored */
+  tempRegValue &= ~PCKTCTRL3_RX_MODE_MASK;
+  tempRegValue |= (uint8_t)xDirectRx;
+
+  /* Writes value on register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the DirectRF RX mode of SPIRIT.
+ * @param  None.
+ * @retval DirectRx Direct Rx mode.
+ */
+DirectRx SpiritDirectRfGetRxMode(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value and mask the RX_Mode field */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return value */
+  return (DirectRx)(tempRegValue & 0x30);
+
+}
+
+
+/**
+ * @brief  Sets the TX mode of SPIRIT.
+ * @param  xDirectTx code of the desired source.
+ *         This parameter can be any value of @ref DirectTx.
+ * @retval None.
+ */
+void SpiritDirectRfSetTxMode(DirectTx xDirectTx)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_DIRECT_TX(xDirectTx));
+
+  /* Reads the register value */
+  SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Build the value to be stored */
+  tempRegValue &= ~PCKTCTRL1_TX_SOURCE_MASK;
+  tempRegValue |= (uint8_t)xDirectTx;
+
+  /* Writes value on register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the DirectRF TX mode of SPIRIT.
+ * @param  None.
+ * @retval DirectTx Direct Tx mode.
+ */
+DirectTx SpiritDirectRfGetTxMode(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value and mask the RX_Mode field */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Returns value */
+  return (DirectTx)(tempRegValue & 0x0C);
+
+}
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_General.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_General.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,449 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_General.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT General functionalities.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_General.h"
+#include "MCU_Interface.h"
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_General
+ * @{
+ */
+
+
+/**
+ * @defgroup General_Private_TypesDefinitions   General Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup General_Private_Defines            General Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup General_Private_Macros             General Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup General_Private_Variables          General Private Variables
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup General_Private_FunctionPrototypes         General Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup General_Private_Functions                          General Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Enables or Disables the output of battery level detector.
+ * @param  xNewState new state for battery level detector.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None
+ */
+void SpiritGeneralBatteryLevel(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the ANA_FUNC_CONF0_BASE register value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+  /* Build the value to be stored */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= BATTERY_LEVEL_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~BATTERY_LEVEL_MASK;
+  }
+
+  /* Writes the new value */
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the battery level.
+ * @param  xBatteryLevel new state for battery level.
+ *         This parameter can be a value of @ref BatteryLevel.
+ * @retval None.
+ */
+void SpiritGeneralSetBatteryLevel(BatteryLevel xBatteryLevel)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_BLD_LVL(xBatteryLevel));
+
+  /* Reads the ANA_FUNC_CONF1_BASE register value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF1_BASE, 1, &tempRegValue);
+
+  /* Build the value to be stored */
+  tempRegValue &= ~ANA_FUNC_CONF1_SET_BLD_LVL_MASK;
+  switch(xBatteryLevel)
+  {
+    case BLD_LVL_2_7_V:
+      tempRegValue |= BLD_LVL_2_7;
+      break;
+    case BLD_LVL_2_5_V:
+      tempRegValue |= BLD_LVL_2_5;
+      break;
+    case BLD_LVL_2_3_V:
+      tempRegValue |= BLD_LVL_2_3;
+      break;
+    case BLD_LVL_2_1_V:
+      tempRegValue |= BLD_LVL_2_1;
+      break;
+  }
+
+  /* Writes the new value */
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the settled battery level.
+ * @param  None.
+ * @retval BatteryLevel Settled battery level. This parameter can be a value of @ref BatteryLevel.
+ */
+BatteryLevel SpiritGeneralGetBatteryLevel(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the ANA_FUNC_CONF1_BASE register value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF1_BASE, 1, &tempRegValue);
+
+  /* Mask the battery level field and returns the settled battery level */
+  return ((BatteryLevel)(tempRegValue & ANA_FUNC_CONF1_SET_BLD_LVL_MASK));
+
+}
+
+
+/**
+ * @brief  Enables or Disables the output of brown out detector.
+ * @param  xNewState new state for brown out detector.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritGeneralBrownOut(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the ANA_FUNC_CONF0_BASE register value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+  /* Build the value to be stored */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= BROWN_OUT_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~BROWN_OUT_MASK;
+  }
+
+  /* Writes value on register */
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets High Power Mode.
+ * @param  xNewState new state for High Power Mode.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritGeneralHighPwr(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the ANA_FUNC_CONF0_BASE register value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+  /* Build the value to write */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= HIGH_POWER_MODE_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~HIGH_POWER_MODE_MASK;
+  }
+
+  /* Writes the new value on register */
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets External Reference.
+ * @param  xExtMode new state for the external reference.
+ *         This parameter can be: MODE_EXT_XO or MODE_EXT_XIN.
+ * @retval None.
+ */
+void SpiritGeneralSetExtRef(ModeExtRef xExtMode)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_MODE_EXT(xExtMode));
+
+  /* Reads the ANA_FUNC_CONF0_BASE register value */
+  SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+  /* Build the value to write */
+  if(xExtMode == MODE_EXT_XO)
+  {
+    tempRegValue &= ~EXT_REF_MASK;
+  }
+  else
+  {
+    tempRegValue |= EXT_REF_MASK;
+  }
+
+  /* Writes value on register */
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns External Reference.
+ * @param  None.
+ * @retval ModeExtRef Settled external reference.
+ *         This parameter can be: MODE_EXT_XO or MODE_EXT_XIN.
+ */
+ModeExtRef SpiritGeneralGetExtRef(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the ANA_FUNC_CONF0_BASE register value and return the result */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+  /* Mask the EXT_REF field field and returns the settled reference signal */
+  return ((ModeExtRef)((tempRegValue & 0x10)>>4));
+
+}
+
+
+/**
+ * @brief  Sets XO gm at startup.
+ * @param  xGm transconductance value of XO at startup.
+ *         This parameter can be a value of @ref GmConf.
+ * @retval None.
+ */
+void SpiritGeneralSetXoGm(GmConf xGm)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_GM_CONF(xGm));
+
+  /* Reads the ANA_FUNC_CONF1_BASE register value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF1_BASE, 1, &tempRegValue);
+
+  /* Build the value to write */
+  tempRegValue &= ~ANA_FUNC_CONF1_GMCONF_MASK;
+  switch(xGm)
+  {
+    case GM_SU_13_2:
+      tempRegValue |= GM_13_2;
+      break;
+    case GM_SU_18_2:
+      tempRegValue |= GM_18_2;
+      break;
+    case GM_SU_21_5:
+      tempRegValue |= GM_21_5;
+      break;
+    case GM_SU_25_6:
+      tempRegValue |= GM_25_6;
+      break;
+    case GM_SU_28_8:
+      tempRegValue |= GM_28_8;
+      break;
+    case GM_SU_33_9:
+      tempRegValue |= GM_33_9;
+      break;
+    case GM_SU_38_5:
+      tempRegValue |= GM_38_5;
+      break;
+    case GM_SU_43_0:
+      tempRegValue |= GM_43_0;
+      break;
+  }
+
+  /* Writes new value on register */
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the configured XO gm at startup.
+ * @param  None.
+ * @retval GmConf Settled XO gm. This parameter can be a value of @ref GmConf.
+ */
+GmConf SpiritGeneralGetXoGm(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the ANA_FUNC_CONF1_BASE register value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF1_BASE, 1, &tempRegValue);
+
+  /* Mask the GM_CONF field field and returns the settled transconductance of the XO at startup */
+  return ((GmConf)((tempRegValue & 0x1C)>>2));
+
+}
+
+
+/**
+ * @brief  Returns the settled packet format.
+ * @param  None.
+ * @retval PacketType Settled packet type. This parameter can be a value of @ref PacketType.
+ */
+PacketType SpiritGeneralGetPktType(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PROTOCOL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* cast and return value */
+  return (PacketType)(tempRegValue>>6);
+
+}
+
+
+
+/**
+ * @brief  Returns device part number.
+ * @param  None.
+ * @retval uint16_t Device part number.
+ */
+uint16_t SpiritGeneralGetDevicePartNumber(void)
+{
+  uint8_t tempRegValue[2];
+
+  /* Reads the register value containing the device part number */
+  g_xStatus = SpiritSpiReadRegisters(DEVICE_INFO1_PARTNUM, 2, tempRegValue);
+
+  return ((((uint16_t)tempRegValue[0])<<8) | ((uint16_t)tempRegValue[1]));
+
+}
+
+/**
+ * @brief  Returns SPIRIT RF board version.
+ * @param  None.
+ * @retval SPIRIT RF board version: 0x30 is the only admitted value
+ */
+uint8_t SpiritGeneralGetSpiritVersion(void)
+{
+  uint8_t ver; 
+  SpiritSpiReadRegisters(DEVICE_INFO0_VERSION, 1, &ver);
+  return ver;
+}
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Gpio.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Gpio.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,458 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_Gpio.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   This file provides all the low level API to manage SPIRIT GPIO.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Gpio.h"
+#include "MCU_Interface.h"
+
+
+/** @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/** @addtogroup SPIRIT_Gpio
+ * @{
+ */
+
+
+/** @defgroup Gpio_Private_TypesDefinitions     GPIO Private Types Definitions
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+/** @defgroup Gpio_Private_Defines              GPIO Private Defines
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Gpio_Private_Macros               GPIO Private Macros
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Gpio_Private_Variables            GPIO Private Variables
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Gpio_Private_FunctionPrototypes   GPIO Private Function Prototypes
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Gpio_Private_Functions            GPIO Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Initializes the SPIRIT GPIOx according to the specified
+ *         parameters in the pxGpioInitStruct.
+ * @param  pxGpioInitStruct pointer to a SGpioInit structure that
+ *         contains the configuration information for the specified SPIRIT GPIO.
+ * @retval None.
+ */
+void SpiritGpioInit(SGpioInit* pxGpioInitStruct)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_GPIO(pxGpioInitStruct->xSpiritGpioPin));
+  s_assert_param(IS_SPIRIT_GPIO_MODE(pxGpioInitStruct->xSpiritGpioMode));
+  s_assert_param(IS_SPIRIT_GPIO_IO(pxGpioInitStruct->xSpiritGpioIO));
+
+  tempRegValue = ((uint8_t)(pxGpioInitStruct->xSpiritGpioMode) | (uint8_t)(pxGpioInitStruct->xSpiritGpioIO));
+
+  g_xStatus = SpiritSpiWriteRegisters(pxGpioInitStruct->xSpiritGpioPin, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Enables or Disables the output of temperature sensor on SPIRIT GPIO_0.
+ * @param  xNewState new state for temperature sensor.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritGpioTemperatureSensor(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+  uint8_t gpio0tempRegValue = 0x00;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the ANA_FUNC_CONF0 register and mask the result to enable or disable the
+     temperature sensor */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= TEMPERATURE_SENSOR_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~TEMPERATURE_SENSOR_MASK);
+    gpio0tempRegValue = 0x0A; /* Default value */
+  }
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+
+  /* Sets the SPIRIT GPIO_0 according to input request */
+  g_xStatus = SpiritSpiWriteRegisters(GPIO0_CONF_BASE, 1, &gpio0tempRegValue);
+
+}
+
+
+/**
+ * @brief  Forces SPIRIT GPIO_x configured as digital output, to VDD or GND.
+ * @param  xGpioX Specifies the GPIO to be configured.
+ *   This parameter can be one of following parameters:
+ *     @arg SPIRIT_GPIO_0: SPIRIT GPIO_0
+ *     @arg SPIRIT_GPIO_1: SPIRIT GPIO_1
+ *     @arg SPIRIT_GPIO_2: SPIRIT GPIO_2
+ *     @arg SPIRIT_GPIO_3: SPIRIT GPIO_3
+ * @param  xLevel Specifies the level.
+ *   This parameter can be: HIGH or LOW.
+ * @retval None.
+ */
+void SpiritGpioSetLevel(SpiritGpioPin xGpioX, OutputLevel xLevel)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_GPIO(xGpioX));
+  s_assert_param(IS_SPIRIT_GPIO_LEVEL(xLevel));
+
+  /* Reads the SPIRIT_GPIOx register and mask the GPIO_SELECT field */
+  g_xStatus = SpiritSpiReadRegisters(xGpioX, 1, &tempRegValue);
+  tempRegValue &= 0x04;
+
+  /* Sets the value of the SPIRIT GPIO register according to the specified level */
+  if(xLevel == HIGH)
+  {
+    tempRegValue |= (uint8_t)SPIRIT_GPIO_DIG_OUT_VDD | (uint8_t)SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_HP;
+  }
+  else
+  {
+    tempRegValue |= (uint8_t)SPIRIT_GPIO_DIG_OUT_GND | (uint8_t)SPIRIT_GPIO_MODE_DIGITAL_OUTPUT_HP;
+  }
+
+  /* Writes the SPIRIT GPIO register */
+  g_xStatus = SpiritSpiWriteRegisters(xGpioX, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns output value (VDD or GND) of SPIRIT GPIO_x, when it is configured as digital output.
+ * @param  xGpioX Specifies the GPIO to be read.
+ *         This parameter can be one of following parameters:
+ *         @arg SPIRIT_GPIO_0: SPIRIT GPIO_0
+ *         @arg SPIRIT_GPIO_1: SPIRIT GPIO_1
+ *         @arg SPIRIT_GPIO_2: SPIRIT GPIO_2
+ *         @arg SPIRIT_GPIO_3: SPIRIT GPIO_3
+ * @retval OutputLevel Logical level of selected GPIO configured as digital output.
+ *         This parameter can be: HIGH or LOW.
+ */
+OutputLevel SpiritGpioGetLevel(SpiritGpioPin xGpioX)
+{
+  uint8_t tempRegValue = 0x00;
+  OutputLevel level;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_GPIO(xGpioX));
+
+  /* Reads the SPIRIT_GPIOx register */
+  g_xStatus = SpiritSpiReadRegisters(xGpioX, 1, &tempRegValue);
+
+  /* Mask the GPIO_SELECT field and returns the value according */
+  tempRegValue &= 0xF8;
+  if(tempRegValue == SPIRIT_GPIO_DIG_OUT_VDD)
+  {
+    level = HIGH;
+  }
+  else
+  {
+    level = LOW;
+  }
+
+  return level;
+
+}
+
+
+/**
+ * @brief  Enables or Disables the MCU clock output.
+ * @param  xNewState new state for the MCU clock output.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritGpioClockOutput(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the MCU_CK_CONF register and mask the result to enable or disable the clock output */
+  g_xStatus = SpiritSpiReadRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+  if(xNewState)
+  {
+    tempRegValue |= MCU_CK_ENABLE;
+  }
+  else
+  {
+    tempRegValue &= (~MCU_CK_ENABLE);
+  }
+
+  /* Writes the MCU_CK_CONF register */
+  g_xStatus = SpiritSpiWriteRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Initializes the SPIRIT Clock Output according to the specified
+ *         parameters in the xClockOutputInitStruct.
+ * @param  pxClockOutputInitStruct pointer to a ClockOutputInit structure that
+ *         contains the configuration information for the SPIRIT Clock Output.
+ * @retval None.
+ * @note   The function SpiritGpioClockOutput() must be called in order to enable
+ *         or disable the MCU clock dividers.
+ */
+void SpiritGpioClockOutputInit(ClockOutputInit* pxClockOutputInitStruct)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_CLOCK_OUTPUT_XO(pxClockOutputInitStruct->xClockOutputXOPrescaler));
+  s_assert_param(IS_SPIRIT_CLOCK_OUTPUT_RCO(pxClockOutputInitStruct->xClockOutputRCOPrescaler));
+  s_assert_param(IS_SPIRIT_CLOCK_OUTPUT_EXTRA_CYCLES(pxClockOutputInitStruct->xExtraClockCycles));
+
+  /* Calculates the register value to write according to the specified configuration */
+  tempRegValue = ((uint8_t)(pxClockOutputInitStruct->xClockOutputXOPrescaler) | (uint8_t)(pxClockOutputInitStruct->xClockOutputRCOPrescaler) | \
+           (uint8_t)(pxClockOutputInitStruct->xExtraClockCycles));
+
+  /* Writes the MCU_CLOCK register */
+  g_xStatus = SpiritSpiWriteRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the XO ratio as clock output.
+ * @param  xXOPrescaler the XO prescaler to be used as clock output.
+ *         This parameter can be any value of @ref ClockOutputXOPrescaler .
+ * @retval None
+ */
+void SpiritGpioSetXOPrescaler(ClockOutputXOPrescaler xXOPrescaler)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_CLOCK_OUTPUT_XO(xXOPrescaler));
+
+  /* Reads the MCU_CLK_CONFIG register */
+  g_xStatus = SpiritSpiReadRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+  /* Mask the XO_RATIO field and writes the new value */
+  tempRegValue &= 0x61;
+  tempRegValue |= ((uint8_t)xXOPrescaler);
+
+  /* Writes the new XO prescaler in the MCU_CLOCK register */
+  g_xStatus = SpiritSpiWriteRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the settled XO prescaler as clock output.
+ * @param  None.
+ * @retval ClockOutputXOPrescaler Settled XO prescaler used for clock
+ *         output. This parameter can be a value of @ref ClockOutputXOPrescaler .
+ */
+ClockOutputXOPrescaler SpiritGpioGetXOPrescaler(void)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Reads the MCU_CLK_CONFIG register */
+  g_xStatus = SpiritSpiReadRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+  /* Mask the XO_RATIO field and return the value */
+  return ((ClockOutputXOPrescaler)(tempRegValue & 0x1E));
+
+}
+
+
+/**
+ * @brief  Sets the RCO ratio as clock output
+ * @param  xRCOPrescaler the RCO prescaler to be used as clock output.
+ *         This parameter can be any value of @ref ClockOutputRCOPrescaler .
+ * @retval None.
+ */
+void SpiritGpioSetRCOPrescaler(ClockOutputRCOPrescaler xRCOPrescaler)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_CLOCK_OUTPUT_RCO(xRCOPrescaler));
+
+  /* Reads the MCU_CLK_CONFIG register */
+  g_xStatus = SpiritSpiReadRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+  /* Mask the RCO_RATIO field and writes the new value */
+  tempRegValue &= 0xFE;
+  tempRegValue |= ((uint8_t)xRCOPrescaler);
+
+  /* Writes the new RCO prescaler in the MCU_CLOCK register */
+  g_xStatus = SpiritSpiWriteRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the settled RCO prescaler as clock output.
+ * @param  None.
+ * @retval ClockOutputRCOPrescaler Settled RCO prescaler used for clock
+ *         output. This parameter can be a value of @ref ClockOutputRCOPrescaler.
+ */
+ClockOutputRCOPrescaler SpiritGpioGetRCOPrescaler(void)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Reads the MCU_CLK_CONFIG register */
+  g_xStatus = SpiritSpiReadRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+  /* Mask the RCO_RATIO field and returns the value */
+  return ((ClockOutputRCOPrescaler)(tempRegValue & 0x01));
+
+}
+
+
+/**
+ * @brief  Sets the RCO ratio as clock output.
+ * @param  xExtraCycles the number of extra clock cycles provided before switching
+ *         to STANDBY state. This parameter can be any value of @ref ExtraClockCycles .
+ * @retval None.
+ */
+void SpiritGpioSetExtraClockCycles(ExtraClockCycles xExtraCycles)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_CLOCK_OUTPUT_EXTRA_CYCLES(xExtraCycles));
+
+  /* Reads the MCU_CLK_CONFIG register */
+  g_xStatus = SpiritSpiReadRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+  /* Mask the CLOCK_TAIL field and writes the new value */
+  tempRegValue &= 0x9F;
+  tempRegValue |= ((uint8_t)xExtraCycles);
+
+  /* Writes the new number of extra clock cycles in the MCU_CLOCK register */
+  g_xStatus = SpiritSpiWriteRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the settled RCO prescaler as clock output.
+ * @param  None.
+ * @retval ExtraClockCycles Settled number of extra clock cycles
+ *         provided before switching to STANDBY state. This parameter can be
+ *         any value of @ref ExtraClockCycles .
+ */
+ExtraClockCycles SpiritGpioGetExtraClockCycles(void)
+{
+  uint8_t tempRegValue = 0x00;
+
+  /* Reads the MCU_CLK_CONFIG register */
+  g_xStatus = SpiritSpiReadRegisters(MCU_CK_CONF_BASE, 1, &tempRegValue);
+
+  /* Mask the CLOCK_TAIL field and returns the value */
+  return ((ExtraClockCycles)(tempRegValue & 0x60));
+
+}
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Irq.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Irq.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,320 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_Irq.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT IRQs.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Irq.h"
+#include "MCU_Interface.h"
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_Irq
+ * @{
+ */
+
+
+/**
+ * @defgroup Irq_Private_TypesDefinitions       IRQ Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Irq_Private_Defines                IRQ Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Irq_Private_Macros                 IRQ Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Irq_Private_Variables              IRQ Private Variables
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Irq_Private_FunctionPrototypes     IRQ Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Irq_Private_Functions              IRQ Private Functions
+ * @{
+ */
+
+
+/**
+ * @brief  De initializate the SpiritIrqs structure setting all the bitfield to 0.
+ *         Moreover, it sets the IRQ mask registers to 0x00000000, disabling all IRQs.
+ * @param  pxIrqInit pointer to a variable of type @ref SpiritIrqs, in which all the
+ *         bitfields will be settled to zero.
+ * @retval None.
+ */
+void SpiritIrqDeInit(SpiritIrqs* pxIrqInit)
+{
+  uint8_t tempRegValue[4]={0x00,0x00,0x00,0x00};
+
+  if(pxIrqInit!=NULL)
+  {
+    /* Sets the bitfields of passed structure to one */
+    *(uint32_t*)pxIrqInit = 0x0;
+  }
+
+  /* Writes the IRQ_MASK registers */
+  g_xStatus = SpiritSpiWriteRegisters(IRQ_MASK3_BASE, 4, tempRegValue);
+}
+
+
+/**
+ * @brief  Enables all the IRQs according to the user defined pxIrqInit structure.
+ * @param  pxIrqInit pointer to a variable of type @ref SpiritIrqs, through which the
+ *         user enable specific IRQs. This parameter is a pointer to a SpiritIrqs.
+ *         For example suppose to enable only the two IRQ Low Battery Level and Tx Data Sent:
+ * @code
+ * SpiritIrqs myIrqInit = {0};
+ * myIrqInit.IRQ_LOW_BATT_LVL = 1;
+ * myIrqInit.IRQ_TX_DATA_SENT = 1;
+ * SpiritIrqInit(&myIrqInit);
+ * @endcode
+ * @retval None.
+ */
+void SpiritIrqInit(SpiritIrqs* pxIrqInit)
+{
+  /* Writes the IRQ_MASK registers */
+  g_xStatus = SpiritSpiWriteRegisters(IRQ_MASK3_BASE, 4, (uint8_t*)pxIrqInit);
+
+}
+
+
+/**
+ * @brief  Enables or disables a specific IRQ.
+ * @param  xIrq IRQ to enable or disable.
+ *         This parameter can be any value of @ref IrqList.
+ * @param  xNewState new state for the IRQ.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritIrq(IrqList xIrq, SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue[4];
+  uint32_t tempValue = 0;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_IRQ_LIST(xIrq));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the IRQ_MASK registers */
+  g_xStatus = SpiritSpiReadRegisters(IRQ_MASK3_BASE, 4, tempRegValue);
+
+  /* Build the IRQ mask word */
+  for(uint8_t i=0; i<4; i++)
+  {
+    tempValue += ((uint32_t)tempRegValue[i])<<(8*(3-i));
+  }
+  
+  /* Rebuild the new mask according to user request */
+  if(xNewState == S_DISABLE)
+  {
+    tempValue &= (~xIrq);
+  }
+  else
+  {
+    tempValue |= (xIrq);
+  }
+
+  /* Build the array of bytes to write in the IRQ_MASK registers */
+  for(uint8_t j=0; j<4; j++)
+  {
+    tempRegValue[j] = (uint8_t)(tempValue>>(8*(3-j)));
+  }
+  
+  /* Writes the new IRQ mask in the corresponding registers */
+  g_xStatus = SpiritSpiWriteRegisters(IRQ_MASK3_BASE, 4, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Fills a pointer to a structure of SpiritIrqs type reading the IRQ_MASK registers.
+ * @param  pxIrqMask pointer to a variable of type @ref SpiritIrqs, through which the
+ *         user can read which IRQs are enabled. All the bitfields equals to zero correspond
+ *         to enabled IRQs, while all the bitfields equals to one correspond to disabled IRQs.
+ *         This parameter is a pointer to a SpiritIrqs.
+ *         For example suppose that the Power On Reset and RX Data ready are the only enabled IRQs.
+ * @code
+ * SpiritIrqs myIrqMask;
+ * SpiritIrqGetStatus(&myIrqMask);
+ * @endcode
+ * Then
+ * myIrqMask.IRQ_POR and myIrqMask.IRQ_RX_DATA_READY are equal to 0
+ * while all the other bitfields are equal to one.
+ * @retval None.
+ */
+void SpiritIrqGetMask(SpiritIrqs* pxIrqMask)
+{
+  /* Reads IRQ_MASK registers */
+  g_xStatus = SpiritSpiReadRegisters(IRQ_MASK3_BASE, 4, (uint8_t*)pxIrqMask);
+}
+
+
+/**
+ * @brief  Filla a pointer to a structure of SpiritIrqs type reading the IRQ_STATUS registers.
+ * @param  pxIrqStatus pointer to a variable of type @ref SpiritIrqs, through which the
+ *         user can read the status of all the IRQs. All the bitfields equals to one correspond
+ *         to the raised interrupts. This parameter is a pointer to a SpiritIrqs.
+ *         For example suppose that the XO settling timeout is raised as well as the Sync word
+ *         detection.
+ * @code
+ * SpiritIrqs myIrqStatus;
+ * SpiritIrqGetStatus(&myIrqStatus);
+ * @endcode
+ * Then
+ * myIrqStatus.IRQ_XO_COUNT_EXPIRED and myIrqStatus.IRQ_VALID_SYNC are equals to 1
+ * while all the other bitfields are equals to zero.
+ * @retval None.
+ */
+void SpiritIrqGetStatus(SpiritIrqs* pxIrqStatus)
+{
+  /* Reads IRQ_STATUS registers */
+  g_xStatus = SpiritSpiReadRegisters(IRQ_STATUS3_BASE, 4, (uint8_t*)pxIrqStatus);
+}
+
+
+/**
+ * @brief  Clear the IRQ status registers.
+ * @param  None.
+ * @retval None.
+ */
+void SpiritIrqClearStatus(void)
+{
+  uint8_t tempRegValue[4];
+
+  /* Reads the IRQ_STATUS registers clearing all the flags */
+  g_xStatus = SpiritSpiReadRegisters(IRQ_STATUS3_BASE, 4, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Verifies if a specific IRQ has been generated.
+ *         The call resets all the IRQ status, so it can't be used in case of multiple raising interrupts.
+ * @param  xFlag IRQ flag to be checked.
+ *         This parameter can be any value of @ref IrqList.
+ * @retval SpiritBool S_TRUE or S_FALSE.
+ */
+SpiritBool SpiritIrqCheckFlag(IrqList xFlag)
+{
+  uint8_t tempRegValue[4];
+  uint32_t tempValue = 0;
+  SpiritBool flag;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_IRQ_LIST(xFlag));
+
+  /* Reads registers and build the status word */
+  g_xStatus = SpiritSpiReadRegisters(IRQ_STATUS3_BASE, 4, tempRegValue);
+  for(uint8_t i=0; i<4; i++)
+  {
+    tempValue += ((uint32_t)tempRegValue[i])<<(8*(3-i));
+  }
+  
+  if(tempValue & xFlag)
+  {
+    flag = S_TRUE;
+  }
+  else
+  {
+    flag = S_FALSE;
+  }
+
+  return flag;
+
+}
+
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_LinearFifo.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_LinearFifo.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,337 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_LinearFifo.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT Fifo.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_LinearFifo.h"
+#include "MCU_Interface.h"
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_LinearFifo
+ * @{
+ */
+
+
+/**
+ * @defgroup LinearFifo_Private_TypesDefinitions        Linear FIFO Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup LinearFifo_Private_Defines                 Linear FIFO Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup LinearFifo_Private_Macros                  Linear FIFO Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup LinearFifo_Private_Variables               Linear FIFO Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup LinearFifo_Private_FunctionPrototypes      Linear FIFO Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup LinearFifo_Private_Functions               Linear FIFO Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Returns the number of elements in the Rx FIFO.
+ * @param  None.
+ * @retval uint8_t Number of elements in the Rx FIFO.
+ */
+uint8_t SpiritLinearFifoReadNumElementsRxFifo(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(LINEAR_FIFO_STATUS0_BASE, 1, &tempRegValue);
+
+  /* Build and return value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ * @brief  Returns the number of elements in the Tx FIFO.
+ * @param  None.
+ * @retval uint8_t Number of elements in the Tx FIFO.
+ */
+uint8_t SpiritLinearFifoReadNumElementsTxFifo(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the number of elements in TX FIFO and return the value */
+  g_xStatus = SpiritSpiReadRegisters(LINEAR_FIFO_STATUS1_BASE, 1, &tempRegValue);
+
+  /* Build and return value */
+  return (tempRegValue & 0x7F);
+}
+
+
+/**
+ * @brief  Sets the almost full threshold for the Rx FIFO. When the number of elements in RX FIFO reaches this value an interrupt can be generated to the MCU.
+ * @note   The almost full threshold is encountered from the top of the FIFO. For example, if it is set to 7 the almost
+ *         full FIFO irq will be raised when the number of elements is equals to 96-7 = 89.
+ * @param  cThrRxFifo almost full threshold.
+ * 	   This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritLinearFifoSetAlmostFullThresholdRx(uint8_t cThrRxFifo)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_FIFO_THR(cThrRxFifo));
+
+  /* Build the register value */
+  tempRegValue = cThrRxFifo & 0x7F;
+
+  /* Writes the Almost Full threshold for RX in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(FIFO_CONFIG3_RXAFTHR_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the almost full threshold for RX FIFO.
+ * @note   The almost full threshold is encountered from the top of the FIFO. For example, if it is 7 the almost
+ *         full FIFO irq will be raised when the number of elements is equals to 96-7 = 89.
+ * @param  None.
+ * @retval uint8_t Almost full threshold for Rx FIFO.
+ */
+uint8_t SpiritLinearFifoGetAlmostFullThresholdRx(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the almost full threshold for RX FIFO and return the value */
+  g_xStatus = SpiritSpiReadRegisters(FIFO_CONFIG3_RXAFTHR_BASE, 1, &tempRegValue);
+
+  /* Build and return value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ * @brief  Sets the almost empty threshold for the Rx FIFO. When the number of elements in RX FIFO reaches this value an interrupt can be generated to the MCU.
+ * @param  cThrRxFifo almost empty threshold.
+ * 	   This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritLinearFifoSetAlmostEmptyThresholdRx(uint8_t cThrRxFifo)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_FIFO_THR(cThrRxFifo));
+
+  /* Build the register value */
+  tempRegValue = cThrRxFifo & 0x7F;
+
+  /* Writes the Almost Empty threshold for RX in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(FIFO_CONFIG2_RXAETHR_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the almost empty threshold for Rx FIFO.
+ * @param  None.
+ * @retval uint8_t Almost empty threshold for Rx FIFO.
+ */
+uint8_t SpiritLinearFifoGetAlmostEmptyThresholdRx(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the almost empty threshold for RX FIFO and returns the value */
+  g_xStatus = SpiritSpiReadRegisters(FIFO_CONFIG2_RXAETHR_BASE, 1, &tempRegValue);
+
+  /* Build and return value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ * @brief  Sets the almost full threshold for the Tx FIFO. When the number of elements in TX FIFO reaches this value an interrupt can be generated to the MCU.
+ * @note   The almost full threshold is encountered from the top of the FIFO. For example, if it is set to 7 the almost
+ *         full FIFO irq will be raised when the number of elements is equals to 96-7 = 89.
+ * @param  cThrTxFifo almost full threshold.
+ * 	   This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritLinearFifoSetAlmostFullThresholdTx(uint8_t cThrTxFifo)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_FIFO_THR(cThrTxFifo));
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(FIFO_CONFIG1_TXAFTHR_BASE, 1, &tempRegValue);
+
+  /* Build the register value */
+  tempRegValue &= 0x80;
+  tempRegValue |= cThrTxFifo;
+
+  /* Writes the Almost Full threshold for Tx in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(FIFO_CONFIG1_TXAFTHR_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the almost full threshold for Tx FIFO.
+ * @note   The almost full threshold is encountered from the top of the FIFO. For example, if it is set to 7 the almost
+ *         full FIFO irq will be raised when the number of elements is equals to 96-7 = 89.
+ * @param  None.
+ * @retval uint8_t Almost full threshold for Tx FIFO.
+ */
+uint8_t SpiritLinearFifoGetAlmostFullThresholdTx(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the almost full threshold for Tx FIFO and returns the value */
+  g_xStatus = SpiritSpiReadRegisters(FIFO_CONFIG1_TXAFTHR_BASE, 1, &tempRegValue);
+
+  /* Build and returns value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ * @brief  Sets the almost empty threshold for the Tx FIFO. When the number of elements in Tx FIFO reaches this value an interrupt can can be generated to the MCU.
+ * @param  cThrTxFifo: almost empty threshold.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritLinearFifoSetAlmostEmptyThresholdTx(uint8_t cThrTxFifo)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_FIFO_THR(cThrTxFifo));
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(FIFO_CONFIG0_TXAETHR_BASE, 1, &tempRegValue);
+
+  /* Build the register value */
+  tempRegValue &= 0x80;
+  tempRegValue |= cThrTxFifo;
+
+  /* Writes the Almost Empty threshold for Tx in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(FIFO_CONFIG0_TXAETHR_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the almost empty threshold for Tx FIFO.
+ * @param  None.
+ * @retval uint8_t Almost empty threshold for Tx FIFO.
+ */
+uint8_t SpiritLinearFifoGetAlmostEmptyThresholdTx(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the almost empty threshold for TX FIFO and returns the value */
+  g_xStatus = SpiritSpiReadRegisters(FIFO_CONFIG0_TXAETHR_BASE, 1, &tempRegValue);
+
+  /* Build and return value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Management.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Management.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,364 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_Management.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   The management layer for SPIRIT1 library.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Management.h"
+
+/**
+* @addtogroup SPIRIT_Libraries
+* @{
+*/
+
+
+/**
+* @defgroup SPIRIT_MANAGEMENT              SPIRIT Management
+* @{
+*/
+
+/**
+* @brief  BS value to write in the SYNT0 register according to the selected band
+*/
+static const uint8_t s_vectcBandRegValue[4]={SYNT0_BS_6, SYNT0_BS_12, SYNT0_BS_16, SYNT0_BS_32};
+
+#define COMMUNICATION_STATE_TX          0
+#define COMMUNICATION_STATE_RX          1
+#define COMMUNICATION_STATE_NONE        2
+
+static uint32_t s_nDesiredFrequency;
+
+static volatile uint8_t s_cCommunicationState = COMMUNICATION_STATE_NONE;
+
+
+/**
+* @brief  Factor is: B/2 used in the formula for SYNTH word calculation
+*/
+static const uint8_t s_vectcBHalfFactor[4]={(HIGH_BAND_FACTOR/2), (MIDDLE_BAND_FACTOR/2), (LOW_BAND_FACTOR/2), (VERY_LOW_BAND_FACTOR/2)};
+
+
+/**
+* @defgroup SPIRIT_MANAGEMENT_FUNCTIONS    SPIRIT Management Functions
+* @{
+*/
+
+
+/**
+* @defgroup WORKAROUND_FUNCTIONS              SPIRIT Management Workaround Functions
+* @{
+*/
+
+/**
+* @brief  Private SpiritRadioSetFrequencyBase function only used in SpiritManagementWaVcoCalibration.
+* @param  lFBase the base carrier frequency expressed in Hz as unsigned word.
+* @retval None.
+*/
+void SpiritManagementSetFrequencyBase(uint32_t lFBase)
+{
+  uint32_t synthWord, Fc;
+  uint8_t band = 0, anaRadioRegArray[4], wcp;
+  
+  /* Check the parameter */
+  s_assert_param(IS_FREQUENCY_BAND(lFBase));
+  
+  /* Search the operating band */
+  if(IS_FREQUENCY_BAND_HIGH(lFBase))
+  {
+    band = HIGH_BAND;
+  }
+  else if(IS_FREQUENCY_BAND_MIDDLE(lFBase))
+  {
+    band = MIDDLE_BAND;
+  }
+  else if(IS_FREQUENCY_BAND_LOW(lFBase))
+  {
+    band = LOW_BAND;
+  }
+  else if(IS_FREQUENCY_BAND_VERY_LOW(lFBase))
+  {
+    band = VERY_LOW_BAND;
+  }
+  
+  int32_t FOffset  = SpiritRadioGetFrequencyOffset();
+  uint32_t lChannelSpace  = SpiritRadioGetChannelSpace();
+  uint8_t cChannelNum = SpiritRadioGetChannel();
+  
+  /* Calculates the channel center frequency */
+  Fc = lFBase + FOffset + lChannelSpace*cChannelNum;
+  
+  /* Reads the reference divider */
+  uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1;
+  
+  switch(band)
+  {
+  case VERY_LOW_BAND:
+    if(Fc<161281250)
+    {
+      SpiritCalibrationSelectVco(VCO_L);
+    }
+    else
+    {
+      SpiritCalibrationSelectVco(VCO_H);
+    }
+    break;
+    
+  case LOW_BAND:
+    if(Fc<322562500)
+    {
+      SpiritCalibrationSelectVco(VCO_L);
+    }
+    else
+    {
+      SpiritCalibrationSelectVco(VCO_H);
+    }
+    break;
+    
+  case MIDDLE_BAND:
+    if(Fc<430083334)
+    {
+      SpiritCalibrationSelectVco(VCO_L);
+    }
+    else
+    {
+      SpiritCalibrationSelectVco(VCO_H);
+    }
+    break;
+    
+  case HIGH_BAND:
+    if(Fc<860166667)
+    {
+      SpiritCalibrationSelectVco(VCO_L);
+    }
+    else
+    {
+      SpiritCalibrationSelectVco(VCO_H);
+    }
+  }
+  
+  /* Search the VCO charge pump word and set the corresponding register */
+  wcp = SpiritRadioSearchWCP(Fc);
+  
+  synthWord = (uint32_t)(lFBase*(((double)(FBASE_DIVIDER*cRefDiv*s_vectcBHalfFactor[band]))/SpiritRadioGetXtalFrequency()));
+  
+  /* Build the array of registers values for the analog part */
+  anaRadioRegArray[0] = (uint8_t)(((synthWord>>21)&(0x0000001F))|(wcp<<5));
+  anaRadioRegArray[1] = (uint8_t)((synthWord>>13)&(0x000000FF));
+  anaRadioRegArray[2] = (uint8_t)((synthWord>>5)&(0x000000FF));
+  anaRadioRegArray[3] = (uint8_t)(((synthWord&0x0000001F)<<3)| s_vectcBandRegValue[band]);
+  
+  /* Configures the needed Analog Radio registers */
+  g_xStatus = SpiritSpiWriteRegisters(SYNT3_BASE, 4, anaRadioRegArray);
+}
+
+uint8_t SpiritManagementWaVcoCalibration(void)
+{
+  uint8_t s_cVcoWordRx;
+  uint8_t s_cVcoWordTx;
+  uint32_t nFreq;
+  uint8_t cRestore = 0;
+  uint8_t cStandby = 0;
+  uint32_t xtal_frequency = SpiritRadioGetXtalFrequency();
+  
+  /* Enable the reference divider if the XTAL is between 48 and 52 MHz */
+  if(xtal_frequency>DOUBLE_XTAL_THR)
+  {
+    if(!SpiritRadioGetRefDiv())
+    {
+      cRestore = 1;
+      nFreq = SpiritRadioGetFrequencyBase();
+      SpiritRadioSetRefDiv(S_ENABLE);
+      SpiritManagementSetFrequencyBase(nFreq);
+    }
+  }
+  nFreq = SpiritRadioGetFrequencyBase();
+  
+  /* Increase the VCO current */
+  uint8_t tmp = 0x19; SpiritSpiWriteRegisters(0xA1,1,&tmp);
+  
+  SpiritCalibrationVco(S_ENABLE);
+  
+  SpiritRefreshStatus();
+  if(g_xStatus.MC_STATE == MC_STATE_STANDBY)
+  {
+    cStandby = 1;
+    SpiritCmdStrobeReady();
+    do{
+      SpiritRefreshStatus();
+      if(g_xStatus.MC_STATE == 0x13)
+      {
+        return 1;
+      }
+    }while(g_xStatus.MC_STATE != MC_STATE_READY); 
+  }
+  
+  SpiritCmdStrobeLockTx();
+  
+  do{
+    SpiritRefreshStatus();
+    if(g_xStatus.MC_STATE == 0x13)
+    {
+      return 1;
+    }
+  }while(g_xStatus.MC_STATE != MC_STATE_LOCK);
+  
+  s_cVcoWordTx = SpiritCalibrationGetVcoCalData();
+  
+  SpiritCmdStrobeReady();
+  
+  do{
+    SpiritRefreshStatus();
+  }while(g_xStatus.MC_STATE != MC_STATE_READY); 
+  
+    
+  SpiritCmdStrobeLockRx();
+  
+  do{
+    SpiritRefreshStatus();
+    if(g_xStatus.MC_STATE == 0x13)
+    {
+      return 1;
+    }
+  }while(g_xStatus.MC_STATE != MC_STATE_LOCK);
+  
+  s_cVcoWordRx = SpiritCalibrationGetVcoCalData();
+  
+  SpiritCmdStrobeReady();
+  
+  do{
+    SpiritRefreshStatus();
+    if(g_xStatus.MC_STATE == 0x13)
+    {
+      return 1;
+    }
+  }while(g_xStatus.MC_STATE != MC_STATE_READY);
+  
+  if(cStandby == 1)
+  {
+    SpiritCmdStrobeStandby();    
+  }
+  SpiritCalibrationVco(S_DISABLE);
+  
+  /* Disable the reference divider if the XTAL is between 48 and 52 MHz */
+  if(cRestore)
+  {
+    SpiritRadioSetRefDiv(S_DISABLE);    
+    SpiritManagementSetFrequencyBase(nFreq);
+  }
+  
+  /* Restore the VCO current */
+  tmp = 0x11; SpiritSpiWriteRegisters(0xA1,1,&tmp);
+  
+  SpiritCalibrationSetVcoCalDataTx(s_cVcoWordTx);
+  SpiritCalibrationSetVcoCalDataRx(s_cVcoWordRx);
+  
+  return 0;
+}
+
+
+void SpiritManagementWaCmdStrobeTx(void)
+{
+  if(s_cCommunicationState != COMMUNICATION_STATE_TX)
+  {
+    //uint32_t xtal_frequency = SpiritRadioGetXtalFrequency();
+    
+    /* To achive the max output power */
+    if(s_nDesiredFrequency>=150000000 && s_nDesiredFrequency<=470000000)
+    {
+      /* Optimal setting for Tx mode only */
+      SpiritRadioSetPACwc(LOAD_3_6_PF);
+    }
+    else
+    {
+      /* Optimal setting for Tx mode only */
+      SpiritRadioSetPACwc(LOAD_0_PF);
+    }
+    
+    uint8_t tmp = 0x11; SpiritSpiWriteRegisters(0xa9, 1, &tmp); /* Enable VCO_L buffer */
+    tmp = 0x20; SpiritSpiWriteRegisters(PM_CONFIG1_BASE, 1, &tmp); /* Set SMPS switching frequency */
+    
+    s_cCommunicationState = COMMUNICATION_STATE_TX;
+  }
+}
+
+
+void SpiritManagementWaCmdStrobeRx(void)
+{
+  if(s_cCommunicationState != COMMUNICATION_STATE_RX)
+  {    
+    uint8_t tmp = 0x98; SpiritSpiWriteRegisters(PM_CONFIG1_BASE, 1, &tmp); /* Set SMPS switching frequency */    
+    SpiritRadioSetPACwc(LOAD_0_PF); /* Set the correct CWC parameter */
+    
+    s_cCommunicationState = COMMUNICATION_STATE_RX;
+  }
+}
+
+void SpiritManagementWaTRxFcMem(uint32_t nDesiredFreq)
+{
+  s_cCommunicationState = COMMUNICATION_STATE_NONE;
+  s_nDesiredFrequency = nDesiredFreq;
+}
+
+
+void SpiritManagementWaExtraCurrent(void)
+{          
+  uint8_t tmp= 0xCA;SpiritSpiWriteRegisters(0xB2, 1, &tmp); 
+  tmp= 0x04;SpiritSpiWriteRegisters(0xA8, 1, &tmp); 
+  /* just a read to loose some microsecs more */
+  SpiritSpiReadRegisters(0xA8, 1, &tmp);
+  tmp= 0x00;SpiritSpiWriteRegisters(0xA8, 1, &tmp); 
+}
+
+/**
+* @}
+*/
+
+
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktBasic.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktBasic.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,615 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_PktBasic.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT Basic packets.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_PktBasic.h"
+#include "MCU_Interface.h"
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_PktBasic
+ * @{
+ */
+
+
+/**
+ * @defgroup PktBasic_Private_TypesDefinitions  Pkt Basic Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktBasic_Private_Defines           Pkt Basic Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktBasic_Private_Macros            Pkt Basic Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktBasic_Private_Variables          Pkt Basic Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+
+/**
+ * @defgroup PktBasic_Private_FunctionPrototypes        Pkt Basic Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktBasic_Private_Functions                 Pkt Basic Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Initializes the SPIRIT Basic packet according to the specified parameters in the PktBasicInit struct.
+ *         Notice that this function sets the autofiltering option on CRC if it is set to any value different from BASIC_NO_CRC.
+ * @param  pxPktBasicInit Basic packet init structure.
+ *         This parameter is a pointer to @ref PktBasicInit.
+ * @retval None.
+ */
+void SpiritPktBasicInit(PktBasicInit* pxPktBasicInit)
+{
+  uint8_t tempRegValue[4], i;
+
+  /* Check the parameters */
+  s_assert_param(IS_BASIC_PREAMBLE_LENGTH(pxPktBasicInit->xPreambleLength));
+  s_assert_param(IS_BASIC_SYNC_LENGTH(pxPktBasicInit->xSyncLength));
+  s_assert_param(IS_BASIC_CRC_MODE(pxPktBasicInit->xCrcMode));
+  s_assert_param(IS_BASIC_LENGTH_WIDTH_BITS(pxPktBasicInit->cPktLengthWidth));
+  s_assert_param(IS_BASIC_FIX_VAR_LENGTH(pxPktBasicInit->xFixVarLength));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktBasicInit->xAddressField));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktBasicInit->xFec));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktBasicInit->xDataWhitening));
+  s_assert_param(IS_BASIC_CONTROL_LENGTH(pxPktBasicInit->xControlLength));
+
+  /* Reads the PROTOCOL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue[0]);
+
+  /* Mask a reserved bit */
+  tempRegValue[0] &= ~0x20;
+
+  /* Always set the automatic packet filtering */
+  tempRegValue[0] |= PROTOCOL1_AUTO_PCKT_FLT_MASK;
+
+  /* Writes the value on register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue[0]);
+
+  /* Reads the PCKT_FLT_OPTIONS register */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+
+  /* Always reset the control and source filtering (also if it is not present in basic) */
+  tempRegValue[0] &= ~(PCKT_FLT_OPTIONS_SOURCE_FILTERING_MASK | PCKT_FLT_OPTIONS_CONTROL_FILTERING_MASK);
+
+  /* Writes the value on register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+
+  if(pxPktBasicInit->xAddressField == S_ENABLE)
+  {
+    tempRegValue[0]=0x08;
+  }
+  else
+  {
+    tempRegValue[0]=0x00;
+  }
+  /* Address and control length setting */
+  tempRegValue[0] |= ((uint8_t) pxPktBasicInit->xControlLength);
+
+  /* Packet format and width length setting */
+  pxPktBasicInit->cPktLengthWidth == 0 ? pxPktBasicInit->cPktLengthWidth=1 : pxPktBasicInit->cPktLengthWidth;
+  tempRegValue[1] = ((uint8_t) PCKTCTRL3_PCKT_FRMT_BASIC) | ((uint8_t)(pxPktBasicInit->cPktLengthWidth-1));
+
+  /* Preamble, sync and fixed or variable length setting */
+  tempRegValue[2] = ((uint8_t) pxPktBasicInit->xPreambleLength) | ((uint8_t) pxPktBasicInit->xSyncLength) |
+                    ((uint8_t) pxPktBasicInit->xFixVarLength);
+
+  /* CRC length, whitening and FEC setting */
+  tempRegValue[3] = (uint8_t) pxPktBasicInit->xCrcMode;
+
+  if(pxPktBasicInit->xDataWhitening == S_ENABLE)
+  {
+     tempRegValue[3] |= PCKTCTRL1_WHIT_MASK;
+  }
+
+  if(pxPktBasicInit->xFec == S_ENABLE)
+  {
+     tempRegValue[3] |= PCKTCTRL1_FEC_MASK;
+  }
+
+  /* Writes registers */
+  SpiritSpiWriteRegisters(PCKTCTRL4_BASE, 4, tempRegValue);
+
+  /* Sync words setting */
+  for(i=0;i<4;i++)
+  {
+    if(i<3-(pxPktBasicInit->xSyncLength >>1))
+    {
+      tempRegValue[i]=0;
+    }
+    else
+    {
+      tempRegValue[i] = (uint8_t)(pxPktBasicInit->lSyncWords>>(8*i));
+    }
+  }
+
+  /* Sets CRC check bit */
+  if(pxPktBasicInit->xCrcMode == PKT_NO_CRC)
+  {
+    SpiritPktBasicFilterOnCrc(S_DISABLE);
+  }
+  else
+  {
+    SpiritPktBasicFilterOnCrc(S_ENABLE);
+  }
+
+  
+  g_xStatus = SpiritSpiWriteRegisters(SYNC4_BASE, 4, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the SPIRIT Basic packet structure according to the specified parameters in the registers.
+ * @param  pxPktBasicInit Basic packet init structure.
+ *         This parameter is a pointer to @ref PktBasicInit.
+ * @retval None.
+ */
+void SpiritPktBasicGetInfo(PktBasicInit* pxPktBasicInit)
+{
+  uint8_t tempRegValue[10];
+
+  /* Reads registers */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL4_BASE, 10, tempRegValue);
+
+  /* Length width */
+  pxPktBasicInit->cPktLengthWidth=(tempRegValue[1] & 0x0F)+1;
+
+  /* Address field */
+  pxPktBasicInit->xAddressField=(SpiritFunctionalState)((tempRegValue[0]>>3) & 0x01);
+
+  /* Control length */
+  pxPktBasicInit->xControlLength=(BasicControlLength)(tempRegValue[0] & 0x07);
+
+  /* CRC mode */
+  pxPktBasicInit->xCrcMode=(BasicCrcMode)(tempRegValue[3] & 0xE0);
+
+  /* Whitening */
+  pxPktBasicInit->xDataWhitening=(SpiritFunctionalState)((tempRegValue[3] >> 4) & 0x01);
+
+  /* FEC */
+  pxPktBasicInit->xFec=(SpiritFunctionalState)(tempRegValue[3] & 0x01);
+
+  /* FIX or VAR bit */
+  pxPktBasicInit->xFixVarLength=(BasicFixVarLength)(tempRegValue[2] & 0x01);
+
+  /* Preamble length */
+  pxPktBasicInit->xPreambleLength=(BasicPreambleLength)(tempRegValue[2] & 0xF8);
+
+  /* Sync length */
+  pxPktBasicInit->xSyncLength=(BasicSyncLength)(tempRegValue[2] & 0x06);
+
+  /* sync Words */
+  pxPktBasicInit->lSyncWords=0;
+  for(uint8_t i=0 ; i<4 ; i++)
+  {
+      if(i>2-(((uint8_t)pxPktBasicInit->xSyncLength) >>1))
+      {
+        pxPktBasicInit->lSyncWords |= (uint32_t)(tempRegValue[i+6])<<(8*i);
+      }
+  }
+
+}
+
+
+/**
+ * @brief  Initializes the SPIRIT Basic packet addresses according to the specified
+ *         parameters in the PktBasicAddressesInit struct.
+ * @param  pxPktBasicAddresses Basic packet addresses init structure.
+ *         This parameter is a pointer to @ref PktBasicAddresses.
+ * @retval None.
+ */
+void SpiritPktBasicAddressesInit(PktBasicAddressesInit* pxPktBasicAddresses)
+{
+  uint8_t tempRegValue[3];
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktBasicAddresses->xFilterOnMyAddress));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktBasicAddresses->xFilterOnMulticastAddress));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktBasicAddresses->xFilterOnBroadcastAddress));
+
+
+  /* Reads the PCKT_FLT_OPTIONS ragister */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+  
+  /* Enables or disables filtering on my address */
+  if(pxPktBasicAddresses->xFilterOnMyAddress == S_ENABLE)
+  {
+    tempRegValue[0] |= PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK;
+  }
+  
+  /* Enables or disables filtering on multicast address */
+  if(pxPktBasicAddresses->xFilterOnMulticastAddress == S_ENABLE)
+  {
+    tempRegValue[0] |= PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK;
+  }
+  
+  /* Enables or disables filtering on broadcast address */
+  if(pxPktBasicAddresses->xFilterOnBroadcastAddress == S_ENABLE)
+  {
+    tempRegValue[0] |= PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK;
+  }
+  
+  /* Writes the new value on the PCKT_FLT_OPTIONS register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+  
+  /* Fills the array with the addresses passed in the structure */
+  tempRegValue[0] = pxPktBasicAddresses->cBroadcastAddress;
+  tempRegValue[1] = pxPktBasicAddresses->cMulticastAddress;
+  tempRegValue[2] = pxPktBasicAddresses->cMyAddress;
+  
+  /* Writes values on the PCKT_FLT_GOALS registers */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_BROADCAST_BASE, 3, tempRegValue);
+  
+  
+}
+
+
+/**
+ * @brief  Returns the SPIRIT Basic packet addresses structure according to the specified
+ *         parameters in the registers.
+ * @param  pxPktBasicAddresses Basic packet addresses init structure.
+ *         This parameter is a pointer to @ref PktBasicAddresses.
+ * @retval None.
+ */
+void SpiritPktBasicGetAddressesInfo(PktBasicAddressesInit* pxPktBasicAddresses)
+{
+  uint8_t tempRegValue[3];
+
+  /* Reads values on the PCKT_FLT_GOALS registers */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_BROADCAST_BASE, 3, tempRegValue);
+
+  /* Fit the structure with the read addresses */
+  pxPktBasicAddresses->cBroadcastAddress = tempRegValue[0];
+  pxPktBasicAddresses->cMulticastAddress = tempRegValue[1];
+  pxPktBasicAddresses->cMyAddress = tempRegValue[2];
+
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+
+  /* Fit the structure with the read filtering bits */
+  pxPktBasicAddresses->xFilterOnBroadcastAddress = (SpiritFunctionalState)((tempRegValue[0] >> 1) & 0x01);
+  pxPktBasicAddresses->xFilterOnMulticastAddress = (SpiritFunctionalState)((tempRegValue[0] >> 2) & 0x01);
+  pxPktBasicAddresses->xFilterOnMyAddress = (SpiritFunctionalState)((tempRegValue[0] >> 3) & 0x01);
+
+}
+
+
+/**
+ * @brief  Configures the Basic packet format as packet used by SPIRIT.
+ * @param  None.
+ * @retval None.
+ */
+void SpiritPktBasicSetFormat(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Build the new value. Also set to 0 the direct RX mode bits */
+  tempRegValue &= 0x0F;
+  tempRegValue |= (uint8_t)PCKTCTRL3_PCKT_FRMT_BASIC;
+
+  /* Writes the  value on the PCKTCTRL3 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Reads the PCKTCTRL1_BASE register */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Build the new value. Set to 0 the direct TX mode bits */
+  tempRegValue &= 0xF3;
+
+  /* Writes the value on the PCKTCTRL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Reads the PROTOCOL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Mask a reserved bit */
+  tempRegValue &= ~0x20;
+
+  /* Writes the value on register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+}
+
+
+/**
+ * @brief  Sets the address length for SPIRIT Basic packets.
+ * @param  xAddressField length of ADDRESS in bytes.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktBasicAddressField(SpiritFunctionalState xAddressField)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xAddressField));
+
+  /* Reads the PCKTCTRL4 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL4_BASE, 1, &tempRegValue);
+
+  /* Build the address length for the register */
+  if(xAddressField==S_ENABLE)
+  {
+    tempRegValue |= 0x08;
+  }
+  else
+  {
+    tempRegValue &= 0x07;
+  }
+
+  /* Writes the new value on the PCKTCTRL4 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL4_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Specifies if the Address field for SPIRIT Basic packets is enabled or disabled.
+ * @param  None.
+ * @retval SpiritFunctionalState Notifies if the address field is enabled or disabled.
+ */
+SpiritFunctionalState SpiritPktBasicGetAddressField(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PCKTCTRL4 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL4_BASE, 1, &tempRegValue);
+
+  /* Returns the address field value */
+  if(tempRegValue & PCKTCTRL4_ADDRESS_LEN_MASK)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+
+}
+
+
+/**
+ * @brief  Sets the payload length for SPIRIT Basic packets. Since the packet length
+ *         depends from the address and the control field size, this
+ *         function reads the correspondent registers in order to determine
+ *         the correct packet length to be written.
+ * @param  nPayloadLength payload length in bytes.
+ *         This parameter is an uint16_t.
+ * @retval None.
+ */
+void SpiritPktBasicSetPayloadLength(uint16_t nPayloadLength)
+{
+  uint8_t tempRegValue[2];
+  uint16_t overSize=0;
+
+  /* Computes the oversize (address + control) size */
+  if(SpiritPktBasicGetAddressField())
+  {
+    overSize=1;
+  }
+  overSize += (uint16_t) SpiritPktBasicGetControlLength();
+
+  /* Computes PCKTLEN0 value from nPayloadLength */
+  tempRegValue[1]=BASIC_BUILD_PCKTLEN0(nPayloadLength+overSize);
+  /* Computes PCKTLEN1 value from nPayloadLength */
+  tempRegValue[0]=BASIC_BUILD_PCKTLEN1(nPayloadLength+overSize);
+
+  /* Writes data on the PCKTLEN1/0 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTLEN1_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the payload length for SPIRIT Basic packets. Since the
+ *         packet length depends from the address and the control
+ *         field size, this function reads the correspondent
+ *         registers in order to determine the correct payload length
+ *         to be returned.
+ * @param  None.
+ * @retval uint16_t Payload length in bytes.
+ */
+uint16_t SpiritPktBasicGetPayloadLength(void)
+{
+  uint8_t tempRegValue[2];
+  uint16_t overSize=0;
+
+  /* Computes the oversize (address + control) size */
+  if(SpiritPktBasicGetAddressField())
+  {
+    overSize=1;
+  }
+  overSize += (uint16_t) SpiritPktBasicGetControlLength();
+
+  /* Reads the packet length registers */
+  g_xStatus = SpiritSpiReadRegisters(PCKTLEN1_BASE, 2, tempRegValue);
+
+  /* Returns the packet length */
+  return ((((uint16_t)tempRegValue[0])<<8) + (uint16_t) tempRegValue[1]) - overSize;
+}
+
+/**
+ * @brief  Returns the packet length field of the received packet.
+ * @param  None.
+ * @retval uint16_t Packet length.
+ */
+uint16_t SpiritPktBasicGetReceivedPktLength(void)
+{
+  uint8_t tempRegValue[2];
+  uint16_t overSize=0;
+
+  /* Computes the oversize (address + control) size */
+  if(SpiritPktBasicGetAddressField())
+  {
+    overSize=1;
+  }
+  overSize += (uint16_t) SpiritPktBasicGetControlLength();
+  
+  /* Reads the RX_PCKT_LENx registers value */
+  g_xStatus = SpiritSpiReadRegisters(RX_PCKT_LEN1_BASE, 2, tempRegValue);
+
+  /* Rebuild and return the length field */
+  return (((((uint16_t) tempRegValue[0]) << 8) + (uint16_t) tempRegValue[1]) - overSize);
+}
+
+/**
+ * @brief  Computes and sets the variable payload length for SPIRIT Basic packets.
+ * @param  nMaxPayloadLength payload length in bytes.
+ *         This parameter is an uint16_t.
+ * @param  xAddressField Enable or Disable Address Field.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @param  xControlLength Control length in bytes.
+ *         This parameter can be any value of @ref BasicControlLength.
+ * @retval None.
+ */
+void SpiritPktBasicSetVarLengthWidth(uint16_t nMaxPayloadLength, SpiritFunctionalState xAddressField, BasicControlLength xControlLength)
+{
+  uint8_t tempRegValue,
+          addressLength,
+          i;
+  uint32_t packetLength;
+
+  /* Sets the address length according to xAddressField */
+  if(xAddressField == S_ENABLE)
+  {
+    addressLength=1;
+  }
+  else
+  {
+    addressLength=0;
+  }
+
+  /* packet length = payload length + address length + control length */
+  packetLength=nMaxPayloadLength+addressLength+xControlLength;
+
+  /* Computes the number of bits */
+  for(i=0;i<16;i++)
+  {
+    if(packetLength == 0) break;
+    {
+    packetLength >>= 1;
+    }
+  }
+  i==0 ? i=1 : i;
+
+  /* Reads the PCKTCTRL3 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Build value for the length width */
+  tempRegValue &= ~PCKTCTRL3_LEN_WID_MASK;
+  tempRegValue |= (uint8_t)(i-1);
+
+  /* Writes the PCKTCTRL3 register value */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+}
+
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktCommon.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktCommon.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1453 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_PktCommon.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of the common features of SPIRIT packets.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_PktCommon.h"
+#include "MCU_Interface.h"
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_PktCommon
+ * @{
+ */
+
+
+/**
+ * @defgroup PktCommon_Private_TypesDefinitions         Pkt Common Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktCommon_Private_Defines                  Pkt Common Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktCommon_Private_Macros                   Pkt Common Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktCommon_Private_Variables                Pkt Common Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+
+/**
+ * @defgroup PktCommon_Private_FunctionPrototypes       Pkt Common Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktCommon_Private_Functions                Pkt Common Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Sets the CONTROL field length for SPIRIT packets.
+ * @param  xControlLength length of CONTROL field in bytes.
+ *         This parameter can be any value of @ref PktControlLength.
+ * @retval None.
+ */
+void SpiritPktCommonSetControlLength(PktControlLength xControlLength)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_CONTROL_LENGTH(xControlLength));
+
+  /* Reads the PCKTCTRL4 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL4_BASE, 1, &tempRegValue);
+
+  /* Set the control length */
+  tempRegValue &= ~PCKTCTRL4_CONTROL_LEN_MASK;
+  tempRegValue |= (uint8_t)xControlLength;
+
+  /* Writes the new value on the PCKTCTRL4 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL4_BASE, 1, &tempRegValue);
+}
+
+
+/**
+ * @brief  Returns the CONTROL field length for SPIRIT packets.
+ * @param  None.
+ * @retval uint8_t Control field length.
+ */
+uint8_t SpiritPktCommonGetControlLength(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PCKTCTRL4 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL4_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return value */
+  return (tempRegValue & PCKTCTRL4_CONTROL_LEN_MASK);
+}
+
+
+/**
+ * @brief  Sets the PREAMBLE field Length mode for SPIRIT packets.
+ * @param  xPreambleLength length of PREAMBLE field in bytes.
+ *         This parameter can be any value of @ref PktPreambleLength.
+ * @retval None.
+ */
+void SpiritPktCommonSetPreambleLength(PktPreambleLength xPreambleLength)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_PREAMBLE_LENGTH(xPreambleLength));
+
+  /* Reads the PCKTCTRL2 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL2_BASE, 1, &tempRegValue);
+
+  /* Set the preamble length */
+  tempRegValue &= ~PCKTCTRL2_PREAMBLE_LENGTH_MASK;
+  tempRegValue |= (uint8_t)xPreambleLength;
+
+  /* Writes the new value on the PCKTCTRL2 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL2_BASE, 1, &tempRegValue);
+}
+
+
+/**
+ * @brief  Returns the PREAMBLE field Length mode for SPIRIT packets.
+ * @param  None.
+ * @retval uint8_t Preamble field length in bytes.
+ */
+uint8_t SpiritPktCommonGetPreambleLength(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PCKTCTRL2 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL2_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return value */
+  return ((tempRegValue & PCKTCTRL2_PREAMBLE_LENGTH_MASK)>>3) + 1;
+
+}
+
+
+/**
+ * @brief  Sets the SYNC field Length for SPIRIT packets.
+ * @param  xSyncLength length of SYNC field in bytes.
+ *         This parameter can be any value of @ref PktSyncLength.
+ * @retval None.
+ */
+void SpiritPktCommonSetSyncLength(PktSyncLength xSyncLength)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_SYNC_LENGTH(xSyncLength));
+
+  /* Reads the PCKTCTRL2 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL2_BASE, 1, &tempRegValue);
+
+  /* Set the sync length */
+  tempRegValue &= ~PCKTCTRL2_SYNC_LENGTH_MASK;
+  tempRegValue |= (uint8_t)xSyncLength;
+
+  /* Writes the new value on the PCKTCTRL2 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the SYNC field Length for SPIRIT packets.
+ * @param  None.
+ * @retval uint8_t Sync field length in bytes.
+ */
+uint8_t SpiritPktCommonGetSyncLength(void)
+{
+  uint8_t tempRetValue;
+
+  /* Reads the PCKTCTRL2 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL2_BASE, 1, &tempRetValue);
+
+  /* Rebuild and return value */
+  return ((tempRetValue & PCKTCTRL2_SYNC_LENGTH_MASK)>>1) + 1;
+
+}
+
+
+/**
+ * @brief  Sets fixed or variable payload length mode for SPIRIT packets.
+ * @param  xFixVarLength variable or fixed length.
+ *         PKT_FIXED_LENGTH_VAR -> variable (the length is extracted from the received packet).
+ *         PKT_FIXED_LENGTH_FIX -> fix (the length is set by PCKTLEN0 and PCKTLEN1).
+ * @retval None.
+ */
+void SpiritPktCommonSetFixVarLength(PktFixVarLength xFixVarLength)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_FIX_VAR_LENGTH(xFixVarLength));
+
+  /* Reads the PCKTCTRL2 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL2_BASE, 1, &tempRegValue);
+
+  /* Set fixed or variable address mode */
+  tempRegValue &= ~PCKTCTRL2_FIX_VAR_LEN_MASK;
+  tempRegValue |= (uint8_t)xFixVarLength;
+
+  /* Writes the new value on the PCKTCTRL2 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Enables or Disables the filtering on CRC.
+ * @param  xNewState new state for CRC_CHECK.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonFilterOnCrc(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PCKT_FLT_OPTIONS register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Modify the register value: enable or disable the CRC filtering */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PCKT_FLT_OPTIONS_CRC_CHECK_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PCKT_FLT_OPTIONS_CRC_CHECK_MASK;
+  }
+
+  /* Writes the PCKT_FLT_OPTIONS register value */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the CRC filtering enable bit.
+ * @param  None.
+ * @retval SpiritFunctionalState CRC filtering.
+ */
+SpiritFunctionalState SpiritPktCommonGetFilterOnCrc(void)
+{
+  uint8_t tempRegValue;
+
+
+  /* Reads the PCKT_FLT_OPTIONS register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Check the CRC filtering bit */
+  if(tempRegValue & PCKT_FLT_OPTIONS_CRC_CHECK_MASK)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+
+}
+
+
+/**
+ * @brief  Sets the CRC mode for SPIRIT packets.
+ * @param  xCrcMode length of CRC field in bytes.
+ *         This parameter can be any value of @ref PktCrcMode.
+ * @retval None.
+ */
+void SpiritPktCommonSetCrcMode(PktCrcMode xCrcMode)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_CRC_MODE(xCrcMode));
+
+  /* Reads the PCKTCTRL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Build data to write setting the CRC mode */
+  tempRegValue &= ~PCKTCTRL1_CRC_MODE_MASK;
+  tempRegValue |= (uint8_t)xCrcMode;
+
+  /* Writes the new value on the PCKTCTRL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the CRC mode for SPIRIT packets.
+ * @param  None.
+ * @retval PktCrcMode Crc mode.
+ */
+PktCrcMode SpiritPktCommonGetCrcMode(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PCKTCTRL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return value */
+  return (PktCrcMode)(tempRegValue & 0xE0);
+
+}
+
+
+/**
+ * @brief  Enables or Disables WHITENING for SPIRIT packets.
+ * @param  xNewState new state for WHITENING mode.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonWhitening(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PCKTCTRL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Build data to write: set or reset the whitening enable bit */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PCKTCTRL1_WHIT_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PCKTCTRL1_WHIT_MASK;
+  }
+
+  /* Writes the new value on the PCKTCTRL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Enables or Disables FEC for SPIRIT packets.
+ * @param  xNewState new state for FEC mode.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonFec(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PCKTCTRL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Build data to write: set or reset the FEC enable bit */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PCKTCTRL1_FEC_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PCKTCTRL1_FEC_MASK;
+  }
+
+  /* Writes data on the PCKTCTRL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets a specific SYNC word for SPIRIT packets.
+ * @param  xSyncX SYNC word number to be set.
+ *         This parameter can be any value of @ref PktSyncX.
+ * @param  cSyncWord SYNC word.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritPktCommonSetSyncxWord(PktSyncX xSyncX ,  uint8_t cSyncWord)
+{
+  uint8_t tempRegAddress;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_SYNCx(xSyncX));
+
+  /* Set the specified address */
+  switch(xSyncX)
+  {
+    case PKT_SYNC_WORD_1:
+      tempRegAddress=SYNC1_BASE;
+      break;
+    case PKT_SYNC_WORD_2:
+      tempRegAddress=SYNC2_BASE;
+      break;
+    case PKT_SYNC_WORD_3:
+      tempRegAddress=SYNC3_BASE;
+      break;
+    default:
+      tempRegAddress=SYNC4_BASE;
+      break;
+  }
+
+  /* Writes value on the selected register */
+  g_xStatus = SpiritSpiWriteRegisters(tempRegAddress, 1, &cSyncWord);
+
+}
+
+
+/**
+ * @brief  Returns a specific SYNC word for SPIRIT packets.
+ * @param  xSyncX SYNC word number to be get.
+ *         This parameter can be any value of @ref PktSyncX.
+ * @retval uint8_t Sync word x.
+ */
+uint8_t SpiritPktCommonGetSyncxWord(PktSyncX xSyncX)
+{
+  uint8_t tempRegAddress, tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_SYNCx(xSyncX));
+
+  /* Set the specified address */
+  switch(xSyncX)
+  {
+    case PKT_SYNC_WORD_1:
+      tempRegAddress=SYNC1_BASE;
+      break;
+    case PKT_SYNC_WORD_2:
+      tempRegAddress=SYNC2_BASE;
+      break;
+    case PKT_SYNC_WORD_3:
+      tempRegAddress=SYNC3_BASE;
+      break;
+    default:
+      tempRegAddress=SYNC4_BASE;
+      break;
+  }
+
+  /* Reads the selected register value */
+  g_xStatus = SpiritSpiReadRegisters(tempRegAddress, 1, &tempRegValue);
+
+  /* Returns the read value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets multiple SYNC words for SPIRIT packets.
+ * @param  lSyncWords SYNC words to be set with format: 0x|SYNC1|SYNC2|SYNC3|SYNC4|.
+ *         This parameter is a uint32_t.
+ * @param  xSyncLength SYNC length in bytes. The 32bit word passed will be stored in the SYNCx registers from the MSb
+ *         until the number of bytes in xSyncLength has been stored.
+ *         This parameter is a @ref PktSyncLength.
+ * @retval None.
+ */
+void SpiritPktCommonSetSyncWords(uint32_t lSyncWords, PktSyncLength xSyncLength)
+{
+  uint8_t tempRegValue[4];
+
+  /* Split the 32-bit value in 4 8-bit values */
+  for(uint8_t i=0 ; i<4 ; i++)
+  {
+	if(i< ((3-xSyncLength) >>1) )
+    {
+      tempRegValue[i]=0;
+    }
+    else
+    {
+      tempRegValue[i]=(uint8_t)(lSyncWords>>(8*i));
+    }
+  }
+
+  /* Writes SYNC value on the SYNCx registers */
+  g_xStatus = SpiritSpiWriteRegisters(SYNC4_BASE, 4, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns multiple SYNC words for SPIRIT packets.
+ * @param  xSyncLength SYNC length in bytes. The 32bit word passed will be stored in the SYNCx registers from the MSb
+ *         until the number of bytes in xSyncLength has been stored.
+ *         This parameter is a pointer to @ref PktSyncLength.
+ * @retval uint32_t Sync words. The format of the read 32 bit word is 0x|SYNC1|SYNC2|SYNC3|SYNC4|.
+ */
+uint32_t SpiritPktCommonGetSyncWords(PktSyncLength xSyncLength)
+{
+  uint8_t tempRegValue[4];
+  uint32_t tempRetValue=0;
+
+  /* Reads the SYNCx registers value */
+  g_xStatus = SpiritSpiReadRegisters(SYNC4_BASE, 4, tempRegValue);
+
+  /* Rebuild the SYNC words */
+  for(uint8_t i=0 ; i<4 ; i++)
+  {
+    if(i>2-(xSyncLength >>1))
+    {
+      tempRetValue |= tempRegValue[i]<<(8*i);
+    }
+  }
+
+  /* Return SYNC words */
+  return tempRetValue;
+
+}
+
+
+/**
+ * @brief  Returns the variable length width (in number of bits).
+ * @param  None.
+ * @retval uint8_t Variable length width in bits.
+ */
+uint8_t SpiritPktCommonGetVarLengthWidth(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PCKTCTRL3 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return value */
+  return (tempRegValue & PCKTCTRL3_LEN_WID_MASK)+1;
+
+}
+
+
+/**
+ * @brief  Sets the destination address for the Tx packet.
+ * @param  cAddress Destination address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritPktCommonSetDestinationAddress(uint8_t cAddress)
+{
+  /* Writes value on PCKT_FLT_GOALS_SOURCE_ADDR register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_SOURCE_ADDR_BASE, 1, &cAddress);
+
+}
+
+
+/**
+ * @brief  Returns the settled destination address.
+ * @param  None.
+ * @retval uint8_t Transmitted destination address.
+ */
+uint8_t SpiritPktCommonGetTransmittedDestAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads value on the PCKT_FLT_GOALS_SOURCE_ADDR register */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_SOURCE_ADDR_BASE, 1, &tempRegValue);
+
+  /* Return value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets the node my address. When the filtering on my address is on, if the destination address extracted from the received packet is equal to the content of the
+ *         my address, then the packet is accepted (this is the address of the node).
+ * @param  cAddress Address of the present node.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritPktCommonSetMyAddress(uint8_t cAddress)
+{
+  /* Writes value on the PCKT_FLT_GOALS_TX_ADDR register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_TX_ADDR_BASE, 1, &cAddress);
+
+}
+
+
+/**
+ * @brief  Returns the address of the present node.
+ * @param  None.
+ * @retval uint8_t My address (address of this node).
+ */
+uint8_t SpiritPktCommonGetMyAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads value on the PCKT_FLT_GOALS_TX_ADDR register */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_TX_ADDR_BASE, 1, &tempRegValue);
+
+  /* Return value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets the broadcast address. If the destination address extracted from the received packet is equal to the content of the
+ *         BROADCAST_ADDR register, then the packet is accepted.
+ * @param  cAddress Broadcast address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritPktCommonSetBroadcastAddress(uint8_t cAddress)
+{
+  /* Writes value on the PCKT_FLT_GOALS_BROADCAST register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_BROADCAST_BASE, 1, &cAddress);
+
+}
+
+
+/**
+ * @brief  Returns the broadcast address.
+ * @param  None.
+ * @retval uint8_t Broadcast address.
+ */
+uint8_t SpiritPktCommonGetBroadcastAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads value on the PCKT_FLT_GOALS_BROADCAST register */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_BROADCAST_BASE, 1, &tempRegValue);
+
+  /* Return value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets the multicast address. When the multicast filtering is on, if the destination address extracted from the received packet is equal to the content of the
+ *         MULTICAST_ADDR register, then the packet is accepted.
+ * @param  cAddress Multicast address.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritPktCommonSetMulticastAddress(uint8_t cAddress)
+{
+  /* Writes value on the PCKT_FLT_GOALS_MULTICAST register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_MULTICAST_BASE, 1, &cAddress);
+
+}
+
+
+/**
+ * @brief  Returns the multicast address.
+ * @param  None.
+ * @retval uint8_t Multicast address.
+ */
+uint8_t SpiritPktCommonGetMulticastAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads value on the PCKT_FLT_GOALS_MULTICAST register */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_MULTICAST_BASE, 1, &tempRegValue);
+
+  /* Return value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets the control mask. The 1 bits of the CONTROL_MASK indicate the
+ *         bits to be used in filtering. (All 0s no filtering)
+ * @param  lMask Control mask.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+void SpiritPktCommonSetCtrlMask(uint32_t lMask)
+{
+  uint8_t tempRegValue[4];
+
+  /* Split the 32-bit value in 4 8-bit values */
+  tempRegValue[0] = (uint8_t) lMask;
+  tempRegValue[1] = (uint8_t)(lMask >> 8);
+  tempRegValue[2] = (uint8_t)(lMask >> 16);
+  tempRegValue[3] = (uint8_t)(lMask >> 24);
+
+  /* Writes values on the CKT_FLT_GOALS_CONTROLx_MASK registers */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_CONTROL0_MASK_BASE, 4, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the control mask. The 1 bits of the CONTROL_MASK indicate the
+ *         bits to be used in filtering. (All 0s no filtering)
+ * @param  None.
+ * @retval uint32_t Control mask.
+ */
+uint32_t SpiritPktCommonGetCtrlMask(void)
+{
+  uint8_t tempRegValue[4];
+  uint32_t tempRetValue=0;
+
+  /* Reads the PCKT_FLT_GOALS_CONTROLx_MASK registers */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_CONTROL0_MASK_BASE, 4, tempRegValue);
+
+  /* Rebuild the control mask value on a 32-bit integer variable */
+  for(uint8_t i=0 ; i<4 ; i++)
+  {
+    tempRetValue |= ((uint32_t)tempRegValue[i])<<(8*i);
+  }
+
+  /* Return value */
+  return tempRetValue;
+}
+
+/**
+ * @brief  Sets the control field reference. If the bits enabled by the CONTROL_MASK
+ *         match the ones of the control fields extracted from the received packet
+ *         then the packet is accepted.
+ * @param  lReference Control reference.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+void SpiritPktCommonSetCtrlReference(uint32_t lReference)
+{
+  uint8_t tempRegValue[4];
+
+  /* Split the 32-bit value in 4 8-bit values */
+  tempRegValue[0] = (uint8_t) lReference;
+  tempRegValue[1] = (uint8_t)(lReference >> 8);
+  tempRegValue[2] = (uint8_t)(lReference >> 16);
+  tempRegValue[3] = (uint8_t)(lReference >> 24);
+
+  /* Writes values on the CKT_FLT_GOALS_CONTROLx_FIELD registers */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_CONTROL0_FIELD_BASE, 4, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the control field reference.
+ * @param  None.
+ * @retval uint32_t Control reference.
+ */
+uint32_t SpiritPktCommonGetCtrlReference(void)
+{
+  uint8_t tempRegValue[4];
+  uint32_t tempRetValue=0;
+
+  /* Reads the PCKT_FLT_GOALS_CONTROLx_FIELD registers */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_CONTROL0_FIELD_BASE, 4, tempRegValue);
+
+  /* Rebuild the control mask value on a 32-bit integer variable */
+  for(uint8_t i=0 ; i<4 ; i++)
+  {
+    tempRetValue |= ((uint32_t)tempRegValue[i])<<(8*i);
+  }
+
+  /* Return value */
+  return tempRetValue;
+}
+
+
+/**
+ * @brief  Sets the TX control field.
+ * @param  lField Tx contro field.
+ *         This parameter is an uint32_t.
+ * @retval None.
+ */
+void SpiritPktCommonSetTransmittedCtrlField(uint32_t lField)
+{
+  uint8_t tempRegValue[4];
+
+  /* Split the 32-bit value in 4 8-bit values */
+  tempRegValue[3] = (uint8_t) lField;
+  tempRegValue[2] = (uint8_t)(lField >> 8);
+  tempRegValue[1] = (uint8_t)(lField >> 16);
+  tempRegValue[0] = (uint8_t)(lField >> 24);
+
+  /* Writes value on the TX_CTRL_FIELDx register */
+  g_xStatus = SpiritSpiWriteRegisters(TX_CTRL_FIELD3_BASE, 4, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the Tx control field.
+ * @param  None.
+ * @retval uint32_t Control field of the transmitted packet.
+ */
+uint32_t SpiritPktCommonGetTransmittedCtrlField(void)
+{
+  uint8_t tempRegValue[4];
+  uint32_t tempRetValue=0;
+
+  /* Reads the TX_CTRL_FIELDx registers */
+  g_xStatus = SpiritSpiReadRegisters(TX_CTRL_FIELD3_BASE, 4, tempRegValue);
+
+  /* Rebuild value: build a 32-bit value from the read bytes */
+  for(uint8_t i=0 ; i<4 ; i++)
+  {
+    tempRetValue |= ((uint32_t)tempRegValue[i])<<(8*(3-i));
+  }
+
+  /* Return value */
+  return tempRetValue;
+
+}
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with My address.
+ * @param  xNewState new state for DEST_VS_SOURCE_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonFilterOnMyAddress(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+   /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+
+  /* Modify the register value: set or reset the TX source address control */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Set or reset the DESTINATION vs TX enabling bit */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK;
+  }
+
+  /* Writes the new value on the PCKT_FLT_OPTIONS register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with multicast address.
+ * @param  xNewState new state for DEST_VS_MULTICAST_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonFilterOnMulticastAddress(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PCKT_FLT_OPTIONS register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Enable or disable the filtering option */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK;
+  }
+
+  /* Writes the new value on the PCKT_FLT_OPTIONS register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  If enabled RX packet is accepted if its destination address matches with broadcast address.
+ * @param  xNewState new state for DEST_VS_BROADCAST_ADDRESS.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonFilterOnBroadcastAddress(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Enable or disable the filtering option */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK;
+  }
+
+  /* Writes the new value on the PCKT_FLT_OPTIONS register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the enable bit of the my address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+SpiritFunctionalState SpiritPktCommonGetFilterOnMyAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Gets the enable/disable bit in form of SpiritFunctionalState type */
+  if(tempRegValue & 0x08)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+
+}
+
+/**
+ * @brief  Returns the enable bit of the multicast address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+SpiritFunctionalState SpiritPktCommonGetFilterOnMulticastAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Get the enable/disable bit in form of SpiritFunctionalState type */
+  if(tempRegValue & 0x04)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+
+}
+
+/**
+ * @brief  Returns the enable bit of the broadcast address filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+SpiritFunctionalState SpiritPktCommonGetFilterOnBroadcastAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Get the enable/disable bit in form of SpiritFunctionalState type */
+  if(tempRegValue & 0x02)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+
+}
+
+
+/**
+ * @brief  Returns the destination address of the received packet.
+ * @param  None.
+ * @retval uint8_t Destination address of the received address.
+ */
+uint8_t SpiritPktCommonGetReceivedDestAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the RX_ADDR_FIELD0 register value */
+  g_xStatus = SpiritSpiReadRegisters(RX_ADDR_FIELD0_BASE, 1, &tempRegValue);
+
+  /* Return value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Returns the control field of the received packet.
+ * @param  None.
+ * @retval uint32_t Received control field.
+ */
+uint32_t SpiritPktCommonGetReceivedCtrlField(void)
+{
+  uint8_t tempRegValue[4];
+  uint32_t tempRetValue=0;
+
+  /* Reads the PCKT_FLT_GOALS_CONTROLx_MASK registers */
+  g_xStatus = SpiritSpiReadRegisters(RX_CTRL_FIELD0_BASE, 4, tempRegValue);
+
+  /* Rebuild the control mask value on a 32-bit integer variable */
+  for(uint8_t i=0 ; i<4 ; i++)
+  {
+    tempRetValue |= ((uint32_t)tempRegValue[i])<<(8*i);
+  }
+
+  /* Returns value */
+  return tempRetValue;
+}
+
+
+/**
+ * @brief  Returns the CRC field of the received packet.
+ * @param  cCrcFieldVect array in which the CRC field has to be stored.
+ *         This parameter is an uint8_t array of 3 elements.
+ * @retval None.
+ */
+void SpiritPktCommonGetReceivedCrcField(uint8_t* cCrcFieldVect)
+{
+  uint8_t tempRegValue[3],crcLength;
+  PktCrcMode crcMode;
+  
+  /* Gets the CRC mode in PktCrcMode enum */
+  crcMode=SpiritPktCommonGetCrcMode();
+  
+  /* Cast to uint8_t */
+  crcLength = (uint8_t)crcMode;
+  
+  /* Obtains the real length: see the @ref PktCrcMode enumeration */
+  crcLength >>= 5;
+  if(crcLength>=3) crcLength--;
+  
+  /* Reads the CRC_FIELDx registers value */
+  g_xStatus = SpiritSpiReadRegisters(CRC_FIELD2_BASE, 3,tempRegValue);
+  
+  /* Sets the array to be returned */
+  for(uint8_t i=0 ; i<3 ; i++)
+  {
+    if(i<crcLength) 
+    {
+      cCrcFieldVect[i]=tempRegValue[2-i];
+    }
+    else 
+    {
+      cCrcFieldVect[i]=0;
+    }
+  }
+  
+}
+
+
+/**
+ * @brief  Sets the AUTO ACKNOLEDGEMENT mechanism on the receiver. When the feature is enabled and
+ *         a data packet has been correctly received, then an acknowledgement packet is sent back to the originator of the received
+ *         packet. If the PIGGYBACKING bit is also set, payload data will be read from the FIFO; otherwise an empty packet is sent
+ *         only containing the source and destination addresses and the sequence number of the packet being acknowledged.
+ * @param  xAutoAck new state for autoack.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @param  xPiggybacking new state for autoack.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonAutoAck(SpiritFunctionalState xAutoAck , SpiritFunctionalState xPiggybacking)
+{
+  uint8_t tempRegValue[2];
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xAutoAck));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xPiggybacking));
+  /* Check if piggybacking is enabled and autoack is disabled */
+  s_assert_param(!(xPiggybacking==S_ENABLE && xAutoAck==S_DISABLE));
+
+  /* Reads the PROTOCOL[1:0] registers value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 2, tempRegValue);
+
+  /* Sets the specified LLP option */
+  /* Autoack setting */
+  if(xAutoAck == S_ENABLE)
+  {
+    tempRegValue[1] |= PROTOCOL0_AUTO_ACK_MASK;
+  }
+  else
+  {
+    tempRegValue[1] &= (~PROTOCOL0_AUTO_ACK_MASK);
+  }
+
+  /* Piggybacking setting */
+  if(xPiggybacking == S_ENABLE)
+  {
+    tempRegValue[0] |= PROTOCOL1_PIGGYBACKING_MASK;
+  }
+  else
+  {
+    tempRegValue[0] &= (~PROTOCOL1_PIGGYBACKING_MASK);
+  }
+
+  /* Writes data on the PROTOCOL[1:0] registers */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the AUTO ACKNOLEDGEMENT mechanism on the transmitter. On the transmitter side, the NACK_TX field can be used to require or not an acknowledgment for each individual packet: if
+ *         NACK_TX is set to "1" then acknowledgment will not be required; if NACK_TX is set to "0" then acknowledgment will be
+ *         required.
+ * @param  xNewState new state for TX_AUTOACK.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonRequireAck(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads value on the PROTOCOL0 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL0_BASE, 1, &tempRegValue);
+
+  /* Enables or disables the ack requirement option */
+  if(xNewState == S_DISABLE)
+  {
+    tempRegValue |= PROTOCOL0_NACK_TX_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL0_NACK_TX_MASK;
+  }
+
+  /* Writes value on the PROTOCOL0 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the TX sequence number to be used to start counting.
+ * @param  cSeqNumberReload new value for Tx seq number reload.
+ * @retval None.
+ */
+void SpiritPktCommonSetTransmittedSeqNumberReload(uint8_t cSeqNumberReload){
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_SEQ_NUMBER_RELOAD(cSeqNumberReload));
+
+  /* Reads value on the PROTOCOL2 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+  tempRegValue &= 0xE7;
+  tempRegValue |= (cSeqNumberReload << 3);
+
+  /* Writes value on the PROTOCOL2 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the TX sequence number to be used to start counting.
+ * @param  cSeqNumberReload new value for Tx seq number reload.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritPktCommonSetNMaxReTx(PktNMaxReTx xNMaxReTx)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PKT_NMAX_RETX(xNMaxReTx));
+
+  /* Reads the PROTOCOL0 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL0_BASE, 1, &tempRegValue);
+
+  /* Build the value to be written */
+  tempRegValue &= ~PROTOCOL0_NMAX_RETX_MASK;
+  tempRegValue |= xNMaxReTx;
+
+  /* Writes value on the PROTOCOL0 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL0_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the max number of automatic retransmission.
+ * @param  None.
+ * @retval uint8_t Max number of retransmissions.
+ *         This parameter is an uint8_t.
+ */
+uint8_t SpiritPktCommonGetNMaxReTx(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PROTOCOL0 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL0_BASE, 1, &tempRegValue);
+
+  /* Build the value to be written */
+  return ((tempRegValue & PROTOCOL0_NMAX_RETX_MASK)>>4);
+
+}
+
+/**
+ * @brief  Returns the TX ACK request
+ * @param  None.
+ * @retval uint8_t Max number of retransmissions.
+ *         This parameter is an uint8_t.
+ */
+SpiritFunctionalState SpiritPktCommonGetTxAckRequest(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PROTOCOL0 register value */
+  g_xStatus = SpiritSpiReadRegisters(RX_PCKT_INFO_BASE, 1, &tempRegValue);
+
+  /* Build the value to be written */
+  return (SpiritFunctionalState)((tempRegValue & TX_PCKT_INFO_NACK_RX)>>2);
+
+}
+   
+   
+/**
+ * @brief  Returns the source address of the received packet.
+ * @param  None.
+ * @retval uint8_t Source address of the received packet.
+ */
+uint8_t SpiritPktCommonGetReceivedSourceAddress(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the RX_ADDR_FIELD1 register value */
+  g_xStatus = SpiritSpiReadRegisters(RX_ADDR_FIELD1_BASE, 1, &tempRegValue);
+
+  /* Returns value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Returns the sequence number of the received packet.
+ * @param  None.
+ * @retval uint8_t Received Sequence number.
+ */
+uint8_t SpiritPktCommonGetReceivedSeqNumber(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the RX_PCKT_INFO register value */
+  g_xStatus = SpiritSpiReadRegisters(RX_PCKT_INFO_BASE, 1, &tempRegValue);
+
+  /* Obtains and returns the sequence number */
+  return tempRegValue & 0x03;
+
+}
+
+
+/**
+ * @brief  Returns the Nack bit of the received packet
+ * @param  None.
+ * @retval uint8_t Value of the Nack bit.
+ */
+uint8_t SpiritPktCommonGetReceivedNackRx(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the RX_PCKT_INFO register value */
+  g_xStatus = SpiritSpiReadRegisters(RX_PCKT_INFO_BASE, 1, &tempRegValue);
+
+  /* Obtains and returns the RX nack bit */
+  return (tempRegValue >> 2) & 0x01;
+
+}
+
+
+/**
+ * @brief  Returns the sequence number of the transmitted packet.
+ * @param  None.
+ * @retval uint8_t Sequence number of the transmitted packet.
+ */
+uint8_t SpiritPktCommonGetTransmittedSeqNumber(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the TX_PCKT_INFO register value */
+  g_xStatus = SpiritSpiReadRegisters(TX_PCKT_INFO_BASE, 1, &tempRegValue);
+
+  /* Obtains and returns the TX sequence number */
+  return (tempRegValue >> 4) & 0x07;
+
+}
+
+
+/**
+ * @brief  Returns the number of retransmission done on the transmitted packet.
+ * @param  None.
+ * @retval uint8_t Number of retransmissions done until now.
+ */
+uint8_t SpiritPktCommonGetNReTx(void)
+{
+  uint8_t tempRetValue;
+
+  /* Reads the TX_PCKT_INFO register value */
+  g_xStatus = SpiritSpiReadRegisters(TX_PCKT_INFO_BASE, 1, &tempRetValue);
+
+  /* Obtains and returns the number of retransmission done */
+  return (tempRetValue & 0x0F);
+
+}
+
+
+/**
+ * @brief  If enabled RX packet is accepted only if the masked control field matches the
+ *         masked control field reference (CONTROL_MASK & CONTROL_FIELD_REF == CONTROL_MASK & RX_CONTROL_FIELD).
+ * @param  xNewState new state for Control filtering enable bit.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ * @note   This filtering control is enabled by default but the control mask is by default set to 0.
+ *         As a matter of fact the user has to enable the control filtering bit after the packet initialization
+ *         because the PktInit routine disables it.
+ */
+void SpiritPktCommonFilterOnControlField(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+   /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+
+  /* Modify the register value: set or reset the control bit filtering */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Set or reset the CONTROL filtering enabling bit */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PCKT_FLT_OPTIONS_CONTROL_FILTERING_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PCKT_FLT_OPTIONS_CONTROL_FILTERING_MASK;
+  }
+
+  /* Writes the new value on the PCKT_FLT_OPTIONS register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the enable bit of the control field filtering.
+ * @param  None.
+ * @retval SpiritFunctionalState This parameter can be S_ENABLE or S_DISABLE.
+ */
+SpiritFunctionalState SpiritPktCommonGetFilterOnControlField(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Gets the enable/disable bit in form of SpiritFunctionalState type */
+  if(tempRegValue & PCKT_FLT_OPTIONS_CONTROL_FILTERING_MASK)
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+
+}
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktMbus.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktMbus.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,354 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_PktMbus.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT MBUS packets.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_PktMbus.h"
+#include "SPIRIT_Radio.h"
+#include "MCU_Interface.h"
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_PktMbus
+ * @{
+ */
+
+
+/**
+ * @defgroup PktMbus_Private_TypesDefinitions           Pkt MBUS Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktMbus_Private_Defines                    Pkt MBUS Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktMbus_Private_Macros                     Pkt MBUS Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktMbus_Private_Variables                  Pkt MBUS Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktMbus_Private_FunctionPrototypes         Pkt MBUS Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktMbus_Private_Functions                  Pkt MBUS Private Functions
+ * @{
+ */
+
+
+/**
+ * @brief  Initializes the SPIRIT MBUS packet according to the specified parameters in the PktMbusInit struct.
+ * @param  pxPktMbusInit pointer to a PktMbusInit structure that contains the configuration information for the specified SPIRIT MBUS PACKET FORMAT.
+ *         This parameter is a pointer to @ref PktMbusInit.
+ * @retval None.
+ */
+void SpiritPktMbusInit(PktMbusInit* pxPktMbusInit)
+{
+  uint8_t tempRegValue[3];
+
+  /* Check the parameters */
+  s_assert_param(IS_MBUS_SUBMODE(pxPktMbusInit->xMbusSubmode));
+
+  /* Packet format config */
+  SpiritPktMbusSetFormat();
+  SpiritPktCommonFilterOnCrc(S_DISABLE);
+  SpiritRadioCsBlanking(S_ENABLE);
+  
+  /* Preamble, postamble and submode config */
+  tempRegValue[0] = pxPktMbusInit->cPreambleLength;
+  tempRegValue[1] = pxPktMbusInit->cPostambleLength;
+  tempRegValue[2] = (uint8_t) pxPktMbusInit->xMbusSubmode;
+
+  /* Writes the new values on the MBUS_PRMBL registers */
+  g_xStatus = SpiritSpiWriteRegisters(MBUS_PRMBL_BASE, 3, tempRegValue);
+
+}
+
+/**
+ * @brief  Returns the SPIRIT MBUS packet structure according to the specified parameters in the registers.
+ * @param  pxPktMbusInit MBUS packet init structure.
+ *         This parameter is a pointer to @ref PktMbusInit.
+ * @retval None.
+ */
+void SpiritPktMbusGetInfo(PktMbusInit* pxPktMbusInit)
+{
+  uint8_t tempRegValue[3];
+
+  /* Reads the MBUS regs value */
+  g_xStatus = SpiritSpiReadRegisters(MBUS_PRMBL_BASE, 3, tempRegValue);
+
+  /* Fit the structure */
+  pxPktMbusInit->cPreambleLength = tempRegValue[0];
+  pxPktMbusInit->cPostambleLength = tempRegValue[1];
+  pxPktMbusInit->xMbusSubmode = (MbusSubmode) (tempRegValue[2]&0x0E);
+
+}
+
+
+/**
+ * @brief  Configures the MBUS packet format as the one used by SPIRIT.
+ * @param  None.
+ * @retval None.
+ */
+void SpiritPktMbusSetFormat(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PCKTCTRL3 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Sets format bits. Also set to 0 the direct RX mode bits */
+  tempRegValue &= 0x0F;
+  tempRegValue |= ((uint8_t)PCKTCTRL3_PCKT_FRMT_MBUS);
+
+  /* Writes value on the PCKTCTRL3 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Reads the PCKTCTRL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Build the new value. Set to 0 the direct TX mode bits */
+  tempRegValue &= 0xF3;
+
+  /* Writes the value on the PCKTCTRL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Reads the PROTOCOL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Mask a reserved bit */
+  tempRegValue &= ~0x20;
+
+  /* Writes the value on the PROTOCOL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets how many chip sequence “01” shall be added in the preamble
+ *         respect to the minimum value as defined according to the specified sub-mode.
+ * @param  cPreamble the number of chip sequence.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritPktMbusSetPreamble(uint8_t cPreamble)
+{
+  /* Modifies the MBUS_PRMBL register value */
+  g_xStatus = SpiritSpiWriteRegisters(MBUS_PRMBL_BASE, 1, &cPreamble);
+
+}
+
+
+/**
+ * @brief  Returns how many chip sequence "01" are added in the preamble
+ *         respect to the minimum value as defined according to the specified sub-mode.
+ * @param  None.
+ * @retval uint8_t Preable in number of "01" chip sequences.
+ */
+uint8_t SpiritPktMbusGetPreamble(void)
+{
+  uint8_t tempRegValue;
+
+  /* Modifies the MBUS_PRMBL register value */
+  g_xStatus = SpiritSpiReadRegisters(MBUS_PRMBL_BASE, 1, &tempRegValue);
+
+  /* Return value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets how many chip sequence “01” will be used in postamble
+ * @param  cPostamble the number of chip sequence.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritPktMbusSetPostamble(uint8_t cPostamble)
+{
+  /* Modifies the MBUS_PSTMBL register value */
+  g_xStatus = SpiritSpiWriteRegisters(MBUS_PSTMBL_BASE, 1, &cPostamble);
+
+}
+
+
+/**
+ * @brief  Returns how many chip sequence "01" are used in the postamble
+ * @param  None.
+ * @retval uint8_t Postamble in number of "01" chip sequences.
+ */
+uint8_t SpiritPktMbusGetPostamble(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the MBUS_PSTMBL register */
+  g_xStatus = SpiritSpiReadRegisters(MBUS_PSTMBL_BASE, 1, &tempRegValue);
+
+  /* Returns value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets the MBUS submode used.
+ * @param  xMbusSubmode the submode used.
+ *         This parameter can be any value of @ref MbusSubmode.
+ * @retval None.
+ */
+void SpiritPktMbusSetSubmode(MbusSubmode xMbusSubmode)
+{
+  /* Modifies the MBUS_CTRL register value */
+  g_xStatus = SpiritSpiWriteRegisters(MBUS_CTRL_BASE, 1, (uint8_t*)xMbusSubmode);
+
+}
+
+
+/**
+ * @brief  Returns the MBUS submode used.
+ * @param  None.
+ * @retval MbusSubmode MBUS submode.
+ */
+MbusSubmode SpiritPktMbusGetSubmode(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the MBUS_CTRL register value */
+  g_xStatus = SpiritSpiReadRegisters(MBUS_CTRL_BASE, 1, &tempRegValue);
+
+  /* Returns value */
+  return (MbusSubmode) tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets the payload length for SPIRIT MBUS packets.
+ * @param  nPayloadLength payload length in bytes.
+ *         This parameter is an uint16_t.
+ * @retval None.
+ */
+void SpiritPktMbusSetPayloadLength(uint16_t nPayloadLength)
+{
+  uint8_t tempRegValue[2];
+
+  /* Computes PCKTLEN0 value from nPayloadLength */
+  tempRegValue[1]=BUILD_PCKTLEN0(nPayloadLength);//(uint8_t)nPayloadLength;
+  /* Computes PCKTLEN1 value from nPayloadLength */
+  tempRegValue[0]=BUILD_PCKTLEN1(nPayloadLength);//(uint8_t)(nPayloadLength>>8);
+
+  /* Writes data on the PCKTLEN1/0 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTLEN1_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the payload length for SPIRIT MBUS packets.
+ * @param  None.
+ * @retval uint16_t Payload length in bytes.
+ */
+uint16_t SpiritPktMbusGetPayloadLength(void)
+{
+  uint8_t tempRegValue[2];
+
+  /* Reads the packet length registers */
+  g_xStatus = SpiritSpiReadRegisters(PCKTLEN1_BASE, 2, tempRegValue);
+
+  /* Returns the packet length */
+  return ((((uint16_t)tempRegValue[0])<<8) + (uint16_t) tempRegValue[1]);
+
+}
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktStack.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_PktStack.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,687 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_PktStack.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT STack packets.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_PktStack.h"
+#include "MCU_Interface.h"
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_PktStack
+ * @{
+ */
+
+
+/**
+ * @defgroup PktStack_Private_TypesDefinitions          Pkt STack Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktStack_Private_Defines                   Pkt STack Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktStack_Private_Macros                    Pkt STack Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktStack_Private_Variables                 Pkt STack Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktStack_Private_FunctionPrototypes        Pkt STack Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup PktStack_Private_Functions                 Pkt STack Private Functions
+ * @{
+ */
+
+
+/**
+ * @brief  Initializes the SPIRIT STack packet according to the specified
+ *         parameters in the PktStackInit.
+ * @param  pxPktStackInit STack packet init structure.
+ *         This parameter is a pointer to @ref PktStackInit.
+ * @retval None.
+ */
+void SpiritPktStackInit(PktStackInit* pxPktStackInit)
+{
+  uint8_t tempRegValue[4], i;
+
+  /* Check the parameters */
+  s_assert_param(IS_STACK_PREAMBLE_LENGTH(pxPktStackInit->xPreambleLength));
+  s_assert_param(IS_STACK_SYNC_LENGTH(pxPktStackInit->xSyncLength));
+  s_assert_param(IS_STACK_CRC_MODE(pxPktStackInit->xCrcMode));
+  s_assert_param(IS_STACK_LENGTH_WIDTH_BITS(pxPktStackInit->cPktLengthWidth));
+  s_assert_param(IS_STACK_FIX_VAR_LENGTH(pxPktStackInit->xFixVarLength));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktStackInit->xFec));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktStackInit->xDataWhitening));
+  s_assert_param(IS_STACK_CONTROL_LENGTH(pxPktStackInit->xControlLength));
+
+
+  /* Reads the PROTOCOL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue[0]);
+
+  /* Mask a reserved bit */
+  tempRegValue[0] &= ~0x20;
+
+  /* Always (!) set the automatic packet filtering */
+  tempRegValue[0] |= PROTOCOL1_AUTO_PCKT_FLT_MASK;
+
+  /* Writes the value on register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue[0]);
+
+  /* Reads the PCKT_FLT_OPTIONS register */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+
+  /* Always reset the control and source filtering */
+  tempRegValue[0] &= ~(PCKT_FLT_OPTIONS_SOURCE_FILTERING_MASK | PCKT_FLT_OPTIONS_CONTROL_FILTERING_MASK);
+
+  /* Writes the value on register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+
+
+  /* Address and control length setting: source and destination address are always present so ADDRESS_LENGTH=2 */
+  tempRegValue[0] = 0x10 | ((uint8_t) pxPktStackInit->xControlLength);
+
+
+  /* Packet format and width length setting */
+  pxPktStackInit->cPktLengthWidth == 0 ? pxPktStackInit->cPktLengthWidth=1 : pxPktStackInit->cPktLengthWidth;
+  tempRegValue[1] = ((uint8_t) PCKTCTRL3_PCKT_FRMT_STACK) | ((uint8_t)(pxPktStackInit->cPktLengthWidth-1));
+
+  /* Preamble, sync and fixed or variable length setting */
+  tempRegValue[2] = ((uint8_t) pxPktStackInit->xPreambleLength) | ((uint8_t) pxPktStackInit->xSyncLength) |
+                    ((uint8_t) pxPktStackInit->xFixVarLength);
+
+  /* CRC length, whitening and FEC setting */
+  tempRegValue[3] = (uint8_t) pxPktStackInit->xCrcMode;
+
+  if(pxPktStackInit->xDataWhitening == S_ENABLE)
+  {
+     tempRegValue[3] |= PCKTCTRL1_WHIT_MASK;
+  }
+
+  if(pxPktStackInit->xFec == S_ENABLE)
+  {
+     tempRegValue[3] |= PCKTCTRL1_FEC_MASK;
+  }
+  
+  /* Writes registers */
+  SpiritSpiWriteRegisters(PCKTCTRL4_BASE, 4, tempRegValue);
+
+  /* Sync words setting */
+  for(i=0;i<4;i++)
+  {
+    if(i<3-(pxPktStackInit->xSyncLength >>1))
+    {
+      tempRegValue[i]=0;
+    }
+    else
+    {
+      tempRegValue[i] = (uint8_t)(pxPktStackInit->lSyncWords>>(8*i));
+    }
+  }
+
+  /* Enables or disables the CRC check */
+  if(pxPktStackInit->xCrcMode == PKT_NO_CRC)
+  {
+    SpiritPktStackFilterOnCrc(S_DISABLE);
+  }
+  else
+  {
+    SpiritPktStackFilterOnCrc(S_ENABLE);
+  }
+
+  /* Writes registers */
+  g_xStatus = SpiritSpiWriteRegisters(SYNC4_BASE, 4, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the SPIRIT STack packet structure according to the specified parameters in the registers.
+ * @param  pxPktStackInit STack packet init structure.
+ *         This parameter is a pointer to @ref PktStackInit.
+ * @retval None.
+ */
+void SpiritPktStackGetInfo(PktStackInit* pxPktStackInit)
+{
+  uint8_t tempRegValue[10];
+
+  /* Reads registers */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL4_BASE, 10, tempRegValue);
+
+  /* Length width */
+  pxPktStackInit->cPktLengthWidth=(tempRegValue[1] & 0x0F)+1;
+
+  /* Control length */
+  pxPktStackInit->xControlLength=(StackControlLength)(tempRegValue[0] & 0x07);
+
+  /* CRC mode */
+  pxPktStackInit->xCrcMode=(StackCrcMode)(tempRegValue[3] & 0xE0);
+
+  /* Whitening */
+  pxPktStackInit->xDataWhitening=(SpiritFunctionalState)((tempRegValue[3] >> 4) & 0x01);
+
+  /* FEC */
+  pxPktStackInit->xFec=(SpiritFunctionalState)(tempRegValue[3] & 0x01);
+
+  /* FIX or VAR bit */
+  pxPktStackInit->xFixVarLength=(StackFixVarLength)(tempRegValue[2] & 0x01);
+
+  /* Preamble length */
+  pxPktStackInit->xPreambleLength=(StackPreambleLength)(tempRegValue[2] & 0xF8);
+
+  /* Sync length */
+  pxPktStackInit->xSyncLength=(StackSyncLength)(tempRegValue[2] & 0x06);
+
+  /* sync Words */
+  pxPktStackInit->lSyncWords=0;
+  for(uint8_t i=0 ; i<4 ; i++)
+  {
+      if(i>2-(pxPktStackInit->xSyncLength >>1))
+      {
+        pxPktStackInit->lSyncWords |= tempRegValue[i+6]<<(8*i);
+      }
+  }
+
+}
+
+
+/**
+ * @brief  Initializes the SPIRIT STack packet addresses according to the specified
+ *         parameters in the PktStackAddresses struct.
+ * @param  pxPktStackAddresses STack packet addresses init structure.
+ *         This parameter is a pointer to @ref PktStackAddressesInit .
+ * @retval None.
+ */
+void SpiritPktStackAddressesInit(PktStackAddressesInit* pxPktStackAddresses)
+{
+  uint8_t tempRegValue[3];
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktStackAddresses->xFilterOnMyAddress));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktStackAddresses->xFilterOnMulticastAddress));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktStackAddresses->xFilterOnBroadcastAddress));
+  
+  /* Reads the filtering options ragister */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+  
+  /* Enables or disables filtering on my address */
+  if(pxPktStackAddresses->xFilterOnMyAddress == S_ENABLE)
+  {
+    tempRegValue[0] |= PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_TX_ADDR_MASK;
+  }
+  
+  /* Enables or disables filtering on multicast address */
+  if(pxPktStackAddresses->xFilterOnMulticastAddress == S_ENABLE)
+  {
+    tempRegValue[0] |= PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_MULTICAST_ADDR_MASK;
+  }
+  
+  /* Enables or disables filtering on broadcast address */
+  if(pxPktStackAddresses->xFilterOnBroadcastAddress == S_ENABLE)
+  {
+    tempRegValue[0] |= PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK;
+  }
+  else
+  {
+    tempRegValue[0] &= ~PCKT_FLT_OPTIONS_DEST_VS_BROADCAST_ADDR_MASK;
+  }
+  
+  /* Writes value on the register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+  
+  /* Fills array with the addresses passed in the structure */
+  tempRegValue[0] = pxPktStackAddresses->cBroadcastAddress;
+  tempRegValue[1] = pxPktStackAddresses->cMulticastAddress;
+  tempRegValue[2] = pxPktStackAddresses->cMyAddress;
+  
+  /* Writes them on the addresses registers */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_BROADCAST_BASE, 3, tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the SPIRIT STack packet addresses structure according to the specified
+*         parameters in the registers.
+* @param  pxPktStackAddresses STack packet addresses init structure.
+*         This parameter is a pointer to @ref PktStackAddresses.
+* @retval None.
+*/
+void SpiritPktStackGetAddressesInfo(PktStackAddressesInit* pxPktStackAddresses)
+{
+  uint8_t tempRegValue[3];
+  
+  /* Reads values on the PCKT_FLT_GOALS registers */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_BROADCAST_BASE, 3, tempRegValue);
+  
+  /* Fit the structure with the read addresses */
+  pxPktStackAddresses->cBroadcastAddress = tempRegValue[0];
+  pxPktStackAddresses->cMulticastAddress = tempRegValue[1];
+  pxPktStackAddresses->cMyAddress = tempRegValue[2];
+  
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue[0]);
+  
+  /* Fit the structure with the read filtering bits */
+  pxPktStackAddresses->xFilterOnBroadcastAddress = (SpiritFunctionalState)((tempRegValue[0] >> 1) & 0x01);
+  pxPktStackAddresses->xFilterOnMulticastAddress = (SpiritFunctionalState)((tempRegValue[0] >> 2) & 0x01);
+  pxPktStackAddresses->xFilterOnMyAddress = (SpiritFunctionalState)((tempRegValue[0] >> 3) & 0x01);
+  
+}
+
+
+/**
+* @brief  Initializes the SPIRIT STack packet LLP options according to the specified
+*         parameters in the PktStackLlpInit struct.
+* @param  pxPktStackLlpInit STack packet LLP init structure.
+*         This parameter is a pointer to @ref PktStackLlpInit.
+* @retval None.
+*/
+void SpiritPktStackLlpInit(PktStackLlpInit* pxPktStackLlpInit)
+{
+  uint8_t tempRegValue[2];
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktStackLlpInit->xPiggybacking));
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(pxPktStackLlpInit->xAutoAck));
+  s_assert_param(IS_STACK_NMAX_RETX(pxPktStackLlpInit->xNMaxRetx));
+  /* check if piggybacking is enabled and autoack is disabled */
+  s_assert_param(!(pxPktStackLlpInit->xPiggybacking==S_ENABLE && pxPktStackLlpInit->xAutoAck==S_DISABLE));
+
+  /* Piggybacking mechanism setting on the PROTOCOL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 2, tempRegValue);
+  if(pxPktStackLlpInit->xPiggybacking == S_ENABLE)
+  {
+    tempRegValue[0] |= PROTOCOL1_PIGGYBACKING_MASK;
+  }
+  else
+  {
+    tempRegValue[0] &= ~PROTOCOL1_PIGGYBACKING_MASK;
+  }
+
+  /* RX and TX autoack mechanisms setting on the PROTOCOL0 register */
+  if(pxPktStackLlpInit->xAutoAck == S_ENABLE)
+  {
+    tempRegValue[1] |= PROTOCOL0_AUTO_ACK_MASK;
+  }
+  else
+  {
+    tempRegValue[1] &= ~PROTOCOL0_AUTO_ACK_MASK;
+  }
+
+  /* Max number of retransmission setting */
+  tempRegValue[1] &= ~PROTOCOL0_NMAX_RETX_MASK;
+  tempRegValue[1] |= pxPktStackLlpInit->xNMaxRetx;
+
+  /* Writes registers */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the SPIRIT STack packet LLP options according to the specified
+ *         values in the registers.
+ * @param  pxPktStackLlpInit STack packet LLP structure.
+ *         This parameter is a pointer to @ref PktStackLlpInit.
+ * @retval None.
+ */
+void SpiritPktStackLlpGetInfo(PktStackLlpInit* pxPktStackLlpInit)
+{
+  uint8_t tempRegValue[2];
+
+  /* Piggybacking mechanism setting on the PROTOCOL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 2, tempRegValue);
+
+  /* Fit the structure with the read values */
+  pxPktStackLlpInit->xPiggybacking = (SpiritFunctionalState)((tempRegValue[0] >> 6) & 0x01);
+  pxPktStackLlpInit->xAutoAck = (SpiritFunctionalState)((tempRegValue[1] >> 2) & 0x01);
+  pxPktStackLlpInit->xNMaxRetx = (StackNMaxReTx)(tempRegValue[1] & PROTOCOL0_NMAX_RETX_MASK);
+
+}
+
+
+/**
+ * @brief  Configures the STack packet format for SPIRIT.
+ * @param  None.
+ * @retval None.
+ */
+void SpiritPktStackSetFormat(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PCKTCTRL3 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Build value to be written. Also set to 0 the direct RX mode bits */
+  tempRegValue &= 0x0F;
+  tempRegValue |= ((uint8_t)PCKTCTRL3_PCKT_FRMT_STACK);
+
+  /* Writes the value on the PCKTCTRL3 register. */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Reads the PCKTCTRL1 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Build the new value. Set to 0 the direct TX mode bits */
+  tempRegValue &= 0xF3;
+
+  /* Writes the PCKTCTRL1 value on register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL1_BASE, 1, &tempRegValue);
+
+  /* Reads the PROTOCOL1 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Mask a reserved bit */
+  tempRegValue &= ~0x20;
+
+  /* Writes the value on the PROTOCOL1 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the address length for SPIRIT STack packets (always 2).
+ * @param  None.
+ * @retval None.
+ */
+void SpiritPktStackSetAddressLength(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the PCKTCTRL4 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL4_BASE, 1, &tempRegValue);
+
+  /* Build the new value */
+  tempRegValue &= ~PCKTCTRL4_ADDRESS_LEN_MASK;
+  tempRegValue |= ((uint8_t)0x10);
+
+  /* Writes the value on the PCKTCTRL4 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL4_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the payload length for SPIRIT STack packets. Since the packet length
+ *         depends from the address (always 2 for this packet format)
+ *         and the control field size, this function reads the control length register
+ *         content in order to determine the correct packet length to be written.
+ * @param  nPayloadLength payload length in bytes.
+ *         This parameter can be any value of uint16_t.
+ * @retval None.
+ */
+void SpiritPktStackSetPayloadLength(uint16_t nPayloadLength)
+{
+  uint8_t tempRegValue[2];
+
+  /* Computes the oversize (address + control) size */
+  uint16_t overSize = 2 + (uint16_t) SpiritPktStackGetControlLength();
+
+  /* Computes PCKTLEN0 value from lPayloadLength */
+  tempRegValue[1]=STACK_BUILD_PCKTLEN0(nPayloadLength+overSize);
+  /* Computes PCKTLEN1 value from lPayloadLength */
+  tempRegValue[0]=STACK_BUILD_PCKTLEN1(nPayloadLength+overSize);
+
+  /* Writes the value on the PCKTLENx registers */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTLEN1_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the payload length for SPIRIT STack packets. Since the
+ *         packet length depends from the address and the control
+ *         field size, this function reads the correspondent
+ *         registers in order to determine the correct payload length
+ *         to be returned.
+ * @param  None.
+ * @retval uint16_t Payload length.
+ */
+uint16_t SpiritPktStackGetPayloadLength(void)
+{
+  uint8_t tempRegValue[2];
+  /* Computes the oversize (address + control) size */
+  uint16_t overSize = 2 + (uint16_t) SpiritPktStackGetControlLength();
+
+  /* Reads the PCKTLEN1 registers value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTLEN1_BASE, 2, tempRegValue);
+
+  /* Rebuild and return the payload length value */
+  return ((((uint16_t) tempRegValue[1])<<8) + (uint16_t) tempRegValue[0] - overSize);
+
+}
+
+
+/**
+ * @brief  Computes and sets the variable payload length for SPIRIT STack packets.
+ * @param  nMaxPayloadLength payload length in bytes.
+ *         This parameter is an uint16_t.
+ * @param  xControlLength control length in bytes.
+ *         This parameter can be any value of @ref StackControlLength.
+ * @retval None.
+ */
+void SpiritPktStackSetVarLengthWidth(uint16_t nMaxPayloadLength, StackControlLength xControlLength)
+{
+  uint8_t tempRegValue,
+          i;
+  uint32_t packetLength;
+
+
+  /* packet length = payload length + address length (2) + control length */
+  packetLength=nMaxPayloadLength+2+xControlLength;
+
+  /* Computes the number of bits */
+  for(i=0;i<16;i++)
+  {
+    if(packetLength == 0) 
+    {
+      break;
+    }
+    packetLength >>= 1;
+  }
+  i==0 ? i=1 : i;
+
+  /* Reads the PCKTCTRL3 register value */
+  g_xStatus = SpiritSpiReadRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+  /* Build the register value */
+  tempRegValue &= ~PCKTCTRL3_LEN_WID_MASK;
+  tempRegValue |= ((uint8_t)(i-1));
+
+  /* Writes the PCKTCTRL3 register value */
+  g_xStatus = SpiritSpiWriteRegisters(PCKTCTRL3_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Rx packet source mask. Used to mask the address of the accepted packets. If 0 -> no filtering.
+ * @param  cMask Rx source mask.
+ *         This parameter is an uint8_t.
+ * @retval None.
+ */
+void SpiritPktStackSetRxSourceMask(uint8_t cMask)
+{
+  /* Writes value on the register PCKT_FLT_GOALS_SOURCE_MASK */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_GOALS_SOURCE_MASK_BASE, 1, &cMask);
+
+}
+
+
+/**
+ * @brief  Returns the Rx packet source mask. Used to mask the address of the accepted packets. If 0 -> no filtering.
+ * @param  None.
+ * @retval uint8_t Rx source mask.
+ */
+uint8_t SpiritPktStackGetRxSourceMask(void)
+{
+  uint8_t tempRegValue;
+
+  /* Writes value on the PCKT_FLT_GOALS_SOURCE_MASK register */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_GOALS_SOURCE_MASK_BASE, 1, &tempRegValue);
+
+  /* Return the read value */
+  return tempRegValue;
+
+}
+
+/**
+ * @brief  Returns the packet length field of the received packet.
+ * @param  None.
+ * @retval uint16_t Packet length.
+ */
+uint16_t SpiritPktStackGetReceivedPktLength(void)
+{
+  uint8_t tempRegValue[2];
+  uint16_t tempLength;
+  
+  /* Reads the RX_PCKT_LENx registers value */
+  g_xStatus = SpiritSpiReadRegisters(RX_PCKT_LEN1_BASE, 2, tempRegValue);
+
+  /* Rebuild and return the the length field */
+  tempLength = ((((uint16_t) tempRegValue[0]) << 8) + (uint16_t) tempRegValue[1]);
+  
+  /* Computes the oversize (address + control) size */
+  tempLength -= 2 + (uint16_t) SpiritPktStackGetControlLength();
+  
+  return tempLength;
+
+}
+
+
+/**
+ * @brief  If enabled RX packet is accepted only if the masked source address field matches the
+ *         masked source address field reference (SOURCE_MASK & SOURCE_FIELD_REF == SOURCE_MASK & RX_SOURCE_FIELD).
+ * @param  xNewState new state for Source address filtering enable bit.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ * @note   This filtering control is enabled by default but the source address mask is by default set to 0.
+ *         As a matter of fact the user has to enable the source filtering bit after the packet initialization
+ *         because the PktInit routine disables it.
+ */
+void SpiritPktStackFilterOnSourceAddress(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+   /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+
+  /* Modify the register value: set or reset the source bit filtering */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+  /* Set or reset the SOURCE ADDRESS filtering enabling bit */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PCKT_FLT_OPTIONS_SOURCE_FILTERING_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PCKT_FLT_OPTIONS_SOURCE_FILTERING_MASK;
+  }
+
+  /* Writes the new value on the PCKT_FLT_OPTIONS register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 1, &tempRegValue);
+
+}
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Qi.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Qi.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,636 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_Qi.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT QI.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Qi.h"
+#include "MCU_Interface.h"
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_Qi
+ * @{
+ */
+
+
+/**
+ * @defgroup Qi_Private_TypesDefinitions        QI Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Qi_Private_Defines                 QI Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Qi_Private_Macros                  QI Private Macros
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Qi_Private_Variables               QI Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Qi_Private_FunctionPrototypes      QI Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Qi_Private_Functions               QI Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Enables/Disables the PQI Preamble Quality Indicator check. The running peak PQI is
+ *         compared to a threshold value and the preamble valid IRQ is asserted as soon as the threshold is passed.
+ * @param  xNewState new state for PQI check.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritQiPqiCheck(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the QI register value */
+  g_xStatus = SpiritSpiReadRegisters(QI_BASE, 1, &tempRegValue);
+
+  /* Enables or disables the PQI Check bit on the QI_BASE register */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= QI_PQI_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~QI_PQI_MASK;
+  }
+
+  /* Writes value on the QI register */
+  g_xStatus = SpiritSpiWriteRegisters(QI_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Enables/Disables the Synchronization Quality Indicator check. The running peak SQI is
+ *         compared to a threshold value and the sync valid IRQ is asserted as soon as the threshold is passed.
+ * @param  xNewState new state for SQI check.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritQiSqiCheck(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the QI register value */
+  g_xStatus = SpiritSpiReadRegisters(QI_BASE, 1, &tempRegValue);
+
+  /* Enables or disables the SQI Check bit on the QI_BASE register */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= QI_SQI_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~QI_SQI_MASK;
+  }
+
+  /* Writes value on the QI register */
+  g_xStatus = SpiritSpiWriteRegisters(QI_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the PQI threshold. The preamble quality threshold is 4*PQI_TH (PQI_TH = 0..15).
+ * @param  xPqiThr parameter of the formula above.
+ * 	   This variable is a @ref PqiThreshold.
+ * @retval None.
+ */
+void SpiritQiSetPqiThreshold(PqiThreshold xPqiThr)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_PQI_THR(xPqiThr));
+
+  /* Reads the QI register value */
+  g_xStatus = SpiritSpiReadRegisters(QI_BASE, 1, &tempRegValue);
+
+  /* Build the PQI threshold value to be written */
+  tempRegValue &= 0xC3;
+  tempRegValue |= ((uint8_t)xPqiThr);
+
+  /* Writes value on the QI register */
+  g_xStatus = SpiritSpiWriteRegisters(QI_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the PQI threshold. The preamble quality threshold is 4*PQI_TH (PQI_TH = 0..15).
+ * @param  None.
+ * @retval PqiThreshold PQI threshold (PQI_TH of the formula above).
+ */
+PqiThreshold SpiritQiGetPqiThreshold(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the QI register value */
+  g_xStatus = SpiritSpiReadRegisters(QI_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return the PQI threshold value */
+  return (PqiThreshold)(tempRegValue & 0x3C);
+
+}
+
+
+/**
+ * @brief  Sets the SQI threshold. The synchronization quality
+ *         threshold is equal to 8 * SYNC_LEN - 2 * SQI_TH with SQI_TH = 0..3. When SQI_TH is 0 perfect match is required; when
+ *         SQI_TH = 1, 2, 3 then 1, 2, or 3 bit errors are respectively accepted. It is recommended that the SQI check is always
+ *         enabled.
+ * @param  xSqiThr parameter of the formula above.
+ * 	   This parameter is a @ref SqiThreshold.
+ * @retval None.
+ */
+void SpiritQiSetSqiThreshold(SqiThreshold xSqiThr)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SQI_THR(xSqiThr));
+
+  /* Reads the QI register value */
+  g_xStatus = SpiritSpiReadRegisters(QI_BASE, 1, &tempRegValue);
+
+  /* Build the SQI threshold value to be written */
+  tempRegValue &= 0x3F;
+  tempRegValue |= ((uint8_t)xSqiThr);
+
+  /* Writes the new value on the QI register */
+  g_xStatus = SpiritSpiWriteRegisters(QI_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the SQI threshold. The synchronization quality threshold is equal to 8 * SYNC_LEN - 2 * SQI_TH with SQI_TH = 0..3.
+ * @param  None.
+ * @retval SqiThreshold SQI threshold (SQI_TH of the formula above).
+ */
+SqiThreshold SpiritQiGetSqiThreshold(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the QI register value */
+  g_xStatus = SpiritSpiReadRegisters(QI_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return the SQI threshold value */
+  return (SqiThreshold)(tempRegValue & 0xC0);
+
+}
+
+
+/**
+ * @brief  Returns the PQI value.
+ * @param  None.
+ * @retval uint8_t PQI value.
+ */
+uint8_t SpiritQiGetPqi(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the LINK_QUALIF2 register value */
+  g_xStatus = SpiritSpiReadRegisters(LINK_QUALIF2_BASE, 1, &tempRegValue);
+
+  /* Returns the PQI value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Returns the SQI value.
+ * @param  None.
+ * @retval uint8_t SQI value.
+ */
+uint8_t SpiritQiGetSqi(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register LINK_QUALIF1 value */
+  g_xStatus = SpiritSpiReadRegisters(LINK_QUALIF1_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return the SQI value */
+  return (tempRegValue & 0x7F);
+
+}
+
+
+/**
+ * @brief  Returns the LQI value.
+ * @param  None.
+ * @retval uint8_t LQI value.
+ */
+uint8_t SpiritQiGetLqi(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the LINK_QUALIF0 register value */
+  g_xStatus = SpiritSpiReadRegisters(LINK_QUALIF0_BASE, 1, &tempRegValue);
+
+  /* Rebuild and return the LQI value */
+  return ((tempRegValue & 0xF0)>> 4);
+
+}
+
+
+/**
+ * @brief  Returns the CS status.
+ * @param  None.
+ * @retval SpiritFlagStatus CS value (S_SET or S_RESET).
+ */
+SpiritFlagStatus SpiritQiGetCs(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the LINK_QUALIF1 register value */
+  g_xStatus = SpiritSpiReadRegisters(LINK_QUALIF1_BASE, 1, &tempRegValue);
+
+  /* Rebuild and returns the CS status value */
+  if((tempRegValue & 0x80) == 0)
+  {
+    return S_RESET;
+  }
+  else
+  {
+    return S_SET;
+  }
+
+}
+
+
+/**
+ * @brief  Returns the RSSI value. The measured power is reported in steps of half a dB from 0 to 255 and is offset in such a way that -120 dBm corresponds
+ *         to 20.
+ * @param  None.
+ * @retval uint8_t RSSI value.
+ */
+uint8_t SpiritQiGetRssi(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the RSSI_LEVEL register value */
+  g_xStatus = SpiritSpiReadRegisters(RSSI_LEVEL_BASE, 1, &tempRegValue);
+
+  /* Returns the RSSI value */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Sets the RSSI threshold.
+ * @param  cRssiThr RSSI threshold reported in steps of half a dBm with a -130 dBm offset.
+ *         This parameter must be a uint8_t.
+ * @retval None.
+ */
+void SpiritQiSetRssiThreshold(uint8_t cRssiThr)
+{
+  /* Writes the new value on the RSSI_TH register */
+  g_xStatus = SpiritSpiWriteRegisters(RSSI_TH_BASE, 1, &cRssiThr);
+
+}
+
+
+/**
+ * @brief  Returns the RSSI threshold.
+ * @param  None.
+ * @retval uint8_t RSSI threshold.
+ */
+uint8_t SpiritQiGetRssiThreshold(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the RSSI_TH register value */
+  g_xStatus = SpiritSpiReadRegisters(RSSI_TH_BASE, 1, &tempRegValue);
+
+  /* Returns RSSI threshold */
+  return tempRegValue;
+
+}
+
+
+/**
+ * @brief  Computes the RSSI threshold from its dBm value according to the formula: (RSSI[Dbm] + 130)/0.5
+ * @param  nDbmValue RSSI threshold reported in dBm.
+ *         This parameter must be a sint16_t.
+ * @retval uint8_t RSSI threshold corresponding to dBm value.
+ */
+uint8_t SpiritQiComputeRssiThreshold(int nDbmValue)
+{
+  /* Check the parameters */
+  s_assert_param(IS_RSSI_THR_DBM(nDbmValue));
+
+  /* Computes the RSSI threshold for register */
+  return 2*(nDbmValue+130);
+
+}
+
+/**
+ * @brief  Sets the RSSI threshold from its dBm value according to the formula: (RSSI[Dbm] + 130)/0.5.
+ * @param  nDbmValue RSSI threshold reported in dBm.
+ *         This parameter must be a sint16_t.
+ * @retval None.
+ */
+void SpiritQiSetRssiThresholddBm(int nDbmValue)
+{
+  uint8_t tempRegValue=2*(nDbmValue+130);
+
+  /* Check the parameters */
+  s_assert_param(IS_RSSI_THR_DBM(nDbmValue));
+
+  /* Writes the new value on the RSSI_TH register */
+  g_xStatus = SpiritSpiWriteRegisters(RSSI_TH_BASE, 1, &tempRegValue);
+
+}
+
+/**
+ * @brief  Sets the RSSI filter gain. This parameter sets the bandwidth of a low pass IIR filter (RSSI_FLT register, allowed values 0..15), a
+ *         lower values gives a faster settling of the measurements but lower precision. The recommended value for such parameter is 14.
+ * @param  xRssiFg RSSI filter gain value.
+ *         This parameter can be any value of @ref RssiFilterGain.
+ * @retval None.
+ */
+void SpiritQiSetRssiFilterGain(RssiFilterGain xRssiFg)
+{
+  uint8_t tempRegValue;
+
+   /* Check the parameters */
+  s_assert_param(IS_RSSI_FILTER_GAIN(xRssiFg));
+
+  /* Reads the RSSI_FLT register */
+  g_xStatus = SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+
+  /* Sets the specified filter gain */
+  tempRegValue &= 0x0F;
+  tempRegValue |= ((uint8_t)xRssiFg);
+
+  /* Writes the new value on the RSSI_FLT register */
+  g_xStatus = SpiritSpiWriteRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the RSSI filter gain.
+ * @param  None.
+ * @retval RssiFilterGain RSSI filter gain.
+ */
+RssiFilterGain SpiritQiGetRssiFilterGain(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the RSSI_FLT register */
+  g_xStatus = SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+
+  /* Rebuild and returns the filter gain value */
+  return (RssiFilterGain)(tempRegValue & 0xF0);
+
+}
+
+
+/**
+ * @brief  Sets the CS Mode. When static carrier sensing is used (cs_mode = 0), the carrier sense signal is asserted when the measured RSSI is above the
+ *         value specified in the RSSI_TH register and is deasserted when the RSSI falls 3 dB below the same threshold.
+ *         When dynamic carrier sense is used (cs_mode = 1, 2, 3), the carrier sense signal is asserted if the signal is above the
+ *         threshold and a fast power increase of 6, 12 or 18 dB is detected; it is deasserted if a power fall of the same amplitude is
+ *         detected.
+ * @param  xCsMode CS mode selector.
+ *         This parameter can be any value of @ref CSMode.
+ * @retval None.
+ */
+void SpiritQiSetCsMode(CSMode xCsMode)
+{
+  uint8_t tempRegValue;
+
+   /* Check the parameters */
+  s_assert_param(IS_CS_MODE(xCsMode));
+
+  /* Reads the RSSI_FLT register */
+  g_xStatus = SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+
+  /* Sets bit to select the CS mode */
+  tempRegValue &= ~0x0C;
+  tempRegValue |= ((uint8_t)xCsMode);
+
+  /* Writes the new value on the RSSI_FLT register */
+  g_xStatus = SpiritSpiWriteRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the CS Mode.
+ * @param  None.
+ * @retval CSMode CS mode.
+ */
+CSMode SpiritQiGetCsMode(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the RSSI_FLT register */
+  g_xStatus = SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+
+  /* Rebuild and returns the CS mode value */
+  return (CSMode)(tempRegValue & 0x0C);
+
+}
+
+/**
+ * @brief  Enables/Disables the CS Timeout Mask. If enabled CS value contributes to timeout disabling.
+ * @param  xNewState new state for CS Timeout Mask.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritQiCsTimeoutMask(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PROTOCOL2 register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+  /* Enables or disables the CS timeout mask */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL2_CS_TIMEOUT_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL2_CS_TIMEOUT_MASK;
+  }
+
+  /* Writes the new value on the PROTOCOL2 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Enables/Disables the PQI Timeout Mask. If enabled PQI value contributes to timeout disabling.
+ * @param  xNewState new state for PQI Timeout Mask.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritQiPqiTimeoutMask(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PROTOCOL2 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+  /* Enables or disables the PQI timeout mask */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL2_PQI_TIMEOUT_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL2_PQI_TIMEOUT_MASK;
+  }
+
+  /* Writes the new value on the PROTOCOL2 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Enables/Disables the SQI Timeout Mask. If enabled SQI value contributes to timeout disabling.
+ * @param  xNewState new state for SQI Timeout Mask.
+ *         This parameter can be S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritQiSqiTimeoutMask(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+
+  /* Reads the PROTOCOL2 register */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+  /* Enables or disables the SQI timeout mask */
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL2_SQI_TIMEOUT_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL2_SQI_TIMEOUT_MASK;
+  }
+
+  /* Writes the new value on the PROTOCOL2 register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ *@}
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Radio.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Radio.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3144 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_Radio.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   This file provides all the low level API to manage Analog and Digital
+  *          radio part of SPIRIT.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Radio.h"
+#include "MCU_Interface.h"
+#include <math.h>
+
+/** @addtogroup SPIRIT_Libraries
+* @{
+*/
+
+
+/** @addtogroup SPIRIT_Radio
+* @{
+*/
+
+
+/** @defgroup Radio_Private_TypesDefinitions            Radio Private Types Definitions
+* @{
+*/
+
+
+/**
+* @}
+*/
+
+
+/** @defgroup Radio_Private_Defines                     Radio Private Defines
+* @{
+*/
+
+
+
+
+/**
+* @}
+*/
+
+
+/** @defgroup Radio_Private_Macros                      Radio Private Macros
+* @{
+*/
+#define XTAL_FLAG(xtalFrequency)               (xtalFrequency>=25e6) ? XTAL_FLAG_26_MHz:XTAL_FLAG_24_MHz
+
+#define ROUND(A)                                  (((A-(uint32_t)A)> 0.5)? (uint32_t)A+1:(uint32_t)A)
+/**
+* @}
+*/
+
+
+/** @defgroup Radio_Private_Variables                   Radio Private Variables
+* @{
+*/
+/**
+* @brief  The Xtal frequency. To be set by the user (see SetXtalFreq() function)
+*/
+static uint32_t s_lXtalFrequency;
+
+/**
+* @brief  Factor is: B/2 used in the formula for SYNTH word calculation
+*/
+static const uint8_t s_vectcBHalfFactor[4]={(HIGH_BAND_FACTOR/2), (MIDDLE_BAND_FACTOR/2), (LOW_BAND_FACTOR/2), (VERY_LOW_BAND_FACTOR/2)};
+
+/**
+* @brief  BS value to write in the SYNT0 register according to the selected band
+*/
+static const uint8_t s_vectcBandRegValue[4]={SYNT0_BS_6, SYNT0_BS_12, SYNT0_BS_16, SYNT0_BS_32};
+
+
+/**
+* @brief  It represents the available channel bandwidth times 10 for 26 Mhz xtal.
+* @note   The channel bandwidth for others xtal frequencies can be computed since this table
+*         multiplying the current table by a factor xtal_frequency/26e6.
+*/
+static const uint16_t s_vectnBandwidth26M[90]=
+{
+  8001, 7951, 7684, 7368, 7051, 6709, 6423, 5867, 5414, \
+    4509, 4259, 4032, 3808, 3621, 3417, 3254, 2945, 2703, \
+      2247, 2124, 2015, 1900, 1807, 1706, 1624, 1471, 1350, \
+        1123, 1062, 1005,  950,  903,  853,  812,  735,  675, \
+          561,  530,  502,  474,  451,  426,  406,  367,  337, \
+            280,  265,  251,  237,  226,  213,  203,  184,  169, \
+              140,  133,  126,  119,  113,  106,  101,   92,   84, \
+                70,   66,   63,   59,   56,   53,   51,   46,   42, \
+                  35,   33,   31,   30,   28,   27,   25,   23,   21, \
+                    18,   17,   16,   15,   14,   13,   13,   12,   11
+};
+
+/**
+* @brief  It represents the available VCO frequencies
+*/
+static const uint16_t s_vectnVCOFreq[16]=
+{
+  4644, 4708, 4772, 4836, 4902, 4966, 5030, 5095, \
+    5161, 5232, 5303, 5375, 5448, 5519, 5592, 5663
+};
+
+/**
+* @brief  This variable is used to enable or disable
+*  the VCO calibration WA called at the end of the SpiritRadioSetFrequencyBase fcn.
+*  Default is enabled.
+*/
+static SpiritFunctionalState xDoVcoCalibrationWA=S_ENABLE;
+
+
+/**
+* @brief  These values are used to interpolate the power curves.
+*         Interpolation curves are linear in the following 3 regions:
+*       - reg value: 1 to 13    (up region)
+*       - reg value: 13 to 40   (mid region)
+*       - reg value: 41 to 90   (low region)
+*       power_reg = m*power_dBm + q
+*       For each band the order is: {m-up, q-up, m-mid, q-mid, m-low, q-low}.
+* @note The power interpolation curves have been extracted
+*       by measurements done on the divisional evaluation boards.
+*/
+static const float fPowerFactors[5][6]={ 
+  {-2.11,25.66,-2.11,25.66,-2.00,31.28},   /* 915 */
+  {-2.04,23.45,-2.04,23.45,-1.95,27.66},   /* 868 */
+  {-3.48,38.45,-1.89,27.66,-1.92,30.23},   /* 433 */
+  {-3.27,35.43,-1.80,26.31,-1.89,29.61},   /* 315 */
+  {-4.18,50.66,-1.80,30.04,-1.86,32.22},   /* 169 */
+};
+
+/**
+* @}
+*/
+
+
+/** @defgroup Radio_Private_FunctionPrototypes          Radio Private Function Prototypes
+* @{
+*/
+
+
+/**
+* @}
+*/
+
+
+/** @defgroup Radio_Private_Functions                    Radio Private Functions
+* @{
+*/
+
+/**
+* @brief  Initializes the SPIRIT analog and digital radio part according to the specified
+*         parameters in the pxSRadioInitStruct.
+* @param  pxSRadioInitStruct pointer to a SRadioInit structure that
+*         contains the configuration information for the analog radio part of SPIRIT.
+* @retval Error code: 0=no error, 1=error during calibration of VCO.
+*/
+uint8_t SpiritRadioInit(SRadioInit* pxSRadioInitStruct)
+{
+  int32_t FOffsetTmp;
+  uint8_t anaRadioRegArray[8], digRadioRegArray[4];
+  int16_t xtalOffsetFactor;
+  uint8_t drM, drE, FdevM, FdevE, bwM, bwE;
+    
+  /* Workaround for Vtune */
+  uint8_t value = 0xA0; SpiritSpiWriteRegisters(0x9F, 1, &value);
+  
+  /* Calculates the offset respect to RF frequency and according to xtal_ppm parameter: (xtal_ppm*FBase)/10^6 */
+  FOffsetTmp = (int32_t)(((float)pxSRadioInitStruct->nXtalOffsetPpm*pxSRadioInitStruct->lFrequencyBase)/PPM_FACTOR);
+  
+  /* Check the parameters */
+  s_assert_param(IS_FREQUENCY_BAND(pxSRadioInitStruct->lFrequencyBase));
+  s_assert_param(IS_MODULATION_SELECTED(pxSRadioInitStruct->xModulationSelect));
+  s_assert_param(IS_DATARATE(pxSRadioInitStruct->lDatarate));
+  s_assert_param(IS_FREQUENCY_OFFSET(FOffsetTmp,s_lXtalFrequency));
+  s_assert_param(IS_CHANNEL_SPACE(pxSRadioInitStruct->nChannelSpace,s_lXtalFrequency));
+  s_assert_param(IS_F_DEV(pxSRadioInitStruct->lFreqDev,s_lXtalFrequency));
+  
+  /* Disable the digital, ADC, SMPS reference clock divider if fXO>24MHz or fXO<26MHz */
+  SpiritSpiCommandStrobes(COMMAND_STANDBY);    
+  do{
+    /* Delay for state transition */
+    for(volatile uint8_t i=0; i!=0xFF; i++);
+    
+    /* Reads the MC_STATUS register */
+    SpiritRefreshStatus();
+  }while(g_xStatus.MC_STATE!=MC_STATE_STANDBY);
+  
+  if(s_lXtalFrequency<DOUBLE_XTAL_THR)
+  {
+    SpiritRadioSetDigDiv(S_DISABLE);
+    s_assert_param(IS_CH_BW(pxSRadioInitStruct->lBandwidth,s_lXtalFrequency));
+  }
+  else
+  {      
+    SpiritRadioSetDigDiv(S_ENABLE);
+    s_assert_param(IS_CH_BW(pxSRadioInitStruct->lBandwidth,(s_lXtalFrequency>>1)));
+  }
+  
+  /* Goes in READY state */
+  SpiritSpiCommandStrobes(COMMAND_READY);
+  do{
+    /* Delay for state transition */
+    for(volatile uint8_t i=0; i!=0xFF; i++);
+    
+    /* Reads the MC_STATUS register */
+    SpiritRefreshStatus();
+  }while(g_xStatus.MC_STATE!=MC_STATE_READY);
+  
+  /* Calculates the FC_OFFSET parameter and cast as signed int: FOffsetTmp = (Fxtal/2^18)*FC_OFFSET */
+  xtalOffsetFactor = (int16_t)(((float)FOffsetTmp*FBASE_DIVIDER)/s_lXtalFrequency);
+  anaRadioRegArray[2] = (uint8_t)((((uint16_t)xtalOffsetFactor)>>8)&0x0F);
+  anaRadioRegArray[3] = (uint8_t)(xtalOffsetFactor);
+  
+  /* Calculates the channel space factor */
+  anaRadioRegArray[0] =((uint32_t)pxSRadioInitStruct->nChannelSpace<<9)/(s_lXtalFrequency>>6)+1;
+  
+  SpiritManagementWaTRxFcMem(pxSRadioInitStruct->lFrequencyBase);
+  
+  /* 2nd order DEM algorithm enabling */
+  uint8_t tmpreg; SpiritSpiReadRegisters(0xA3, 1, &tmpreg);
+  tmpreg &= ~0x02; SpiritSpiWriteRegisters(0xA3, 1, &tmpreg);
+  
+  /* Check the channel center frequency is in one of the possible range */
+  s_assert_param(IS_FREQUENCY_BAND((pxSRadioInitStruct->lFrequencyBase + ((xtalOffsetFactor*s_lXtalFrequency)/FBASE_DIVIDER) + pxSRadioInitStruct->nChannelSpace * pxSRadioInitStruct->cChannelNumber)));  
+  
+  /* Calculates the datarate mantissa and exponent */
+  SpiritRadioSearchDatarateME(pxSRadioInitStruct->lDatarate, &drM, &drE);
+  digRadioRegArray[0] = (uint8_t)(drM);
+  digRadioRegArray[1] = (uint8_t)(0x00 | pxSRadioInitStruct->xModulationSelect |drE);
+  
+  /* Read the fdev register to preserve the clock recovery algo bit */
+  SpiritSpiReadRegisters(0x1C, 1, &tmpreg);
+  
+  /* Calculates the frequency deviation mantissa and exponent */
+  SpiritRadioSearchFreqDevME(pxSRadioInitStruct->lFreqDev, &FdevM, &FdevE);
+  digRadioRegArray[2] = (uint8_t)((FdevE<<4) | (tmpreg&0x08) | FdevM);
+  
+  /* Calculates the channel filter mantissa and exponent */
+  SpiritRadioSearchChannelBwME(pxSRadioInitStruct->lBandwidth, &bwM, &bwE);
+  
+  digRadioRegArray[3] = (uint8_t)((bwM<<4) | bwE);
+ 
+  float if_off=(3.0*480140)/(s_lXtalFrequency>>12)-64;
+  
+  uint8_t ifOffsetAna = ROUND(if_off);
+  
+  if(s_lXtalFrequency<DOUBLE_XTAL_THR)
+  {
+    /* if offset digital is the same in case of single xtal */
+    anaRadioRegArray[1] = ifOffsetAna;
+  }
+  else
+  {
+    if_off=(3.0*480140)/(s_lXtalFrequency>>13)-64;
+    
+    /* ... otherwise recompute it */
+    anaRadioRegArray[1] = ROUND(if_off);
+  }
+//  if(s_lXtalFrequency==24000000) {
+//    ifOffsetAna = 0xB6;
+//    anaRadioRegArray[1] = 0xB6;
+//  }
+//  if(s_lXtalFrequency==25000000) {
+//    ifOffsetAna = 0xAC;
+//    anaRadioRegArray[1] = 0xAC;
+//  }
+//  if(s_lXtalFrequency==26000000) {
+//    ifOffsetAna = 0xA3;
+//    anaRadioRegArray[1] = 0xA3;
+//  }
+//  if(s_lXtalFrequency==48000000) {
+//    ifOffsetAna = 0x3B;
+//    anaRadioRegArray[1] = 0xB6;
+//  }
+//  if(s_lXtalFrequency==50000000) {
+//    ifOffsetAna = 0x36;
+//    anaRadioRegArray[1] = 0xAC;
+//  }
+//  if(s_lXtalFrequency==52000000) {
+//    ifOffsetAna = 0x31;
+//    anaRadioRegArray[1] = 0xA3;
+//  }
+  
+  g_xStatus = SpiritSpiWriteRegisters(IF_OFFSET_ANA_BASE, 1, &ifOffsetAna);
+
+  
+  /* Sets Xtal configuration */
+  if(s_lXtalFrequency>DOUBLE_XTAL_THR)
+  {
+    SpiritRadioSetXtalFlag(XTAL_FLAG((s_lXtalFrequency/2)));
+  }
+  else
+  {
+    SpiritRadioSetXtalFlag(XTAL_FLAG(s_lXtalFrequency));
+  }
+  
+  /* Sets the channel number in the corresponding register */
+  SpiritSpiWriteRegisters(CHNUM_BASE, 1, &pxSRadioInitStruct->cChannelNumber);
+  
+  /* Configures the Analog Radio registers */
+  SpiritSpiWriteRegisters(CHSPACE_BASE, 4, anaRadioRegArray);
+  
+  /* Configures the Digital Radio registers */
+  g_xStatus = SpiritSpiWriteRegisters(MOD1_BASE, 4, digRadioRegArray);
+  
+  /* Enable the freeze option of the AFC on the SYNC word */
+  SpiritRadioAFCFreezeOnSync(S_ENABLE);
+  
+  /* Set the IQC correction optimal value */
+  anaRadioRegArray[0]=0x80;
+  anaRadioRegArray[1]=0xE3;
+  g_xStatus = SpiritSpiWriteRegisters(0x99, 2, anaRadioRegArray);
+  
+  return SpiritRadioSetFrequencyBase(pxSRadioInitStruct->lFrequencyBase);
+  
+}
+
+
+/**
+* @brief  Returns the SPIRIT analog and digital radio structure according to the registers value.
+* @param  pxSRadioInitStruct pointer to a SRadioInit structure that
+*         contains the configuration information for the analog radio part of SPIRIT.
+* @retval None.
+*/
+void SpiritRadioGetInfo(SRadioInit* pxSRadioInitStruct)
+{
+  uint8_t anaRadioRegArray[8], digRadioRegArray[4];
+  BandSelect band;
+  int16_t xtalOffsetFactor;
+  
+  /* Get the RF board version */
+  //SpiritVersion xSpiritVersion = SpiritGeneralGetSpiritVersion();
+  
+  /* Reads the Analog Radio registers */
+  SpiritSpiReadRegisters(SYNT3_BASE, 8, anaRadioRegArray);
+  
+  /* Reads the Digital Radio registers */
+  g_xStatus = SpiritSpiReadRegisters(MOD1_BASE, 4, digRadioRegArray);
+  
+  /* Reads the operating band masking the Band selected field */
+  if((anaRadioRegArray[3] & 0x07) == SYNT0_BS_6)
+  {
+    band = HIGH_BAND;
+  }
+  else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_12)
+  {
+    band = MIDDLE_BAND;
+  }
+  else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_16)
+  {
+    band = LOW_BAND;
+  }
+  else if ((anaRadioRegArray[3] & 0x07) == SYNT0_BS_32)
+  {
+    band = VERY_LOW_BAND;
+  }
+  else
+  {
+    /* if it is another value, set it to a valid one in order to avoid access violation */
+    uint8_t tmp=(anaRadioRegArray[3]&0xF8)|SYNT0_BS_6;
+    SpiritSpiWriteRegisters(SYNT0_BASE,1,&tmp);
+    band = HIGH_BAND;
+  }
+  
+  /* Computes the synth word */
+  uint32_t synthWord = (uint32_t)((((uint32_t)(anaRadioRegArray[0]&0x1F))<<21)+(((uint32_t)(anaRadioRegArray[1]))<<13)+\
+    (((uint32_t)(anaRadioRegArray[2]))<<5)+(((uint32_t)(anaRadioRegArray[3]))>>3));
+  
+  /* Calculates the frequency base */
+  uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1;
+  pxSRadioInitStruct->lFrequencyBase = (uint32_t)round(synthWord*(((double)s_lXtalFrequency)/(FBASE_DIVIDER*cRefDiv*s_vectcBHalfFactor[band])));
+  
+  /* Calculates the Offset Factor */
+  uint16_t xtalOffTemp = ((((uint16_t)anaRadioRegArray[6])<<8)+((uint16_t)anaRadioRegArray[7]));
+  
+  /* If a negative number then convert the 12 bit 2-complement in a 16 bit number */
+  if(xtalOffTemp & 0x0800)
+  {
+    xtalOffTemp = xtalOffTemp | 0xF000;
+  }
+  else
+  {
+    xtalOffTemp = xtalOffTemp & 0x0FFF;
+  }
+  
+  xtalOffsetFactor = *((int16_t*)(&xtalOffTemp));
+  
+  /* Calculates the frequency offset in ppm */
+  pxSRadioInitStruct->nXtalOffsetPpm =(int16_t)((uint32_t)xtalOffsetFactor*s_lXtalFrequency*PPM_FACTOR)/((uint32_t)FBASE_DIVIDER*pxSRadioInitStruct->lFrequencyBase);
+  
+  /* Channel space */
+  pxSRadioInitStruct->nChannelSpace = anaRadioRegArray[4]*(s_lXtalFrequency>>15);
+  
+  /* Channel number */
+  pxSRadioInitStruct->cChannelNumber = SpiritRadioGetChannel();
+  
+  /* Modulation select */
+  pxSRadioInitStruct->xModulationSelect = (ModulationSelect)(digRadioRegArray[1] & 0x70);
+  
+  /* Reads the frequency deviation for mantissa and exponent */
+  uint8_t FDevM = digRadioRegArray[2]&0x07;
+  uint8_t FDevE = (digRadioRegArray[2]&0xF0)>>4;
+  
+  /* Reads the channel filter register for mantissa and exponent */
+  uint8_t bwM = (digRadioRegArray[3]&0xF0)>>4;
+  uint8_t bwE = digRadioRegArray[3]&0x0F;
+  
+  uint8_t cDivider = 0;
+  cDivider = SpiritRadioGetDigDiv();
+  
+  /* Calculates the datarate */
+  pxSRadioInitStruct->lDatarate = ((s_lXtalFrequency>>(5+cDivider))*(256+digRadioRegArray[0]))>>(23-(digRadioRegArray[1]&0x0F));
+  
+  /* Calculates the frequency deviation */
+  // (((s_lXtalFrequency>>6)*(8+FDevM))>>(12-FDevE+cCorrection));
+  pxSRadioInitStruct->lFreqDev =(uint32_t)((float)s_lXtalFrequency/(((uint32_t)1)<<18)*(uint32_t)((8.0+FDevM)/2*(1<<FDevE)));
+  
+  /* Reads the channel filter bandwidth from the look-up table and return it */
+  pxSRadioInitStruct->lBandwidth = (uint32_t)(100.0*s_vectnBandwidth26M[bwM+(bwE*9)]*((s_lXtalFrequency>>cDivider)/26e6));
+  
+}
+
+
+/**
+* @brief  Sets the Xtal configuration in the ANA_FUNC_CONF0 register.
+* @param  xXtal one of the possible value of the enum type XtalFrequency.
+*         @arg XTAL_FLAG_24_MHz:  in case of 24 MHz crystal
+*         @arg XTAL_FLAG_26_MHz:  in case of 26 MHz crystal
+* @retval None.
+*/
+void SpiritRadioSetXtalFlag(XtalFlag xXtal)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_XTAL_FLAG(xXtal));
+  
+  /* Reads the ANA_FUNC_CONF_0 register */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+  if(xXtal == XTAL_FLAG_26_MHz)
+  {
+    tempRegValue|=SELECT_24_26_MHZ_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~SELECT_24_26_MHZ_MASK);
+  }
+  
+  /* Sets the 24_26MHz_SELECT field in the ANA_FUNC_CONF_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the Xtal configuration in the ANA_FUNC_CONF0 register.
+* @param  None.
+* @retval XtalFrequency Settled Xtal configuration.
+*/
+XtalFlag SpiritRadioGetXtalFlag(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the Xtal configuration in the ANA_FUNC_CONF_0 register and return the value */
+  g_xStatus = SpiritSpiReadRegisters(ANA_FUNC_CONF0_BASE, 1, &tempRegValue);
+  
+  return (XtalFlag)((tempRegValue & 0x40)>>6);
+  
+}
+
+
+/**
+* @brief  Returns the charge pump word for a given VCO frequency.
+* @param  lFc channel center frequency expressed in Hz.
+*         This parameter can be a value in one of the following ranges:<ul>
+*         <li> High_Band: from 779 MHz to 915 MHz </li>
+*         <li> Middle Band: from 387 MHz to 470 MHz </li>
+*         <li> Low Band: from 300 MHz to 348 MHz </li>
+*         <li> Very low Band: from 150 MHz to 174 MHz </li> </ul>
+* @retval uint8_t Charge pump word.
+*/
+uint8_t SpiritRadioSearchWCP(uint32_t lFc)
+{
+  int8_t i;
+  uint32_t vcofreq;
+  uint8_t BFactor;
+  
+  /* Check the channel center frequency is in one of the possible range */
+  s_assert_param(IS_FREQUENCY_BAND(lFc));
+  
+  /* Search the operating band */
+  if(IS_FREQUENCY_BAND_HIGH(lFc))
+  {
+    BFactor = HIGH_BAND_FACTOR;
+  }
+  else if(IS_FREQUENCY_BAND_MIDDLE(lFc))
+  {
+    BFactor = MIDDLE_BAND_FACTOR;
+  }
+  else if(IS_FREQUENCY_BAND_LOW(lFc))
+  {
+    BFactor = LOW_BAND_FACTOR;
+  }
+  else
+  {
+    BFactor = VERY_LOW_BAND_FACTOR;
+  }
+  
+  /* Calculates the VCO frequency VCOFreq = lFc*B */
+  vcofreq = (lFc/1000000)*BFactor;
+  
+  /* Search in the vco frequency array the charge pump word */
+  if(vcofreq>=s_vectnVCOFreq[15])
+  {
+    i=15;
+  }
+  else
+  {
+    /* Search the value */
+    for(i=0 ; i<15 && vcofreq>s_vectnVCOFreq[i] ; i++);
+    
+    /* Be sure that it is the best approssimation */
+    if (i!=0 && s_vectnVCOFreq[i]-vcofreq>vcofreq-s_vectnVCOFreq[i-1])
+      i--;
+  }
+  
+  /* Return index */
+  return (i%8);
+  
+}
+
+/**
+* @brief  Returns the synth word.
+* @param  None.
+* @retval uint32_t Synth word.
+*/
+uint32_t SpiritRadioGetSynthWord(void)
+{
+  uint8_t regArray[4];
+  
+  /* Reads the SYNTH registers, build the synth word and return it */
+  g_xStatus = SpiritSpiReadRegisters(SYNT3_BASE, 4, regArray);
+  return ((((uint32_t)(regArray[0]&0x1F))<<21)+(((uint32_t)(regArray[1]))<<13)+\
+    (((uint32_t)(regArray[2]))<<5)+(((uint32_t)(regArray[3]))>>3));
+  
+}
+
+
+/**
+* @brief  Sets the SYNTH registers.
+* @param  lSynthWord the synth word to write in the SYNTH[3:0] registers.
+* @retval None.
+*/
+void SpiritRadioSetSynthWord(uint32_t lSynthWord)
+{
+  uint8_t tempArray[4];
+  uint8_t tempRegValue;
+  
+  /* Reads the SYNT0 register */
+  g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue);
+  
+  /* Mask the Band selected field */
+  tempRegValue &= 0x07;
+  
+  /* Build the array for SYNTH registers */
+  tempArray[0] = (uint8_t)((lSynthWord>>21)&(0x0000001F));
+  tempArray[1] = (uint8_t)((lSynthWord>>13)&(0x000000FF));
+  tempArray[2] = (uint8_t)((lSynthWord>>5)&(0x000000FF));
+  tempArray[3] = (uint8_t)(((lSynthWord&0x0000001F)<<3)| tempRegValue);
+  
+  /* Writes the synth word in the SYNTH registers */
+  g_xStatus = SpiritSpiWriteRegisters(SYNT3_BASE, 4, tempArray);
+  
+}
+
+
+/**
+* @brief  Sets the operating band.
+* @param  xBand the band to set.
+*         This parameter can be one of following parameters:
+*         @arg  HIGH_BAND   High_Band selected: from 779 MHz to 915 MHz
+*         @arg  MIDDLE_BAND: Middle Band selected: from 387 MHz to 470 MHz
+*         @arg  LOW_BAND:  Low Band selected: from 300 MHz to 348 MHz
+*         @arg  VERY_LOW_BAND:  Very low Band selected: from 150 MHz to 174 MHz
+* @retval None.
+*/
+void SpiritRadioSetBand(BandSelect xBand)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_BAND_SELECTED(xBand));
+  
+  /* Reads the SYNT0 register*/
+  g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue);
+  
+  /* Mask the SYNTH[4;0] field and write the BS value */
+  tempRegValue &= 0xF8;
+  tempRegValue |= s_vectcBandRegValue[xBand];
+  
+  /* Configures the SYNT0 register setting the operating band */
+  g_xStatus = SpiritSpiWriteRegisters(SYNT0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the operating band.
+* @param  None.
+* @retval BandSelect Settled band.
+*         This returned value can be one of the following parameters:
+*         @arg  HIGH_BAND   High_Band selected: from 779 MHz to 915 MHz
+*         @arg  MIDDLE_BAND: Middle Band selected: from 387 MHz to 470 MHz
+*         @arg  LOW_BAND:  Low Band selected: from 300 MHz to 348 MHz
+*         @arg  VERY_LOW_BAND:  Very low Band selected: from 150 MHz to 174 MHz
+*/
+BandSelect SpiritRadioGetBand(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the SYNT0 register */
+  g_xStatus = SpiritSpiReadRegisters(SYNT0_BASE, 1, &tempRegValue);
+  
+  /* Mask the Band selected field */
+  if((tempRegValue & 0x07) == SYNT0_BS_6)
+  {
+    return HIGH_BAND;
+  }
+  else if ((tempRegValue & 0x07) == SYNT0_BS_12)
+  {
+    return MIDDLE_BAND;
+  }
+  else if ((tempRegValue & 0x07) == SYNT0_BS_16)
+  {
+    return LOW_BAND;
+  }
+  else
+  {
+    return VERY_LOW_BAND;
+  }
+  
+}
+
+
+/**
+* @brief  Sets the channel number.
+* @param  cChannel the channel number.
+* @retval None.
+*/
+void SpiritRadioSetChannel(uint8_t cChannel)
+{
+  /* Writes the CHNUM register */
+  g_xStatus = SpiritSpiWriteRegisters(CHNUM_BASE, 1, &cChannel);
+  
+}
+
+
+/**
+* @brief  Returns the actual channel number.
+* @param  None.
+* @retval uint8_t Actual channel number.
+*/
+uint8_t SpiritRadioGetChannel(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the CHNUM register and return the value */
+  g_xStatus = SpiritSpiReadRegisters(CHNUM_BASE, 1, &tempRegValue);
+  
+  return tempRegValue;
+  
+}
+
+
+/**
+* @brief  Sets the channel space factor in channel space register.
+*         The channel spacing step is computed as F_Xo/32768.
+* @param  fChannelSpace the channel space expressed in Hz.
+* @retval None.
+*/
+void SpiritRadioSetChannelSpace(uint32_t fChannelSpace)
+{
+  uint8_t cChannelSpaceFactor;
+  
+  /* Round to the nearest integer */
+  cChannelSpaceFactor = ((uint32_t)fChannelSpace*CHSPACE_DIVIDER)/s_lXtalFrequency;
+  
+  /* Write value into the register */
+  g_xStatus = SpiritSpiWriteRegisters(CHSPACE_BASE, 1, &cChannelSpaceFactor);
+  
+}
+
+
+/**
+* @brief  Returns the channel space register.
+* @param  None.
+* @retval uint32_t Channel space. The channel space is: CS = channel_space_factor x XtalFrequency/2^15
+*         where channel_space_factor is the CHSPACE register value.
+*/
+uint32_t SpiritRadioGetChannelSpace(void)
+{
+  uint8_t channelSpaceFactor;
+  
+  /* Reads the CHSPACE register, calculate the channel space and return it */
+  g_xStatus = SpiritSpiReadRegisters(CHSPACE_BASE, 1, &channelSpaceFactor);
+  
+  /* Compute the Hertz value and return it */
+  return ((channelSpaceFactor*s_lXtalFrequency)/CHSPACE_DIVIDER);
+  
+}
+
+
+/**
+* @brief  Sets the FC OFFSET register starting from xtal ppm value.
+* @param  nXtalPpm the xtal offset expressed in ppm.
+* @retval None.
+*/
+void SpiritRadioSetFrequencyOffsetPpm(int16_t nXtalPpm)
+{
+  uint8_t tempArray[2];
+  int16_t xtalOffsetFactor;
+  uint32_t synthWord, fBase;
+  int32_t FOffsetTmp;
+  BandSelect band;
+  
+  /* Reads the synth word */
+  synthWord = SpiritRadioGetSynthWord();
+  
+  /* Reads the operating band */
+  band = SpiritRadioGetBand();
+  
+  /* Calculates the frequency base */
+  uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1;
+  fBase = synthWord*(s_lXtalFrequency/(s_vectcBHalfFactor[band]*cRefDiv)/FBASE_DIVIDER);
+  
+  /* Calculates the offset respect to RF frequency and according to xtal_ppm parameter */
+  FOffsetTmp = (int32_t)(((float)nXtalPpm*fBase)/PPM_FACTOR);
+  
+  /* Check the Offset is in the correct range */
+  s_assert_param(IS_FREQUENCY_OFFSET(FOffsetTmp,s_lXtalFrequency));
+  
+  /* Calculates the FC_OFFSET value to write in the corresponding register */  
+  xtalOffsetFactor = (int16_t)(((float)FOffsetTmp*FBASE_DIVIDER)/s_lXtalFrequency);
+  
+  /* Build the array related to the FC_OFFSET_1 and FC_OFFSET_0 register */
+  tempArray[0]=(uint8_t)((((uint16_t)xtalOffsetFactor)>>8)&0x0F);
+  tempArray[1]=(uint8_t)(xtalOffsetFactor);
+  
+  /* Writes the FC_OFFSET registers */
+  g_xStatus = SpiritSpiWriteRegisters(FC_OFFSET1_BASE, 2, tempArray);
+  
+}
+
+
+/**
+* @brief  Sets the FC OFFSET register starting from frequency offset expressed in Hz.
+* @param  lFOffset frequency offset expressed in Hz as signed word.
+* @retval None.
+*/
+void SpiritRadioSetFrequencyOffset(int32_t lFOffset)
+{
+  uint8_t tempArray[2];
+  int16_t offset;
+  
+  /* Check that the Offset is in the correct range */
+  s_assert_param(IS_FREQUENCY_OFFSET(lFOffset,s_lXtalFrequency));
+  
+  /* Calculates the offset value to write in the FC_OFFSET register */
+  offset = (int16_t)(((float)lFOffset*FBASE_DIVIDER)/s_lXtalFrequency);
+  
+  /* Build the array related to the FC_OFFSET_1 and FC_OFFSET_0 register */
+  tempArray[0]=(uint8_t)((((uint16_t)offset)>>8)&0x0F);
+  tempArray[1]=(uint8_t)(offset);
+  
+  /* Writes the FC_OFFSET registers */
+  g_xStatus = SpiritSpiWriteRegisters(FC_OFFSET1_BASE, 2, tempArray);
+  
+}
+
+
+/**
+* @brief  Returns the actual frequency offset.
+* @param  None.
+* @retval int32_t Frequency offset expressed in Hz as signed word.
+*/
+int32_t SpiritRadioGetFrequencyOffset(void)
+{
+  uint8_t tempArray[2];
+  int16_t xtalOffsetFactor;
+  
+  /* Reads the FC_OFFSET registers */
+  g_xStatus = SpiritSpiReadRegisters(FC_OFFSET1_BASE, 2, tempArray);
+  
+  /* Calculates the Offset Factor */
+  uint16_t xtalOffTemp = ((((uint16_t)tempArray[0])<<8)+((uint16_t)tempArray[1]));
+  
+  if(xtalOffTemp & 0x0800)
+  {
+    xtalOffTemp = xtalOffTemp | 0xF000;
+  }
+  else
+  {
+    xtalOffTemp = xtalOffTemp & 0x0FFF;
+  }
+  
+  xtalOffsetFactor = *((int16_t*)(&xtalOffTemp));
+  
+  /* Calculates the frequency offset and return it */
+  return ((int32_t)(xtalOffsetFactor*s_lXtalFrequency)/FBASE_DIVIDER);
+  
+}
+
+
+
+/**
+* @brief  Sets the Synth word and the Band Select register according to desired base carrier frequency.
+*         In this API the Xtal configuration is read out from
+*         the corresponding register. The user shall fix it before call this API.
+* @param  lFBase the base carrier frequency expressed in Hz as unsigned word.
+* @retval Error code: 0=no error, 1=error during calibration of VCO.
+*/
+uint8_t SpiritRadioSetFrequencyBase(uint32_t lFBase)
+{
+  uint32_t synthWord, Fc;
+  uint8_t band, anaRadioRegArray[4], wcp;
+  
+  /* Check the parameter */
+  s_assert_param(IS_FREQUENCY_BAND(lFBase));
+  
+  /* Search the operating band */
+  if(IS_FREQUENCY_BAND_HIGH(lFBase))
+  {
+    band = HIGH_BAND;
+  }
+  else if(IS_FREQUENCY_BAND_MIDDLE(lFBase))
+  {
+    band = MIDDLE_BAND;
+  }
+  else if(IS_FREQUENCY_BAND_LOW(lFBase))
+  {
+    band = LOW_BAND;
+  }
+  else
+  {
+    band = VERY_LOW_BAND;
+  }
+  
+  int32_t FOffset  = SpiritRadioGetFrequencyOffset();
+  uint32_t lChannelSpace  = SpiritRadioGetChannelSpace();
+  uint8_t cChannelNum = SpiritRadioGetChannel();
+  
+  /* Calculates the channel center frequency */
+  Fc = lFBase + FOffset + lChannelSpace*cChannelNum;
+  
+  /* Reads the reference divider */
+  uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv()+1;
+  
+  /* Selects the VCO */
+  switch(band)
+  {
+  case VERY_LOW_BAND:
+    if(Fc<161281250)
+    {
+      SpiritCalibrationSelectVco(VCO_L);
+    }
+    else
+    {
+      SpiritCalibrationSelectVco(VCO_H);
+    }
+    break;
+    
+  case LOW_BAND:
+    if(Fc<322562500)
+    {
+      SpiritCalibrationSelectVco(VCO_L);
+    }
+    else
+    {
+      SpiritCalibrationSelectVco(VCO_H);
+    }
+    break;
+    
+  case MIDDLE_BAND:
+    if(Fc<430083334)
+    {
+      SpiritCalibrationSelectVco(VCO_L);
+    }
+    else
+    {
+      SpiritCalibrationSelectVco(VCO_H);
+    }
+    break;
+    
+  case HIGH_BAND:
+    if(Fc<860166667)
+    {
+      SpiritCalibrationSelectVco(VCO_L);
+    }
+    else
+    {
+      SpiritCalibrationSelectVco(VCO_H);
+    }
+  }
+  
+  /* Search the VCO charge pump word and set the corresponding register */
+  wcp = SpiritRadioSearchWCP(Fc);
+  
+  synthWord = (uint32_t)(lFBase*s_vectcBHalfFactor[band]*(((double)(FBASE_DIVIDER*cRefDiv))/s_lXtalFrequency));
+  
+  /* Build the array of registers values for the analog part */
+  anaRadioRegArray[0] = (uint8_t)(((synthWord>>21)&(0x0000001F))|(wcp<<5));
+  anaRadioRegArray[1] = (uint8_t)((synthWord>>13)&(0x000000FF));
+  anaRadioRegArray[2] = (uint8_t)((synthWord>>5)&(0x000000FF));
+  anaRadioRegArray[3] = (uint8_t)(((synthWord&0x0000001F)<<3)| s_vectcBandRegValue[band]);
+  
+  /* Configures the needed Analog Radio registers */
+  g_xStatus = SpiritSpiWriteRegisters(SYNT3_BASE, 4, anaRadioRegArray);
+  
+  if(xDoVcoCalibrationWA==S_ENABLE)
+    return SpiritManagementWaVcoCalibration();
+  
+  return 0;
+}
+
+/**
+* @brief  To say to the set frequency base if do or not the VCO calibration WA.
+* @param  S_ENABLE or S_DISABLE the WA procedure.
+* @retval None.
+*/
+void SpiritRadioVcoCalibrationWAFB(SpiritFunctionalState xNewstate)
+{
+  xDoVcoCalibrationWA=xNewstate;
+}
+
+/**
+* @brief  Returns the base carrier frequency.
+* @param  None.
+* @retval uint32_t Base carrier frequency expressed in Hz as unsigned word.
+*/
+uint32_t SpiritRadioGetFrequencyBase(void)
+{
+  uint32_t synthWord;
+  BandSelect band;
+  
+  /* Reads the synth word */
+  synthWord = SpiritRadioGetSynthWord();
+  
+  /* Reads the operating band */
+  band = SpiritRadioGetBand();
+  
+  uint8_t cRefDiv = (uint8_t)SpiritRadioGetRefDiv() + 1;
+  
+  /* Calculates the frequency base and return it */
+  return (uint32_t)round(synthWord*(((double)s_lXtalFrequency)/(FBASE_DIVIDER*cRefDiv*s_vectcBHalfFactor[band])));
+}
+
+
+/**
+* @brief  Returns the actual channel center frequency.
+* @param  None.
+* @retval uint32_t Actual channel center frequency expressed in Hz.
+*/
+uint32_t SpiritRadioGetCenterFrequency(void)
+{
+  int32_t offset;
+  uint8_t channel;
+  uint32_t fBase;
+  uint32_t channelSpace;
+  
+  /* Reads the frequency base */
+  fBase = SpiritRadioGetFrequencyBase();
+  
+  /* Reads the frequency offset */
+  offset = SpiritRadioGetFrequencyOffset();
+  
+  /* Reads the channel space */
+  channelSpace = SpiritRadioGetChannelSpace();
+  
+  /* Reads the channel number */
+  channel = SpiritRadioGetChannel();
+  
+  /* Calculates the channel center frequency and return it */
+  return (uint32_t)(fBase +  offset + (uint32_t)(channelSpace*channel));
+  
+}
+
+
+/**
+* @brief  Returns the mantissa and exponent, whose value used in the datarate formula
+*         will give the datarate value closer to the given datarate.
+* @param  fDatarate datarate expressed in bps. This parameter ranging between 100 and 500000.
+* @param  pcM pointer to the returned mantissa value.
+* @param  pcE pointer to the returned exponent value.
+* @retval None.
+*/
+void SpiritRadioSearchDatarateME(uint32_t lDatarate, uint8_t* pcM, uint8_t* pcE)
+{
+  volatile SpiritBool find = S_FALSE;
+  int8_t i=15;
+  uint8_t cMantissaTmp;
+  uint8_t cDivider = 0;
+  
+  /* Check the parameters */
+  s_assert_param(IS_DATARATE(lDatarate));
+  
+  cDivider = (uint8_t)SpiritRadioGetDigDiv();
+  
+  /* Search in the datarate array the exponent value */
+  while(!find && i>=0)
+  {
+    if(lDatarate>=(s_lXtalFrequency>>(20-i+cDivider)))
+    {
+      find = S_TRUE;
+    }
+    else
+    {
+      i--;
+    }
+  }
+  i<0 ? i=0 : i;
+  *pcE = i;
+  
+  /* Calculates the mantissa value according to the datarate formula */
+  cMantissaTmp = (lDatarate*((uint32_t)1<<(23-i)))/(s_lXtalFrequency>>(5+cDivider))-256;
+  
+  /* Finds the mantissa value with less approximation */
+  int16_t mantissaCalculation[3];
+  for(uint8_t j=0;j<3;j++)
+  {
+    if((cMantissaTmp+j-1))
+    {
+      mantissaCalculation[j]=lDatarate-(((256+cMantissaTmp+j-1)*(s_lXtalFrequency>>(5+cDivider)))>>(23-i));
+    }
+    else
+    {
+      mantissaCalculation[j]=0x7FFF;
+    }
+  }
+  uint16_t mantissaCalculationDelta = 0xFFFF;
+  for(uint8_t j=0;j<3;j++)
+  {
+    if(S_ABS(mantissaCalculation[j])<mantissaCalculationDelta)
+    {
+      mantissaCalculationDelta = S_ABS(mantissaCalculation[j]);
+      *pcM = cMantissaTmp+j-1;
+    }
+  }
+  
+}
+
+
+/**
+* @brief  Returns the mantissa and exponent for a given bandwidth.
+*         Even if it is possible to pass as parameter any value in the below mentioned range,
+*         the API will search the closer value according to a fixed table of channel
+*         bandwidth values (@ref s_vectnBandwidth), as defined in the datasheet, returning the corresponding mantissa
+*         and exponent value.
+* @param  lBandwidth bandwidth expressed in Hz. This parameter ranging between 1100 and 800100.
+* @param  pcM pointer to the returned mantissa value.
+* @param  pcE pointer to the returned exponent value.
+* @retval None.
+*/
+void SpiritRadioSearchChannelBwME(uint32_t lBandwidth, uint8_t* pcM, uint8_t* pcE)
+{
+  int8_t i, i_tmp;
+  uint8_t cDivider = 1;
+  
+    /* Search in the channel filter bandwidth table the exponent value */
+  if(SpiritRadioGetDigDiv())
+  {
+    cDivider = 2;
+  }
+  else
+  {
+    cDivider = 1;
+  }
+    
+  s_assert_param(IS_CH_BW(lBandwidth,s_lXtalFrequency/cDivider));
+  
+  uint32_t lChfltFactor = (s_lXtalFrequency/cDivider)/100;
+  
+  for(i=0;i<90 && (lBandwidth<(uint32_t)((s_vectnBandwidth26M[i]*lChfltFactor)/2600));i++);
+  
+  if(i!=0)
+  {
+    /* Finds the mantissa value with less approximation */
+    i_tmp=i;
+    int16_t chfltCalculation[3];
+    for(uint8_t j=0;j<3;j++) 
+    {
+      if(((i_tmp+j-1)>=0) || ((i_tmp+j-1)<=89))
+      {
+        chfltCalculation[j] = lBandwidth - (uint32_t)((s_vectnBandwidth26M[i_tmp+j-1]*lChfltFactor)/2600);
+      }
+      else
+      {
+        chfltCalculation[j] = 0x7FFF;
+      }
+    }
+    uint16_t chfltDelta = 0xFFFF;
+    
+    for(uint8_t j=0;j<3;j++)
+    {
+      if(S_ABS(chfltCalculation[j])<chfltDelta)
+      {
+        chfltDelta = S_ABS(chfltCalculation[j]);
+        i=i_tmp+j-1;
+      }    
+    }
+  }
+  (*pcE) = (uint8_t)(i/9);
+  (*pcM) = (uint8_t)(i%9);
+  
+}
+
+/**
+* @brief  Returns the mantissa and exponent, whose value used in the frequency deviation formula
+*         will give a frequency deviation value most closer to the given frequency deviation.
+* @param  fFDev frequency deviation expressed in Hz. This parameter can be a value in the range [F_Xo*8/2^18, F_Xo*7680/2^18].
+* @param  pcM pointer to the returned mantissa value.
+* @param  pcE pointer to the returned exponent value.
+* @retval None.
+*/
+void SpiritRadioSearchFreqDevME(uint32_t lFDev, uint8_t* pcM, uint8_t* pcE)
+{
+  uint8_t i;
+  uint32_t a,bp,b=0;
+  float xtalDivtmp=(float)s_lXtalFrequency/(((uint32_t)1)<<18);
+  
+  /* Check the parameters */
+  s_assert_param(IS_F_DEV(lFDev,s_lXtalFrequency));
+  
+  for(i=0;i<10;i++)
+  {
+    a=(uint32_t)(xtalDivtmp*(uint32_t)(7.5*(1<<i)));
+    if(lFDev<a)
+      break;
+  }
+  (*pcE) = i;
+  
+  for(i=0;i<8;i++)
+  {
+    bp=b;
+    b=(uint32_t)(xtalDivtmp*(uint32_t)((8.0+i)/2*(1<<(*pcE))));
+    if(lFDev<b)
+      break;
+  }
+  
+  (*pcM)=i;
+  if((lFDev-bp)<(b-lFDev))
+    (*pcM)--;
+  
+}
+
+
+/**
+* @brief  Sets the datarate.
+* @param  fDatarate datarate expressed in bps. This value shall be in the range
+*         [100 500000].
+* @retval None.
+*/
+void SpiritRadioSetDatarate(uint32_t lDatarate)
+{
+  uint8_t drE, tempRegValue[2];
+  
+  /* Check the parameters */
+  s_assert_param(IS_DATARATE(lDatarate));
+  
+  /* Calculates the datarate mantissa and exponent */
+  SpiritRadioSearchDatarateME(lDatarate, &tempRegValue[0], &drE);
+  
+  /* Reads the MOD_O register*/
+  SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue[1]);
+  
+  /* Mask the other fields and set the datarate exponent */
+  tempRegValue[1] &= 0xF0;
+  tempRegValue[1] |= drE;
+  
+  /* Writes the Datarate registers */
+  g_xStatus = SpiritSpiWriteRegisters(MOD1_BASE, 2, tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the datarate.
+* @param  None.
+* @retval uint32_t Settled datarate expressed in bps.
+*/
+uint32_t SpiritRadioGetDatarate(void)
+{
+  uint8_t tempRegValue[2];
+  uint8_t cDivider=0;
+  
+  /* Reads the datarate registers for mantissa and exponent */
+  g_xStatus = SpiritSpiReadRegisters(MOD1_BASE, 2, tempRegValue);
+  
+  /* Calculates the datarate */
+  cDivider = (uint8_t)SpiritRadioGetDigDiv(); 
+  
+  return (((s_lXtalFrequency>>(5+cDivider))*(256+tempRegValue[0]))>>(23-(tempRegValue[1]&0x0F)));
+}
+
+
+/**
+* @brief  Sets the frequency deviation.
+* @param  fFDev frequency deviation expressed in Hz. Be sure that this value
+*         is in the correct range [F_Xo*8/2^18, F_Xo*7680/2^18] Hz.
+* @retval None.
+*/
+void SpiritRadioSetFrequencyDev(uint32_t lFDev)
+{
+  uint8_t FDevM, FDevE, tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_F_DEV(lFDev, s_lXtalFrequency));
+  
+  /* Calculates the frequency deviation mantissa and exponent */
+  SpiritRadioSearchFreqDevME(lFDev, &FDevM, &FDevE);
+  
+  /* Reads the FDEV0 register */
+  SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue);
+  
+  /* Mask the other fields and set the frequency deviation mantissa and exponent */
+  tempRegValue &= 0x08;
+  tempRegValue |= ((FDevE<<4)|(FDevM));
+  
+  /* Writes the Frequency deviation register */
+  g_xStatus = SpiritSpiWriteRegisters(FDEV0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the frequency deviation.
+* @param  None.
+* @retval uint32_t Frequency deviation value expressed in Hz.
+*         This value will be in the range [F_Xo*8/2^18, F_Xo*7680/2^18] Hz.
+*/
+uint32_t SpiritRadioGetFrequencyDev(void)
+{
+  uint8_t tempRegValue, FDevM, FDevE;  
+
+  
+  /* Reads the frequency deviation register for mantissa and exponent */
+  g_xStatus = SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue);
+  FDevM = tempRegValue&0x07;
+  FDevE = (tempRegValue&0xF0)>>4;
+  
+  /* Calculates the frequency deviation and return it */
+  //return (((s_lXtalFrequency>>6)*(8+FDevM))>>(13-FDevE));
+  
+  return (uint32_t)((float)s_lXtalFrequency/(((uint32_t)1)<<18)*(uint32_t)((8.0+FDevM)/2*(1<<FDevE)));
+   
+}
+
+
+/**
+* @brief  Sets the channel filter bandwidth.
+* @param  lBandwidth channel filter bandwidth expressed in Hz. This parameter shall be in the range [1100 800100]
+*         Even if it is possible to pass as parameter any value in the above mentioned range,
+*         the API will search the most closer value according to a fixed table of channel
+*         bandwidth values (@ref s_vectnBandwidth), as defined in the datasheet. To verify the settled channel bandwidth
+*         it is possible to use the SpiritRadioGetChannelBW() API.
+* @retval None.
+*/
+void SpiritRadioSetChannelBW(uint32_t lBandwidth)
+{
+  uint8_t bwM, bwE, tempRegValue;
+  
+  /* Search in the channel filter bandwidth table the exponent value */
+  if(SpiritRadioGetDigDiv())
+  {
+    s_assert_param(IS_CH_BW(lBandwidth,(s_lXtalFrequency/2)));
+  }
+  else
+  {
+    s_assert_param(IS_CH_BW(lBandwidth,(s_lXtalFrequency)));
+  } 
+  
+  /* Calculates the channel bandwidth mantissa and exponent */
+  SpiritRadioSearchChannelBwME(lBandwidth, &bwM, &bwE);
+  tempRegValue = (bwM<<4)|(bwE);
+  
+  /* Writes the Channel filter register */
+  g_xStatus = SpiritSpiWriteRegisters(CHFLT_BASE, 1, &tempRegValue);
+  
+}
+
+/**
+* @brief  Returns the channel filter bandwidth.
+* @param  None.
+* @retval uint32_t Channel filter bandwidth expressed in Hz.
+*/
+uint32_t SpiritRadioGetChannelBW(void)
+{
+  uint8_t tempRegValue, bwM, bwE;
+  
+  /* Reads the channel filter register for mantissa and exponent */
+  g_xStatus = SpiritSpiReadRegisters(CHFLT_BASE, 1, &tempRegValue);
+  bwM = (tempRegValue&0xF0)>>4;
+  bwE = tempRegValue&0x0F;
+  
+  /* Reads the channel filter bandwidth from the look-up table and return it */
+  return (uint32_t)(100.0*s_vectnBandwidth26M[bwM+(bwE*9)]*s_lXtalFrequency/26e6);
+  
+}
+
+
+/**
+* @brief  Sets the modulation type.
+* @param  xModulation modulation to set.
+*         This parameter shall be of type @ref ModulationSelect .
+* @retval None.
+*/
+void SpiritRadioSetModulation(ModulationSelect xModulation)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_MODULATION_SELECTED(xModulation));
+  
+  /* Reads the modulation register */
+  SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue);
+  
+  /* Mask the other fields and set the modulation type */
+  tempRegValue &=0x8F;
+  tempRegValue |= xModulation;
+  
+  /* Writes the modulation register */
+  g_xStatus = SpiritSpiWriteRegisters(MOD0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the modulation type used.
+* @param  None.
+* @retval ModulationSelect Settled modulation type.
+*/
+ModulationSelect SpiritRadioGetModulation(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the modulation register MOD0*/
+  g_xStatus = SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue);
+  
+  /* Return the modulation type */
+  return (ModulationSelect)(tempRegValue&0x70);
+  
+}
+
+
+/**
+* @brief  Enables or Disables the Continuous Wave transmit mode.
+* @param  xNewState new state for power ramping.
+*         This parameter can be: S_ENABLE or S_DISABLE .
+* @retval None.
+*/
+void SpiritRadioCWTransmitMode(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the modulation register MOD0 and mask the CW field */
+  SpiritSpiReadRegisters(MOD0_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |=MOD0_CW;
+  }
+  else
+  {
+    tempRegValue &= (~MOD0_CW);
+  }
+  
+  /* Writes the new value in the MOD0 register */
+  g_xStatus = SpiritSpiWriteRegisters(MOD0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Sets the OOK Peak Decay.
+* @param  xOokDecay Peak decay control for OOK.
+*         This parameter shall be of type @ref OokPeakDecay .
+* @retval None.
+*/
+void SpiritRadioSetOokPeakDecay(OokPeakDecay xOokDecay)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_OOK_PEAK_DECAY(xOokDecay));
+  
+  /* Reads the RSSI_FLT register */
+  SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+  
+  /* Mask the other fields and set OOK Peak Decay */
+  tempRegValue &= 0xFC;
+  tempRegValue |= xOokDecay;
+  
+  /* Writes the RSSI_FLT register to set the new OOK peak dacay value */
+  g_xStatus = SpiritSpiWriteRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the OOK Peak Decay.
+* @param  None
+* @retval OokPeakDecay Ook peak decay value.
+*/
+OokPeakDecay SpiritRadioGetOokPeakDecay(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the OOK peak decay register RSSI_FLT_BASE*/
+  g_xStatus = SpiritSpiReadRegisters(RSSI_FLT_BASE, 1, &tempRegValue);
+  
+  /* Returns the OOK peak decay */
+  return (OokPeakDecay) (tempRegValue & 0x03);
+  
+}
+
+/**
+* @brief  Returns the PA register value that corresponds to the passed dBm power.
+* @param  lFbase Frequency base expressed in Hz.
+* @param  fPowerdBm Desired power in dBm.
+* @retval Register value as byte.
+* @note The power interpolation curves used by this function have been extracted
+*       by measurements done on the divisional evaluation boards.
+*/
+uint8_t SpiritRadioGetdBm2Reg(uint32_t lFBase, float fPowerdBm)
+{
+  uint8_t i=0;
+  uint8_t j=0;
+  float fReg;
+  
+  if(IS_FREQUENCY_BAND_HIGH(lFBase))
+  {
+    i=0;
+    if(lFBase<900000000) i=1;// 868   
+  }
+  else if(IS_FREQUENCY_BAND_MIDDLE(lFBase))
+  {
+    i=2;
+  }
+  else if(IS_FREQUENCY_BAND_LOW(lFBase))
+  {
+    i=3;
+  }
+  else if(IS_FREQUENCY_BAND_VERY_LOW(lFBase))
+  {
+    i=4;
+  }
+  
+  j=1;
+  if(fPowerdBm>0 && 13.0/fPowerFactors[i][2]-fPowerFactors[i][3]/fPowerFactors[i][2]<fPowerdBm)
+      j=0;
+  else if(fPowerdBm<=0 && 40.0/fPowerFactors[i][2]-fPowerFactors[i][3]/fPowerFactors[i][2]>fPowerdBm)
+      j=2;
+
+  fReg=fPowerFactors[i][2*j]*fPowerdBm+fPowerFactors[i][2*j+1];
+  
+  if(fReg<1)
+    fReg=1;
+  else if(fReg>90) 
+    fReg=90;
+  
+  return ((uint8_t)fReg);
+}
+
+
+/**
+* @brief  Returns the dBm power that corresponds to the value of PA register.
+* @param  lFbase Frequency base expressed in Hz.
+* @param  cPowerReg Register value of the PA.
+* @retval Power in dBm as float.
+* @note The power interpolation curves used by this function have been extracted
+*       by measurements done on the divisional evaluation boards.
+*/
+float SpiritRadioGetReg2dBm(uint32_t lFBase, uint8_t cPowerReg)
+{
+  uint8_t i=0;
+  uint8_t j=0;
+  float fPower;
+  
+  if(cPowerReg==0 || cPowerReg>90)
+    return (-130.0);
+  
+  if(IS_FREQUENCY_BAND_HIGH(lFBase))
+  {
+    i=0;
+    if(lFBase<900000000) i=1;// 868   
+  }
+  else if(IS_FREQUENCY_BAND_MIDDLE(lFBase))
+  {
+    i=2;
+  }
+  else if(IS_FREQUENCY_BAND_LOW(lFBase))
+  {
+    i=3;
+  }
+  else if(IS_FREQUENCY_BAND_VERY_LOW(lFBase))
+  {
+    i=4;
+  }
+  
+  j=1;
+  if(cPowerReg<13) j=0;
+  else if(cPowerReg>40) j=2;
+  
+  fPower=(((float)cPowerReg)/fPowerFactors[i][2*j]-fPowerFactors[i][2*j+1]/fPowerFactors[i][2*j]);
+  
+  return fPower;
+}
+
+/**
+* @brief  Configures the Power Amplifier Table and registers with value expressed in dBm.
+* @param  cPALevelMaxIndex number of levels to set. This parameter shall be in the range [0:7].
+* @param  cWidth step width expressed in terms of bit period units Tb/8.
+*         This parameter shall be in the range [1:4].
+* @param  xCLoad one of the possible value of the enum type PALoadCapacitor.
+*         @arg LOAD_0_PF    No additional PA load capacitor
+*         @arg LOAD_1_2_PF  1.2pF additional PA load capacitor
+*         @arg LOAD_2_4_PF  2.4pF additional PA load capacitor
+*         @arg LOAD_3_6_PF  3.6pF additional PA load capacitor
+* @param  pfPAtabledBm pointer to an array of PA values in dbm between [-PA_LOWER_LIMIT: PA_UPPER_LIMIT] dbm.
+*         The first element shall be the lower level (PA_LEVEL[0]) value and the last element
+*         the higher level one (PA_LEVEL[paLevelMaxIndex]).
+* @retval None.
+*/
+void SpiritRadioSetPATabledBm(uint8_t cPALevelMaxIndex, uint8_t cWidth, PALoadCapacitor xCLoad, float* pfPAtabledBm)
+{
+  uint8_t palevel[9], address, paLevelValue;
+  uint32_t lFBase=SpiritRadioGetFrequencyBase();
+
+  /* Check the parameters */
+  s_assert_param(IS_PA_MAX_INDEX(cPALevelMaxIndex));
+  s_assert_param(IS_PA_STEP_WIDTH(cWidth));
+  s_assert_param(IS_PA_LOAD_CAP(xCLoad));
+  
+  /* Check the PA level in dBm is in the range and calculate the PA_LEVEL value
+  to write in the corresponding register using the linearization formula */
+  for(int i=0; i<=cPALevelMaxIndex; i++)
+  {
+    s_assert_param(IS_PAPOWER_DBM(*pfPAtabledBm));
+    paLevelValue=SpiritRadioGetdBm2Reg(lFBase,(*pfPAtabledBm));
+    palevel[cPALevelMaxIndex-i]=paLevelValue;
+    pfPAtabledBm++;
+  }
+  
+  /* Sets the PA_POWER[0] register */
+  palevel[cPALevelMaxIndex+1]=xCLoad|(cWidth-1)<<3|cPALevelMaxIndex;
+  
+  /* Sets the base address */
+  address=PA_POWER8_BASE+7-cPALevelMaxIndex;
+  
+  /* Configures the PA_POWER registers */
+  g_xStatus = SpiritSpiWriteRegisters(address, cPALevelMaxIndex+2, palevel);
+  
+}
+
+
+/**
+* @brief  Returns the Power Amplifier Table and registers, returning values in dBm.
+* @param  pcPALevelMaxIndex pointer to the number of levels settled.
+*         This parameter will be in the range [0:7].
+* @param  pfPAtabledBm pointer to an array of 8 elements containing the PA value in dbm.
+*         The first element will be the PA_LEVEL_0 and the last element
+*         will be PA_LEVEL_7. Any value higher than PA_UPPER_LIMIT implies no output
+*         power (output stage is in high impedance).
+* @retval None.
+*/
+void SpiritRadioGetPATabledBm(uint8_t* pcPALevelMaxIndex, float* pfPAtabledBm)
+{
+  uint8_t palevelvect[9];
+  uint32_t lFBase=SpiritRadioGetFrequencyBase();
+  
+  /* Reads the PA_LEVEL_x registers and the PA_POWER_0 register */
+  g_xStatus = SpiritSpiReadRegisters(PA_POWER8_BASE, 9, palevelvect);
+  
+  /* Fill the PAtable */
+  for(int i=7; i>=0; i--)
+  {
+    (*pfPAtabledBm)=SpiritRadioGetReg2dBm(lFBase,palevelvect[i]);
+    pfPAtabledBm++;
+  }
+  
+  /* Return the settled index */
+  *pcPALevelMaxIndex = palevelvect[8]&0x07;
+  
+}
+
+
+
+
+
+
+/**
+* @brief  Sets a specific PA_LEVEL register, with a value given in dBm.
+* @param  cIndex PA_LEVEL to set. This parameter shall be in the range [0:7].
+* @param  fPowerdBm PA value to write expressed in dBm . Be sure that this values is in the
+*         correct range [-PA_LOWER_LIMIT: PA_UPPER_LIMIT] dBm.
+* @retval None.
+* @note This function makes use of the @ref SpiritRadioGetdBm2Reg fcn to interpolate the 
+*       power value.
+*/
+void SpiritRadioSetPALeveldBm(uint8_t cIndex, float fPowerdBm)
+{
+  uint8_t address, paLevelValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_PA_MAX_INDEX(cIndex));
+  s_assert_param(IS_PAPOWER_DBM(fPowerdBm));
+  
+  /* interpolate the power level */
+  paLevelValue=SpiritRadioGetdBm2Reg(SpiritRadioGetFrequencyBase(),fPowerdBm);
+
+  /* Sets the base address */
+  address=PA_POWER8_BASE+7-cIndex;
+  
+  /* Configures the PA_LEVEL register */
+  g_xStatus = SpiritSpiWriteRegisters(address, 1, &paLevelValue);
+  
+}
+
+
+/**
+* @brief  Returns a specific PA_LEVEL register, returning a value in dBm.
+* @param  cIndex PA_LEVEL to read. This parameter shall be in the range [0:7]
+* @retval float Settled power level expressed in dBm. A value
+*         higher than PA_UPPER_LIMIT dBm implies no output power
+*         (output stage is in high impedance).
+* @note This function makes use of the @ref SpiritRadioGetReg2dBm fcn to interpolate the 
+*       power value.
+*/
+float SpiritRadioGetPALeveldBm(uint8_t cIndex)
+{
+  uint8_t address, paLevelValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_PA_MAX_INDEX(cIndex));
+  
+  /* Sets the base address */
+  address=PA_POWER8_BASE+7-cIndex;
+  
+  /* Reads the PA_LEVEL[cIndex] register */
+  g_xStatus = SpiritSpiReadRegisters(address, 1, &paLevelValue);
+  
+  return SpiritRadioGetReg2dBm(SpiritRadioGetFrequencyBase(),paLevelValue);
+}
+
+
+/**
+* @brief  Configures the Power Amplifier Table and registers.
+* @param  cPALevelMaxIndex number of levels to set. This parameter shall be in the range [0:7].
+* @param  cWidth step width expressed in terms of bit period units Tb/8.
+*         This parameter shall be in the range [1:4].
+* @param  xCLoad one of the possible value of the enum type PALoadCapacitor.
+*         @arg LOAD_0_PF    No additional PA load capacitor
+*         @arg LOAD_1_2_PF  1.2pF additional PA load capacitor
+*         @arg LOAD_2_4_PF  2.4pF additional PA load capacitor
+*         @arg LOAD_3_6_PF  3.6pF additional PA load capacitor
+* @param  pcPAtable pointer to an array of PA values in the range [0: 90], where 0 implies no
+*         output power, 1 will be the maximum level and 90 the minimum one
+*         The first element shall be the lower level (PA_LEVEL[0]) value and the last element
+*         the higher level one (PA_LEVEL[paLevelMaxIndex]).
+* @retval None.
+*/
+void SpiritRadioSetPATable(uint8_t cPALevelMaxIndex, uint8_t cWidth, PALoadCapacitor xCLoad, uint8_t* pcPAtable)
+{
+  uint8_t palevel[9], address;
+  
+  /* Check the parameters */
+  s_assert_param(IS_PA_MAX_INDEX(cPALevelMaxIndex));
+  s_assert_param(IS_PA_STEP_WIDTH(cWidth));
+  s_assert_param(IS_PA_LOAD_CAP(xCLoad));
+  
+  /* Check the PA levels are in the range */
+  for(int i=0; i<=cPALevelMaxIndex; i++)
+  {
+    s_assert_param(IS_PAPOWER(*pcPAtable));
+    palevel[cPALevelMaxIndex-i]=*pcPAtable;
+    pcPAtable++;
+  }
+  
+  /* Sets the PA_POWER[0] register */
+  palevel[cPALevelMaxIndex+1]=xCLoad|((cWidth-1)<<3)|cPALevelMaxIndex;
+  
+  /* Sets the base address */
+  address=PA_POWER8_BASE+7-cPALevelMaxIndex;
+  
+  /* Configures the PA_POWER registers */
+  g_xStatus = SpiritSpiWriteRegisters(address, cPALevelMaxIndex+2, palevel);
+  
+}
+
+
+/**
+* @brief  Returns the Power Amplifier Table and registers.
+* @param  pcPALevelMaxIndex pointer to the number of levels settled.
+*         This parameter shall be in the range [0:7].
+* @param  pcPAtable pointer to an array of 8 elements containing the PA value.
+*         The first element will be the PA_LEVEL_0 and the last element
+*         will be PA_LEVEL_7. Any value equals to 0 implies that level has
+*         no output power (output stage is in high impedance).
+* @retval None
+*/
+void SpiritRadioGetPATable(uint8_t* pcPALevelMaxIndex, uint8_t* pcPAtable)
+{
+  uint8_t palevelvect[9];
+  
+  /* Reads the PA_LEVEL_x registers and the PA_POWER_0 register */
+  g_xStatus = SpiritSpiReadRegisters(PA_POWER8_BASE, 9, palevelvect);
+  
+  /* Fill the PAtable */
+  for(int i=7; i>=0; i--)
+  {
+    *pcPAtable = palevelvect[i];
+    pcPAtable++;
+  }
+  
+  /* Return the settled index */
+  *pcPALevelMaxIndex = palevelvect[8]&0x07;
+  
+}
+
+
+/**
+* @brief  Sets a specific PA_LEVEL register.
+* @param  cIndex PA_LEVEL to set. This parameter shall be in the range [0:7].
+* @param  cPower PA value to write in the register. Be sure that this values is in the
+*         correct range [0 : 90].
+* @retval None.
+*/
+void SpiritRadioSetPALevel(uint8_t cIndex, uint8_t cPower)
+{
+  uint8_t address;
+  
+  /* Check the parameters */
+  s_assert_param(IS_PA_MAX_INDEX(cIndex));
+  s_assert_param(IS_PAPOWER(cPower));
+  
+  /* Sets the base address */
+  address=PA_POWER8_BASE+7-cIndex;
+  
+  /* Configures the PA_LEVEL register */
+  g_xStatus = SpiritSpiWriteRegisters(address, 1, &cPower);
+  
+}
+
+
+/**
+* @brief  Returns a specific PA_LEVEL register.
+* @param  cIndex PA_LEVEL to read. This parameter shall be in the range [0:7].
+* @retval uint8_t PA_LEVEL value. A value equal to zero
+*         implies no output power (output stage is in high impedance).
+*/
+uint8_t SpiritRadioGetPALevel(uint8_t cIndex)
+{
+  uint8_t address, tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_PA_MAX_INDEX(cIndex));
+  
+  /* Sets the base address */
+  address=PA_POWER8_BASE+7-cIndex;
+  
+  /* Reads the PA_LEVEL[cIndex] register and return the value */
+  g_xStatus = SpiritSpiReadRegisters(address, 1, &tempRegValue);
+  return tempRegValue;
+  
+}
+
+
+/**
+* @brief  Sets the output stage additional load capacitor bank.
+* @param  xCLoad one of the possible value of the enum type PALoadCapacitor.
+*         @arg LOAD_0_PF    No additional PA load capacitor
+*         @arg LOAD_1_2_PF  1.2pF additional PA load capacitor
+*         @arg LOAD_2_4_PF  2.4pF additional PA load capacitor
+*         @arg LOAD_3_6_PF  3.6pF additional PA load capacitor
+* @retval None.
+*/
+void SpiritRadioSetPACwc(PALoadCapacitor xCLoad)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_PA_LOAD_CAP(xCLoad));
+  
+  /* Reads the PA_POWER_0 register */
+  SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+  /* Mask the CWC[1:0] field and write the new value */
+  tempRegValue &= 0x3F;
+  tempRegValue |= xCLoad;
+  
+  /* Configures the PA_POWER_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the output stage additional load capacitor bank.
+* @param  None.
+* @retval PALoadCapacitor Output stage additional load capacitor bank.
+*         This parameter can be:
+*         @arg LOAD_0_PF    No additional PA load capacitor
+*         @arg LOAD_1_2_PF  1.2pF additional PA load capacitor
+*         @arg LOAD_2_4_PF  2.4pF additional PA load capacitor
+*         @arg LOAD_3_6_PF  3.6pF additional PA load capacitor
+*/
+PALoadCapacitor SpiritRadioGetPACwc(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the PA_POWER_0 register */
+  g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+  /* Mask the CWC[1:0] field and return the value*/
+  return (PALoadCapacitor)(tempRegValue & 0xC0);
+  
+}
+
+
+/**
+* @brief  Sets a specific PA_LEVEL_MAX_INDEX.
+* @param  cIndex PA_LEVEL_MAX_INDEX to set. This parameter shall be in the range [0:7].
+* @retval None
+*/
+void SpiritRadioSetPALevelMaxIndex(uint8_t cIndex)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_PA_MAX_INDEX(cIndex));
+  
+  /* Reads the PA_POWER_0 register */
+  SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+  /* Mask the PA_LEVEL_MAX_INDEX[1:0] field and write the new value */
+  tempRegValue &= 0xF8;
+  tempRegValue |= cIndex;
+  
+  /* Configures the PA_POWER_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the actual PA_LEVEL_MAX_INDEX.
+* @param  None.
+* @retval uint8_t Actual PA_LEVEL_MAX_INDEX. This parameter will be in the range [0:7].
+*/
+uint8_t SpiritRadioGetPALevelMaxIndex(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the PA_POWER_0 register */
+  g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+  /* Mask the PA_LEVEL_MAX_INDEX[1:0] field and return the value */
+  return (tempRegValue & 0x07);
+  
+}
+
+
+/**
+* @brief  Sets a specific PA_RAMP_STEP_WIDTH.
+* @param  cWidth step width expressed in terms of bit period units Tb/8.
+*         This parameter shall be in the range [1:4].
+* @retval None.
+*/
+void SpiritRadioSetPAStepWidth(uint8_t cWidth)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_PA_STEP_WIDTH(cWidth));
+  
+  /* Reads the PA_POWER_0 register */
+  SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+  /* Mask the PA_RAMP_STEP_WIDTH[1:0] field and write the new value */
+  tempRegValue &= 0xE7;
+  tempRegValue |= (cWidth-1)<<3;
+  
+  /* Configures the PA_POWER_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the actual PA_RAMP_STEP_WIDTH.
+* @param  None.
+* @retval uint8_t Step width value expressed in terms of bit period units Tb/8.
+*         This parameter will be in the range [1:4].
+*/
+uint8_t SpiritRadioGetPAStepWidth(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the PA_POWER_0 register */
+  g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+  /* Mask the PA_RAMP_STEP_WIDTH[1:0] field and return the value */
+  tempRegValue &= 0x18;
+  return  ((tempRegValue>>3)+1);
+  
+}
+
+
+/**
+* @brief  Enables or Disables the Power Ramping.
+* @param  xNewState new state for power ramping.
+*         This parameter can be: S_ENABLE or S_DISABLE.
+* @retval None.
+*/
+void SpiritRadioPARamping(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the PA_POWER_0 register and configure the PA_RAMP_ENABLE field */
+  SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PA_POWER0_PA_RAMP_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~PA_POWER0_PA_RAMP_MASK);
+  }
+  
+  /* Sets the PA_POWER_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+}
+
+/**
+* @brief  Returns the Power Ramping enable bit.
+* @param  xNewState new state for power ramping.
+*         This parameter can be: S_ENABLE or S_DISABLE.
+* @retval None.
+*/
+SpiritFunctionalState SpiritRadioGetPARamping(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the PA_POWER_0 register and configure the PA_RAMP_ENABLE field */
+  g_xStatus = SpiritSpiReadRegisters(PA_POWER0_BASE, 1, &tempRegValue);
+  
+  /* Mask and return data */
+  return (SpiritFunctionalState)((tempRegValue>>5) & 0x01);
+  
+}
+
+
+/**
+* @brief  Enables or Disables the AFC.
+* @param  xNewState new state for AFC.
+*         This parameter can be: S_ENABLE or S_DISABLE.
+* @retval None.
+*/
+void SpiritRadioAFC(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the AFC_2 register and configure the AFC Enabled field */
+  SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= AFC2_AFC_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~AFC2_AFC_MASK);
+  }
+  
+  /* Sets the AFC_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Enables or Disables the AFC freeze on sync word detection.
+* @param  xNewState new state for AFC freeze on sync word detection.
+*         This parameter can be: S_ENABLE or S_DISABLE.
+* @retval None.
+*/
+void SpiritRadioAFCFreezeOnSync(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the AFC_2 register and configure the AFC Freeze on Sync field */
+  SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= AFC2_AFC_FREEZE_ON_SYNC_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~AFC2_AFC_FREEZE_ON_SYNC_MASK);
+  }
+  
+  /* Sets the AFC_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Sets the AFC working mode.
+* @param  xMode the AFC mode. This parameter can be one of the values defined in @ref AFCMode :
+*         @arg AFC_SLICER_CORRECTION     AFC loop closed on slicer
+*         @arg AFC_2ND_IF_CORRECTION     AFC loop closed on 2nd conversion stage
+* @retval None.
+*/
+void SpiritRadioSetAFCMode(AFCMode xMode)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_AFC_MODE(xMode));
+  
+  /* Reads the AFC_2 register and configure the AFC Mode field */
+  SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue);
+  if(xMode == AFC_2ND_IF_CORRECTION)
+  {
+    tempRegValue |= AFC_2ND_IF_CORRECTION;
+  }
+  else
+  {
+    tempRegValue &= (~AFC_2ND_IF_CORRECTION);
+  }
+  
+  /* Sets the AFC_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AFC working mode.
+* @param  None.
+* @retval AFCMode Settled AFC mode. This parameter will be one of the values defined in @ref AFCMode :
+*         @arg AFC_SLICER_CORRECTION     AFC loop closed on slicer
+*         @arg AFC_2ND_IF_CORRECTION     AFC loop closed on 2nd conversion stage
+*/
+AFCMode SpiritRadioGetAFCMode(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AFC_2 register */
+  g_xStatus = SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue);
+  
+  /* Mask the AFC Mode field and returns the value */
+  return (AFCMode)(tempRegValue & 0x20);
+  
+}
+
+
+/**
+* @brief  Sets the AFC peak detector leakage.
+* @param  cLeakage the peak detector leakage. This parameter shall be in the range:
+*         [0:31].
+* @retval None.
+*/
+void SpiritRadioSetAFCPDLeakage(uint8_t cLeakage)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_AFC_PD_LEAKAGE(cLeakage));
+  
+  /* Reads the AFC_2 register and configure the AFC PD leakage field */
+  SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue);
+  tempRegValue &= 0xE0;
+  tempRegValue |= cLeakage;
+  
+  /* Sets the AFC_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AFC2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AFC peak detector leakage.
+* @param  None.
+* @retval uint8_t Peak detector leakage value. This parameter will be in the range:
+*         [0:31].
+*/
+uint8_t SpiritRadioGetAFCPDLeakage(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AFC_2 register */
+  g_xStatus = SpiritSpiReadRegisters(AFC2_BASE, 1, &tempRegValue);
+  
+  /* Mask the AFC PD leakage field and return the value */
+  return (tempRegValue & 0x1F);
+  
+}
+
+
+/**
+* @brief  Sets the length of the AFC fast period expressed as number of samples.
+* @param  cLength length of the fast period in number of samples.
+* @retval None.
+*/
+void SpiritRadioSetAFCFastPeriod(uint8_t cLength)
+{
+  /* Sets the AFC_1 register */
+  g_xStatus = SpiritSpiWriteRegisters(AFC1_BASE, 1, &cLength);
+  
+}
+
+
+/**
+* @brief  Returns the AFC fast period expressed as number of samples.
+* @param  None.
+* @retval uint8_t Length of the fast period in number of samples.
+*/
+uint8_t SpiritRadioGetAFCFastPeriod(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AFC 1 register and return the value */
+  g_xStatus = SpiritSpiReadRegisters(AFC1_BASE, 1, &tempRegValue);
+  
+  return tempRegValue;
+  
+}
+
+
+/**
+* @brief  Sets the AFC loop gain in fast mode.
+* @param  cGain AFC loop gain in fast mode. This parameter shall be in the range:
+*         [0:15].
+* @retval None.
+*/
+void SpiritRadioSetAFCFastGain(uint8_t cGain)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_AFC_FAST_GAIN(cGain));
+  
+  /* Reads the AFC_0 register and configure the AFC Fast Gain field */
+  SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue);
+  tempRegValue &= 0x0F;
+  tempRegValue |= cGain<<4;
+  
+  /* Sets the AFC_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(AFC0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AFC loop gain in fast mode.
+* @param  None.
+* @retval uint8_t AFC loop gain in fast mode. This parameter will be in the range:
+*         [0:15].
+*/
+uint8_t SpiritRadioGetAFCFastGain(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AFC_0 register, mask the AFC Fast Gain field and return the value  */
+  g_xStatus = SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue);
+  
+  return ((tempRegValue & 0xF0)>>4);
+  
+}
+
+
+/**
+* @brief  Sets the AFC loop gain in slow mode.
+* @param  cGain AFC loop gain in slow mode. This parameter shall be in the range:
+*         [0:15].
+* @retval None.
+*/
+void SpiritRadioSetAFCSlowGain(uint8_t cGain)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_AFC_SLOW_GAIN(cGain));
+  
+  /* Reads the AFC_0 register and configure the AFC Slow Gain field */
+  SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue);
+  tempRegValue &= 0xF0;
+  tempRegValue |= cGain;
+  
+  /* Sets the AFC_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(AFC0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AFC loop gain in slow mode.
+* @param  None.
+* @retval uint8_t AFC loop gain in slow mode. This parameter will be in the range:
+*         [0:15].
+*/
+uint8_t SpiritRadioGetAFCSlowGain(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AFC_0 register, mask the AFC Slow Gain field and return the value */
+  g_xStatus = SpiritSpiReadRegisters(AFC0_BASE, 1, &tempRegValue);
+  
+  return (tempRegValue & 0x0F);
+  
+}
+
+
+/**
+* @brief  Returns the AFC correction from the corresponding register.
+* @param  None.
+* @retval int8_t AFC correction, read from the corresponding register.
+*         This parameter will be in the range [-128:127].
+*/
+int8_t SpiritRadioGetAFCCorrectionReg(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AFC_CORR register, cast the read value as signed char and return it */
+  g_xStatus = SpiritSpiReadRegisters(AFC_CORR_BASE, 1, &tempRegValue);
+  
+  return (int8_t)tempRegValue;
+  
+}
+
+
+/**
+* @brief  Returns the AFC correction expressed in Hz.
+* @param  None.
+* @retval int32_t AFC correction expressed in Hz
+*         according to the following formula:<ul>
+*         <li> Fafc[Hz]= (Fdig/(12*2^10))*AFC_CORR  where </li>
+*         <li> AFC_CORR is the value read in the AFC_CORR register </li> </ul>
+*/
+int32_t SpiritRadioGetAFCCorrectionHz(void)
+{
+  int8_t correction;
+  uint32_t xtal = s_lXtalFrequency;
+  
+  /* Reads the AFC correction register */
+  correction = SpiritRadioGetAFCCorrectionReg();
+  
+  if(xtal>DOUBLE_XTAL_THR)
+  {
+    xtal /= 2;
+  }
+  
+  /* Calculates and return the Frequency Correction */
+  return (int32_t)(xtal/(12*pow(2,10))*correction);
+  
+}
+
+
+/**
+* @brief  Enables or Disables the AGC.
+* @param  xNewState new state for AGC.
+*         This parameter can be: S_ENABLE or S_DISABLE
+* @retval None.
+*/
+void SpiritRadioAGC(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the AGCCTRL_0 register and configure the AGC Enabled field */
+  SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= AGCCTRL0_AGC_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~AGCCTRL0_AGC_MASK);
+  }
+  
+  /* Sets the AGCCTRL_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Sets the AGC working mode.
+* @param  xMode the AGC mode. This parameter can be one of the values defined in @ref AGCMode :
+*         @arg AGC_LINEAR_MODE     AGC works in linear mode
+*         @arg AGC_BINARY_MODE     AGC works in binary mode
+* @retval None.
+*/
+void SpiritRadioSetAGCMode(AGCMode xMode)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_AGC_MODE(xMode));
+  
+  /* Reads the AGCCTRL_0 register and configure the AGC Mode field */
+  SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  if(xMode == AGC_BINARY_MODE)
+  {
+    tempRegValue |= AGC_BINARY_MODE;
+  }
+  else
+  {
+    tempRegValue &= (~AGC_BINARY_MODE);
+  }
+  
+  /* Sets the AGCCTRL_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AGC working mode.
+* @param  None.
+* @retval AGCMode Settled AGC mode.  This parameter can be one of the values defined in @ref AGCMode :
+*         @arg AGC_LINEAR_MODE     AGC works in linear mode
+*         @arg AGC_BINARY_MODE     AGC works in binary mode
+*/
+AGCMode SpiritRadioGetAGCMode(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AGCCTRL_0 register, mask the AGC Mode field and return the value */
+  g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+  return  (AGCMode)(tempRegValue & 0x40);
+  
+}
+
+
+/**
+* @brief  Enables or Disables the AGC freeze on steady state.
+* @param  xNewState new state for AGC freeze on steady state.
+*         This parameter can be: S_ENABLE or S_DISABLE.
+* @retval None.
+*/
+void SpiritRadioAGCFreezeOnSteady(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the AGCCTRL_2 register and configure the AGC Freeze On Steady field */
+  SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= AGCCTRL2_FREEZE_ON_STEADY_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~AGCCTRL2_FREEZE_ON_STEADY_MASK);
+  }
+  
+  /* Sets the AGCCTRL_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Enable or Disable the AGC freeze on sync detection.
+* @param  xNewState new state for AGC freeze on sync detection.
+*         This parameter can be: S_ENABLE or S_DISABLE.
+* @retval None.
+*/
+void SpiritRadioAGCFreezeOnSync(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the AGCCTRL_2 register and configure the AGC Freeze On Sync field */
+  SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= AGCCTRL2_FREEZE_ON_SYNC_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~AGCCTRL2_FREEZE_ON_SYNC_MASK);
+  }
+  
+  /* Sets the AGCCTRL_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Enable or Disable the AGC to start with max attenuation.
+* @param  xNewState new state for AGC start with max attenuation mode.
+*         This parameter can be: S_ENABLE or S_DISABLE.
+* @retval None.
+*/
+void SpiritRadioAGCStartMaxAttenuation(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue = 0x00;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the AGCCTRL_2 register and configure the AGC Start Max Attenuation field */
+  SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= AGCCTRL2_START_MAX_ATTENUATION_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~AGCCTRL2_START_MAX_ATTENUATION_MASK);
+  }
+  
+  /* Sets the AGCCTRL_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Sets the AGC measure time.
+* @param  nTime AGC measure time expressed in us. This parameter shall be in the range [0, 393216/F_Xo].
+* @retval None.
+*/
+void SpiritRadioSetAGCMeasureTimeUs(uint16_t nTime)
+{
+  uint8_t tempRegValue, measure;
+  
+  /* Check the parameter */
+  s_assert_param(IS_AGC_MEASURE_TIME_US(nTime,s_lXtalFrequency));
+  
+  /* Reads the AGCCTRL_2 register */
+  SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  
+  /* Calculates the measure time value to write in the register */
+  measure = (uint8_t)lroundf(log2((float)nTime/1e6 * s_lXtalFrequency/12));
+  (measure>15) ? (measure=15):(measure);
+  
+  /* Mask the MEAS_TIME field and write the new value */
+  tempRegValue &= 0xF0;
+  tempRegValue |= measure;
+  
+  /* Sets the AGCCTRL_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AGC measure time.
+* @param  None.
+* @retval uint16_t AGC measure time expressed in us. This parameter will be in the range [0, 393216/F_Xo].
+*/
+uint16_t SpiritRadioGetAGCMeasureTimeUs(void)
+{
+  uint8_t measure;
+  
+  /* Reads the AGCCTRL_2 register */
+  g_xStatus = SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &measure);
+  
+  /* Mask the MEAS_TIME field */
+  measure &= 0x0F;
+  
+  /* Calculates the measure time value to write in the register */
+  return (uint16_t)((12.0/s_lXtalFrequency)*(float)pow(2,measure)*1e6);
+  
+}
+
+
+/**
+* @brief  Sets the AGC measure time.
+* @param  cTime AGC measure time to write in the MEAS_TIME field of AGCCTRL_2 register.
+*         This parameter shall be in the range [0:15].
+* @retval None.
+*/
+void SpiritRadioSetAGCMeasureTime(uint8_t cTime)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_AGC_MEASURE_TIME(cTime));
+  
+  /* Reads the AGCCTRL_2 register */
+  SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  
+  /* Mask the MEAS_TIME field and write the new value */
+  tempRegValue &= 0xF0;
+  tempRegValue |= cTime;
+  
+  /* Sets the AGCCTRL_2 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AGC measure time.
+* @param  None.
+* @retval uint8_t AGC measure time read from the MEAS_TIME field of AGCCTRL_2 register.
+*         This parameter will be in the range [0:15].
+*/
+uint8_t SpiritRadioGetAGCMeasureTime(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AGCCTRL_2 register, mask the MEAS_TIME field and return the value  */
+  g_xStatus = SpiritSpiReadRegisters(AGCCTRL2_BASE, 1, &tempRegValue);
+  
+  return (tempRegValue & 0x0F);
+  
+}
+
+
+/**
+* @brief  Sets the AGC hold time.
+* @param  cTime AGC hold time expressed in us. This parameter shall be in the range[0, 756/F_Xo].
+* @retval None.
+*/
+void SpiritRadioSetAGCHoldTimeUs(uint8_t cTime)
+{
+  uint8_t tempRegValue, hold;
+  
+  /* Check the parameter */
+  s_assert_param(IS_AGC_HOLD_TIME_US(cTime,s_lXtalFrequency));
+  
+  /* Reads the AGCCTRL_0 register */
+  SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+  /* Calculates the hold time value to write in the register */
+  hold = (uint8_t)lroundf(((float)cTime/1e6 * s_lXtalFrequency)/12);
+  (hold>63) ? (hold=63):(hold);
+  
+  /* Mask the HOLD_TIME field and write the new value */
+  tempRegValue &= 0xC0;
+  tempRegValue |= hold;
+  
+  /* Sets the AGCCTRL_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AGC hold time.
+* @param  None.
+* @retval uint8_t AGC hold time expressed in us. This parameter will be in the range:
+*         [0, 756/F_Xo].
+*/
+uint8_t SpiritRadioGetAGCHoldTimeUs(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AGCCTRL_0 register */
+  g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+  /* Mask the HOLD_TIME field */
+  tempRegValue &= 0x3F;
+  
+  /* Calculates the hold time value and return it */
+  return (uint8_t)lroundf ((12.0/s_lXtalFrequency)*(tempRegValue*1e6));
+  
+}
+
+
+/**
+* @brief  Sets the AGC hold time.
+* @param  cTime AGC hold time to write in the HOLD_TIME field of AGCCTRL_0 register.
+*         This parameter shall be in the range [0:63].
+* @retval None.
+*/
+void SpiritRadioSetAGCHoldTime(uint8_t cTime)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_AGC_HOLD_TIME(cTime));
+  
+  /* Reads the AGCCTRL_0 register */
+  SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+  /* Mask the HOLD_TIME field and write the new value */
+  tempRegValue &= 0xC0;
+  tempRegValue |= cTime;
+  
+  /* Sets the AGCCTRL_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AGC hold time.
+* @param  None.
+* @retval uint8_t AGC hold time read from the HOLD_TIME field of AGCCTRL_0 register.
+*         This parameter will be in the range [0:63].
+*/
+uint8_t SpiritRadioGetAGCHoldTime(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AGCCTRL_0 register, mask the MEAS_TIME field and return the value  */
+  g_xStatus = SpiritSpiReadRegisters(AGCCTRL0_BASE, 1, &tempRegValue);
+  
+  return (tempRegValue & 0x3F);
+  
+}
+
+
+/**
+* @brief  Sets the AGC high threshold.
+* @param  cHighThreshold AGC high threshold to write in the THRESHOLD_HIGH field of AGCCTRL_1 register.
+*         This parameter shall be in the range [0:15].
+* @retval None.
+*/
+void SpiritRadioSetAGCHighThreshold(uint8_t cHighThreshold)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_AGC_THRESHOLD(cHighThreshold));
+  
+  /* Reads the AGCCTRL_1 register */
+  SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue);
+  
+  /* Mask the THRESHOLD_HIGH field and write the new value */
+  tempRegValue &= 0x0F;
+  tempRegValue |= cHighThreshold<<4;
+  
+  /* Sets the AGCCTRL_1 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL1_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AGC high threshold.
+* @param  None.
+* @retval uint8_t AGC high threshold read from the THRESHOLD_HIGH field of AGCCTRL_1 register.
+*         This parameter will be in the range [0:15].
+*/
+uint8_t SpiritRadioGetAGCHighThreshold(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AGCCTRL_1 register, mask the THRESHOLD_HIGH field and return the value */
+  g_xStatus = SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue);
+  
+  return ((tempRegValue & 0xF0)>>4);
+  
+}
+
+
+/**
+* @brief  Sets the AGC low threshold.
+* @param  cLowThreshold AGC low threshold to write in the THRESHOLD_LOW field of AGCCTRL_1 register.
+*         This parameter shall be in the range [0:15].
+* @retval None.
+*/
+void SpiritRadioSetAGCLowThreshold(uint8_t cLowThreshold)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_AGC_THRESHOLD(cLowThreshold));
+  
+  /* Reads the AGCCTRL_1 register */
+  SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue);
+  
+  /* Mask the THRESHOLD_LOW field and write the new value */
+  tempRegValue &= 0xF0;
+  tempRegValue |= cLowThreshold;
+  
+  /* Sets the AGCCTRL_1 register */
+  g_xStatus = SpiritSpiWriteRegisters(AGCCTRL1_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the AGC low threshold.
+* @param  None.
+* @retval uint8_t AGC low threshold read from the THRESHOLD_LOW field of AGCCTRL_1 register.
+*         This parameter will be in the range [0:15].
+*/
+uint8_t SpiritRadioGetAGCLowThreshold(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the AGCCTRL_1 register, mask the THRESHOLD_LOW field and return the value  */
+  g_xStatus = SpiritSpiReadRegisters(AGCCTRL1_BASE, 1, &tempRegValue);
+  
+  return (tempRegValue & 0x0F);
+  
+}
+
+
+/**
+* @brief  Sets the clock recovery algorithm.
+* @param  xMode the Clock Recovery mode. This parameter can be one of the values defined in @ref ClkRecMode :
+*         @arg CLK_REC_PLL     PLL alogrithm for clock recovery
+*         @arg CLK_REC_DLL     DLL alogrithm for clock recovery
+* @retval None.
+*/
+void SpiritRadioSetClkRecMode(ClkRecMode xMode)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_CLK_REC_MODE(xMode));
+  
+  /* Reads the FDEV_0 register */
+  SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue);
+  
+  /* Mask the CLOCK_REC_ALGO_SEL field and write the new value */
+  tempRegValue &= 0xF7;
+  tempRegValue |= (uint8_t)xMode;
+  
+  /* Sets the FDEV_0 register */
+  g_xStatus = SpiritSpiWriteRegisters(FDEV0_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the Clock Recovery working mode.
+* @param  None.
+* @retval ClkRecMode Clock Recovery mode. This parameter can be one of the values defined in @ref ClkRecMode :
+*         @arg CLK_REC_PLL     PLL alogrithm for clock recovery
+*         @arg CLK_REC_DLL     DLL alogrithm for clock recovery
+*/
+ClkRecMode SpiritRadioGetClkRecMode(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the FDEV_0 register, mask the CLOCK_REC_ALGO_SEL field and return the value */
+  g_xStatus = SpiritSpiReadRegisters(FDEV0_BASE, 1, &tempRegValue);
+  
+  return (ClkRecMode)(tempRegValue & 0x08);
+  
+}
+
+
+/**
+* @brief  Sets the clock recovery proportional gain.
+* @param  cPGain the Clock Recovery proportional gain to write in the CLK_REC_P_GAIN field of CLOCKREC register.
+*         It represents is log2 value of the clock recovery proportional gain.
+*          This parameter shall be in the range [0:7].
+* @retval None.
+*/
+void SpiritRadioSetClkRecPGain(uint8_t cPGain)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_CLK_REC_P_GAIN(cPGain));
+  
+  /* Reads the CLOCKREC register */
+  SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+  /* Mask the CLK_REC_P_GAIN field and write the new value */
+  tempRegValue &= 0x1F;
+  tempRegValue |= (cPGain<<5);
+  
+  /* Sets the CLOCKREC register */
+  g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the log2 of the clock recovery proportional gain.
+* @param  None.
+* @retval uint8_t Clock Recovery proportional gain read from the CLK_REC_P_GAIN field of CLOCKREC register.
+*         This parameter will be in the range [0:7].
+*/
+uint8_t SpiritRadioGetClkRecPGain(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the CLOCKREC register, mask the CLK_REC_P_GAIN field and return the value  */
+  g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+  return ((tempRegValue & 0xEF)>>5);
+  
+}
+
+
+/**
+* @brief  Sets the clock recovery integral gain.
+* @param  cIGain the Clock Recovery integral gain to write in the CLK_REC_I_GAIN field of CLOCKREC register.
+*         This parameter shall be in the range [0:15].
+* @retval None.
+*/
+void SpiritRadioSetClkRecIGain(uint8_t cIGain)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_CLK_REC_I_GAIN(cIGain));
+  
+  /* Reads the CLOCKREC register */
+  SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+  /* Mask the CLK_REC_P_GAIN field and write the new value */
+  tempRegValue &= 0xF0;
+  tempRegValue |= cIGain;
+  
+  /* Sets the CLOCKREC register */
+  g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the clock recovery integral gain.
+* @param  None.
+* @retval uint8_t Clock Recovery integral gain read from the
+*         CLK_REC_I_GAIN field of CLOCKREC register.
+*         This parameter will be in the range [0:15].
+*/
+uint8_t SpiritRadioGetClkRecIGain(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the CLOCKREC register, mask the CLK_REC_I_GAIN field and return the value */
+  g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+  return (tempRegValue & 0x0F);
+  
+}
+
+
+/**
+* @brief  Sets the postfilter length for clock recovery algorithm.
+* @param  xLength the postfilter length in symbols. This parameter can be one of the values defined in @ref PstFltLength :
+*         @arg PSTFLT_LENGTH_8     Postfilter length is 8 symbols
+*         @arg PSTFLT_LENGTH_16    Postfilter length is 16 symbols
+* @retval None.
+*/
+void SpiritRadioSetClkRecPstFltLength(PstFltLength xLength)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameter */
+  s_assert_param(IS_PST_FLT_LENGTH(xLength));
+  
+  /* Reads the CLOCKREC register */
+  SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+  /* Mask the PSTFLT_LEN field and write the new value */
+  tempRegValue &= 0xEF;
+  tempRegValue |= (uint8_t)xLength;
+  
+  /* Sets the CLOCKREC register */
+  g_xStatus = SpiritSpiWriteRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+}
+
+
+/**
+* @brief  Returns the postfilter length for clock recovery algorithm.
+* @param  None.
+* @retval PstFltLength Postfilter length in symbols. This parameter can be one of the values defined in @ref PstFltLength :
+*         @arg PSTFLT_LENGTH_8     Postfilter length is 8 symbols
+*         @arg PSTFLT_LENGTH_16    Postfilter length is 16 symbols
+*/
+PstFltLength SpiritRadioGetClkRecPstFltLength(void)
+{
+  uint8_t tempRegValue;
+  
+  /* Reads the CLOCKREC register, mask the PSTFLT_LEN field and return the value */
+  g_xStatus = SpiritSpiReadRegisters(CLOCKREC_BASE, 1, &tempRegValue);
+  
+  return (PstFltLength)(tempRegValue & 0x10);
+  
+}
+
+
+/**
+* @brief  Enables or Disables the received data blanking when the CS is under the threshold.
+* @param  xNewState new state of this mode.
+*         This parameter can be: S_ENABLE or S_DISABLE .
+* @retval None.
+*/
+void SpiritRadioCsBlanking(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the ANT_SELECT_CONF_BASE and mask the CS_BLANKING BIT field */
+  SpiritSpiReadRegisters(ANT_SELECT_CONF_BASE, 1, &tempRegValue);
+  
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= ANT_SELECT_CS_BLANKING_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~ANT_SELECT_CS_BLANKING_MASK);
+  }
+  
+  /* Writes the new value in the ANT_SELECT_CONF register */
+  g_xStatus = SpiritSpiWriteRegisters(ANT_SELECT_CONF_BASE, 1, &tempRegValue);
+  
+  
+}
+
+/**
+* @brief  Enables or Disables the persistent RX mode.
+* @param  xNewState new state of this mode.
+*         This parameter can be: S_ENABLE or S_DISABLE .
+* @retval None.
+*/
+void SpiritRadioPersistenRx(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the PROTOCOL0_BASE and mask the PROTOCOL0_PERS_RX_MASK bitfield */
+  SpiritSpiReadRegisters(PROTOCOL0_BASE, 1, &tempRegValue);
+  
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL0_PERS_RX_MASK;
+  }
+  else
+  {
+    tempRegValue &= (~PROTOCOL0_PERS_RX_MASK);
+  }
+  
+  /* Writes the new value in the PROTOCOL0_BASE register */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL0_BASE, 1, &tempRegValue);
+  
+}
+
+/**
+* @brief  Enables or Disables the synthesizer reference divider.
+* @param  xNewState new state for synthesizer reference divider.
+*         This parameter can be: S_ENABLE or S_DISABLE .
+* @retval None.
+*/
+void SpiritRadioSetRefDiv(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the SYNTH_CONFIG1_BASE and mask the REFDIV bit field */
+  SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue);
+  
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue |= 0x80;
+  }
+  else
+  {
+    tempRegValue &= 0x7F;
+  }
+  
+  /* Writes the new value in the SYNTH_CONFIG1_BASE register */
+  g_xStatus = SpiritSpiWriteRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue);
+  
+}
+
+/**
+* @brief  Get the the synthesizer reference divider state.
+* @param  void.
+* @retval None.
+*/
+SpiritFunctionalState SpiritRadioGetRefDiv(void)
+{
+  uint8_t tempRegValue;
+  
+  g_xStatus = SpiritSpiReadRegisters(SYNTH_CONFIG1_BASE, 1, &tempRegValue);
+  
+  if(((tempRegValue>>7)&0x1))
+  {
+    return S_ENABLE;
+  }
+  else
+  {
+    return S_DISABLE;
+  }
+  
+}
+
+/**
+* @brief  Enables or Disables the synthesizer reference divider.
+* @param  xNewState new state for synthesizer reference divider.
+*         This parameter can be: S_ENABLE or S_DISABLE .
+* @retval None.
+*/
+void SpiritRadioSetDigDiv(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+  
+  /* Check the parameters */
+  s_assert_param(IS_SPIRIT_FUNCTIONAL_STATE(xNewState));
+  
+  /* Reads the XO_RCO_TEST_BASE and mask the PD_CLKDIV bit field */
+  SpiritSpiReadRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue);
+  
+  if(xNewState == S_ENABLE)
+  {
+    tempRegValue &= 0xf7;
+  }
+  else
+  {
+    
+    tempRegValue |= 0x08;
+  }
+  
+  /* Writes the new value in the XO_RCO_TEST_BASE register */
+  g_xStatus = SpiritSpiWriteRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue);
+  
+}
+
+/**
+* @brief  Get the the synthesizer reference divider state.
+* @param  void.
+* @retval None.
+*/
+SpiritFunctionalState SpiritRadioGetDigDiv(void)
+{
+  uint8_t tempRegValue;
+  
+  g_xStatus = SpiritSpiReadRegisters(XO_RCO_TEST_BASE, 1, &tempRegValue);
+  
+  if(((tempRegValue>>3)&0x1))
+  {
+    return S_DISABLE;
+  }
+  else
+  {
+    return S_ENABLE;
+  }
+  
+}
+
+/**
+* @brief  Returns the XTAL frequency.
+* @param  void.
+* @retval uint32_t XTAL frequency.
+*/
+uint32_t SpiritRadioGetXtalFrequency(void)
+{
+  return s_lXtalFrequency; 
+}
+
+/**
+* @brief  Sets the XTAL frequency.
+* @param  uint32_t XTAL frequency.
+* @retval void.
+*/
+void SpiritRadioSetXtalFrequency(uint32_t lXtalFrequency)
+{
+  s_lXtalFrequency = lXtalFrequency; 
+}
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+
+/**
+* @}
+*/
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Timer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Timer.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,700 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_Timer.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   Configuration and management of SPIRIT timers.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Timer.h"
+#include "SPIRIT_Radio.h"
+#include "MCU_Interface.h"
+
+
+
+
+/**
+ * @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/**
+ * @addtogroup SPIRIT_Timer
+ * @{
+ */
+
+
+/**
+ * @defgroup Timer_Private_TypesDefinitions             Timer Private Types Definitions
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Timer_Private_Defines                      Timer Private Defines
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Timer_Private_Macros                       Timer Private Macros
+ * @{
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Timer_Private_Variables                    Timer Private Variables
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Timer_Private_FunctionPrototypes            Timer Private Function Prototypes
+ * @{
+ */
+
+/**
+ *@}
+ */
+
+
+/**
+ * @defgroup Timer_Private_Functions                    Timer Private Functions
+ * @{
+ */
+
+/**
+ * @brief  Enables or Disables the LDCR mode.
+ * @param  xNewState new state for LDCR mode.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritTimerLdcrMode(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+  /* Mask the read value to enable or disable the LDC mode */
+  if(xNewState==S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL2_LDC_MODE_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL2_LDC_MODE_MASK;
+  }
+
+  /* Writes the register to Enable or Disable the LDCR mode */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL2_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Enables or Disables the LDCR timer reloading with the value stored in the LDCR_RELOAD registers.
+ * @param  xNewState new state for LDCR reloading.
+ *         This parameter can be: S_ENABLE or S_DISABLE.
+ * @retval None.
+ */
+void SpiritTimerLdcrAutoReload(SpiritFunctionalState xNewState)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  /* Mask te read value to enable or disable the reload on sync mode */
+  if(xNewState==S_ENABLE)
+  {
+    tempRegValue |= PROTOCOL1_LDC_RELOAD_ON_SYNC_MASK;
+  }
+  else
+  {
+    tempRegValue &= ~PROTOCOL1_LDC_RELOAD_ON_SYNC_MASK;
+  }
+
+  /* Writes the register to Enable or Disable the Auto Reload */
+  g_xStatus = SpiritSpiWriteRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+}
+
+
+/**
+ * @brief  Returns the LDCR timer reload bit.
+ * @param  None.
+ * @retval SpiritFunctionalState: value of the reload bit.
+ */
+SpiritFunctionalState SpiritTimerLdcrGetAutoReload(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the register value */
+  g_xStatus = SpiritSpiReadRegisters(PROTOCOL1_BASE, 1, &tempRegValue);
+
+  return (SpiritFunctionalState)(tempRegValue & 0x80);
+
+}
+
+/**
+ * @brief  Sets the RX timeout timer initialization registers with the values of COUNTER and PRESCALER according to the formula: Trx=PRESCALER*COUNTER*Tck.
+ *         Remember that it is possible to have infinite RX_Timeout writing 0 in the RX_Timeout_Counter and/or RX_Timeout_Prescaler registers.
+ * @param  cCounter value for the timer counter.
+ *         This parameter must be an uint8_t.
+ * @param  cPrescaler value for the timer prescaler.
+ *         This parameter must be an uint8_t.
+ * @retval None.
+ */
+void SpiritTimerSetRxTimeout(uint8_t cCounter , uint8_t cPrescaler)
+{
+  uint8_t tempRegValue[2]={cPrescaler,cCounter};
+
+  /* Writes the prescaler and counter value for RX timeout in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS5_RX_TIMEOUT_PRESCALER_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the RX timeout timer counter and prescaler from the desired value in ms. it is possible to fix the RX_Timeout to
+ *         a minimum value of 50.417us to a maximum value of about 3.28 s.
+ * @param  fDesiredMsec desired timer value.
+ *         This parameter must be a float.
+ * @retval None
+ */
+
+void SpiritTimerSetRxTimeoutMs(float fDesiredMsec)
+{
+  uint8_t tempRegValue[2];
+
+  /* Computes the counter and prescaler value */
+  SpiritTimerComputeRxTimeoutValues(fDesiredMsec , &tempRegValue[1] , &tempRegValue[0]);
+
+  /* Writes the prescaler and counter value for RX timeout in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS5_RX_TIMEOUT_PRESCALER_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the RX timeout timer counter. If it is equal to 0 the timeout is infinite.
+ * @param  cCounter value for the timer counter.
+ *         This parameter must be an uint8_t.
+ * @retval None.
+ */
+void SpiritTimerSetRxTimeoutCounter(uint8_t cCounter)
+{
+  /* Writes the counter value for RX timeout in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS4_RX_TIMEOUT_COUNTER_BASE, 1, &cCounter);
+
+}
+
+
+/**
+ * @brief  Sets the RX timeout timer prescaler. If it is equal to 0 the timeout is infinite.
+ * @param  cPrescaler value for the timer prescaler.
+ *         This parameter must be an uint8_t.
+ * @retval None
+ */
+void SpiritTimerSetRxTimeoutPrescaler(uint8_t cPrescaler)
+{
+  /* Writes the prescaler value for RX timeout in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS5_RX_TIMEOUT_PRESCALER_BASE, 1, &cPrescaler);
+
+}
+
+
+/**
+ * @brief  Returns the RX timeout timer.
+ * @param  pfTimeoutMsec pointer to the variable in which the timeout expressed in milliseconds has to be stored.
+ *         If the returned value is 0, it means that the RX_Timeout is infinite.
+ *         This parameter must be a float*.
+ * @param  pcCounter pointer to the variable in which the timer counter has to be stored.
+ *         This parameter must be an uint8_t*.
+ * @param  pcPrescaler pointer to the variable in which the timer prescaler has to be stored.
+ *         This parameter must be an uint8_t*.
+ * @retval None.
+ */
+void SpiritTimerGetRxTimeout(float* pfTimeoutMsec, uint8_t* pcCounter , uint8_t* pcPrescaler)
+{
+  uint8_t tempRegValue[2];
+
+  /* Reads the RX timeout registers value */
+  g_xStatus = SpiritSpiReadRegisters(TIMERS5_RX_TIMEOUT_PRESCALER_BASE, 2, tempRegValue);
+
+  /* Returns values */
+  (*pcPrescaler) = tempRegValue[0];
+  (*pcCounter) = tempRegValue[1];
+    
+  float nXtalFrequency = (float)SpiritRadioGetXtalFrequency();
+  if(nXtalFrequency>DOUBLE_XTAL_THR) {
+    nXtalFrequency /= 2.0;
+  }
+  nXtalFrequency /= 1000.0;
+  *pfTimeoutMsec = (float)((tempRegValue[0]+1)*tempRegValue[1]*(1210.0/nXtalFrequency));
+  
+
+}
+
+
+/**
+ * @brief  Sets the LDCR wake up timer initialization registers with the values of
+ *         COUNTER and PRESCALER according to the formula: Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where
+ *         Tck = 28.818 us. The minimum vale of the wakeup timeout is 28.818us (PRESCALER and
+ *         COUNTER equals to 0) and the maximum value is about 1.89 s (PRESCALER anc COUNTER equals
+ *         to 255).
+ * @param  cCounter value for the timer counter.
+ *         This parameter must be an uint8_t.
+ * @param  cPrescaler value for the timer prescaler.
+ *         This parameter must be an uint8_t.
+ * @retval None.
+ */
+void SpiritTimerSetWakeUpTimer(uint8_t cCounter , uint8_t cPrescaler)
+{
+  uint8_t tempRegValue[2]={cPrescaler,cCounter};
+
+  /* Writes the counter and prescaler value of wake-up timer in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS3_LDC_PRESCALER_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the LDCR wake up timer counter and prescaler from the desired value in ms,
+ *         according to the formula: Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where Tck = 28.818 us.
+ *         The minimum vale of the wakeup timeout is 28.818us (PRESCALER and COUNTER equals to 0)
+ *         and the maximum value is about 1.89 s (PRESCALER anc COUNTER equals to 255).
+ * @param  fDesiredMsec desired timer value.
+ *         This parameter must be a float.
+ * @retval None.
+ */
+void SpiritTimerSetWakeUpTimerMs(float fDesiredMsec)
+{
+  uint8_t tempRegValue[2];
+
+  /* Computes counter and prescaler */
+  SpiritTimerComputeWakeUpValues(fDesiredMsec , &tempRegValue[1] , &tempRegValue[0]);
+
+  /* Writes the counter and prescaler value of wake-up timer in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS3_LDC_PRESCALER_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the LDCR wake up timer counter. Remember that this value is incresead by one in the Twu calculation.
+ *         Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where Tck = 28.818 us
+ * @param  cCounter value for the timer counter.
+ *         This parameter must be an uint8_t.
+ * @retval None.
+ */
+void SpiritTimerSetWakeUpTimerCounter(uint8_t cCounter)
+{
+  /* Writes the counter value for Wake_Up timer in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS2_LDC_COUNTER_BASE, 1, &cCounter);
+
+}
+
+
+/**
+ * @brief  Sets the LDCR wake up timer prescaler. Remember that this value is incresead by one in the Twu calculation.
+ *         Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where Tck = 28.818 us
+ * @param  cPrescaler value for the timer prescaler.
+ *         This parameter must be an uint8_t.
+ * @retval None.
+ */
+void SpiritTimerSetWakeUpTimerPrescaler(uint8_t cPrescaler)
+{
+  /* Writes the prescaler value for Wake_Up timer in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS3_LDC_PRESCALER_BASE, 1, &cPrescaler);
+
+}
+
+
+/**
+ * @brief  Returns the LDCR wake up timer, according to the formula: Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where Tck = 28.818 us.
+ * @param  pfWakeUpMsec pointer to the variable in which the wake-up time expressed in milliseconds has to be stored.
+ *         This parameter must be a float*.
+ * @param  pcCounter pointer to the variable in which the timer counter has to be stored.
+ *         This parameter must be an uint8_t*.
+ * @param  pcPrescaler pointer to the variable in which the timer prescaler has to be stored.
+ *         This parameter must be an uint8_t*.
+ * @retval None.
+ */
+void SpiritTimerGetWakeUpTimer(float* pfWakeUpMsec, uint8_t* pcCounter , uint8_t* pcPrescaler)
+{
+  uint8_t tempRegValue[2];
+  //uint32_t xtal=SpiritRadioGetXtalFrequency();
+  float rco_freq;
+  
+  rco_freq=(float)SpiritTimerGetRcoFrequency();
+  
+  /* Reads the Wake_Up timer registers value */
+  g_xStatus = SpiritSpiReadRegisters(TIMERS3_LDC_PRESCALER_BASE, 2, tempRegValue);
+
+  /* Returns values */
+  (*pcPrescaler)=tempRegValue[0];
+  (*pcCounter)=tempRegValue[1];
+  *pfWakeUpMsec = (float)((((*pcPrescaler)+1)*((*pcCounter)+1)*(1000.0/rco_freq)));
+
+}
+
+
+/**
+ * @brief  Sets the LDCR wake up timer reloading registers with the values of
+ *         COUNTER and PRESCALER according to the formula: Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where
+ *         Tck = 28.818 us. The minimum vale of the wakeup timeout is 28.818us (PRESCALER and
+ *         COUNTER equals to 0) and the maximum value is about 1.89 s (PRESCALER anc COUNTER equals
+ *         to 255).
+ * @param  cCounter reload value for the timer counter.
+ *         This parameter must be an uint8_t.
+ * @param  cPrescaler reload value for the timer prescaler.
+ *         This parameter must be an uint8_t.
+ * @retval None.
+ */
+void SpiritTimerSetWakeUpTimerReload(uint8_t cCounter , uint8_t cPrescaler)
+{
+  uint8_t tempRegValue[2]={cPrescaler,cCounter};
+
+  /* Writes the counter and prescaler value of reload wake-up timer in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS1_LDC_RELOAD_PRESCALER_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the LDCR wake up reload timer counter and prescaler from the desired value in ms,
+ *         according to the formula: Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where Tck = 28.818 us.
+ *         The minimum vale of the wakeup timeout is 28.818us (PRESCALER and COUNTER equals to 0)
+ *         and the maximum value is about 1.89 s (PRESCALER anc COUNTER equals to 255).
+ * @param  fDesiredMsec desired timer value.
+ *         This parameter must be a float.
+ * @retval None.
+ */
+void SpiritTimerSetWakeUpTimerReloadMs(float fDesiredMsec)
+{
+  uint8_t tempRegValue[2];
+
+  /* Computes counter and prescaler */
+  SpiritTimerComputeWakeUpValues(fDesiredMsec , &tempRegValue[1] , &tempRegValue[0]);
+
+  /* Writes the counter and prescaler value of reload wake-up timer in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS1_LDC_RELOAD_PRESCALER_BASE, 2, tempRegValue);
+
+}
+
+
+/**
+ * @brief  Sets the LDCR wake up timer reload counter. Remember that this value is incresead by one in the Twu calculation.
+ *         Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where Tck = 28.818 us
+ * @param  cCounter value for the timer counter.
+ *         This parameter must be an uint8_t.
+ * @retval None
+ */
+void SpiritTimerSetWakeUpTimerReloadCounter(uint8_t cCounter)
+{
+  /* Writes the counter value for reload Wake_Up timer in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS0_LDC_RELOAD_COUNTER_BASE, 1, &cCounter);
+
+}
+
+
+/**
+ * @brief  Sets the LDCR wake up timer reload prescaler. Remember that this value is incresead by one in the Twu calculation.
+ *         Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where Tck = 28.818 us
+ * @param  cPrescaler value for the timer prescaler.
+ *         This parameter must be an uint8_t.
+ * @retval None
+ */
+void SpiritTimerSetWakeUpTimerReloadPrescaler(uint8_t cPrescaler)
+{
+  /* Writes the prescaler value for reload Wake_Up timer in the corresponding register */
+  g_xStatus = SpiritSpiWriteRegisters(TIMERS1_LDC_RELOAD_PRESCALER_BASE, 1, &cPrescaler);
+
+}
+
+
+/**
+ * @brief  Returns the LDCR wake up reload timer, according to the formula: Twu=(PRESCALER +1)*(COUNTER+1)*Tck, where Tck = 28.818 us.
+ * @param  pfWakeUpReloadMsec pointer to the variable in which the wake-up reload time expressed in milliseconds has to be stored.
+ *         This parameter must be a float*.
+ * @param  pcCounter pointer to the variable in which the timer counter has to be stored.
+ *         This parameter must be an uint8_t*.
+ * @param  pcPrescaler pointer to the variable in which the timer prescaler has to be stored.
+ *         This parameter must be an uint8_t*.
+ * @retval None.
+ */
+void SpiritTimerGetWakeUpTimerReload(float* pfWakeUpReloadMsec, uint8_t* pcCounter , uint8_t* pcPrescaler)
+{
+  uint8_t tempRegValue[2];
+  //uint32_t xtal=SpiritRadioGetXtalFrequency();
+  float rco_freq;
+  
+  rco_freq=(float)SpiritTimerGetRcoFrequency();
+  
+  /* Reads the reload Wake_Up timer registers value */
+  g_xStatus = SpiritSpiReadRegisters(TIMERS1_LDC_RELOAD_PRESCALER_BASE, 2, tempRegValue);
+
+  /* Returns values */
+  (*pcPrescaler)=tempRegValue[0];
+  (*pcCounter)=tempRegValue[1];
+  *pfWakeUpReloadMsec = (float)((((*pcPrescaler)+1)*((*pcCounter)+1)*(1000.0/rco_freq)));
+
+}
+
+/**
+ * @brief  Computes and returns the RCO frequency. 
+ *         This frequency depends on the xtal frequency and the XTAL bit in register 0x01.
+ * @retval RCO frequency in Hz as an uint16_t.
+ */
+uint16_t SpiritTimerGetRcoFrequency(void)
+{
+  uint16_t rco_freq=34700;
+  uint32_t xtal=SpiritRadioGetXtalFrequency();
+  
+  if(xtal>30000000) xtal/=2;
+  
+  if(xtal==25000000)
+  {
+    uint8_t xtal_flag;
+    SpiritSpiReadRegisters(0x01, 1, &xtal_flag);
+    xtal_flag=(xtal_flag&0x40);
+    
+    if(xtal_flag==0)
+    {
+      rco_freq=36100;
+    }
+    else
+    {
+      rco_freq=33300;
+    }
+  }
+  
+  return rco_freq;
+}
+
+/**
+ * @brief  Computes the values of the wakeup timer counter and prescaler from the user time expressed in millisecond.
+ *         The prescaler and the counter values are computed maintaining the prescaler value as
+ *         small as possible in order to obtain the best resolution, and in the meantime minimizing the error.
+ * @param  fDesiredMsec desired wakeup timeout in millisecs.
+ *         This parameter must be a float. Since the counter and prescaler are 8 bit registers the maximum
+ *         reachable value is maxTime = fTclk x 256 x 256.
+ * @param  pcCounter pointer to the variable in which the value for the wakeup timer counter has to be stored.
+ *         This parameter must be a uint8_t*.
+ * @param  pcPrescaler pointer to the variable in which the value for the wakeup timer prescaler has to be stored.
+ *         This parameter must be an uint8_t*.
+ * @retval None
+ */
+void SpiritTimerComputeWakeUpValues(float fDesiredMsec , uint8_t* pcCounter , uint8_t* pcPrescaler)
+{
+  float rco_freq,err;
+  uint32_t n;
+  
+  rco_freq=((float)SpiritTimerGetRcoFrequency())/1000;
+  
+  /* N cycles in the time base of the timer: 
+     - clock of the timer is RCO frequency
+     - divide times 1000 more because we have an input in ms (variable rco_freq is already this frequency divided by 1000)
+  */
+  n=(uint32_t)(fDesiredMsec*rco_freq);
+    
+  /* check if it is possible to reach that target with prescaler and counter of spirit1 */
+  if(n/0xFF>0xFD)
+  {
+    /* if not return the maximum possible value */
+    (*pcCounter) = 0xFF;
+    (*pcPrescaler) = 0xFF;
+    return;
+  }
+  
+  /* prescaler is really 2 as min value */
+  (*pcPrescaler)=(n/0xFF)+2;
+  (*pcCounter) = n / (*pcPrescaler);
+  
+  /* check if the error is minimum */
+  err=S_ABS((float)(*pcCounter)*(*pcPrescaler)/rco_freq-fDesiredMsec);
+  
+  if((*pcCounter)<=254)
+  {
+    if(S_ABS((float)((*pcCounter)+1)*(*pcPrescaler)/rco_freq-fDesiredMsec)<err)
+      (*pcCounter)=(*pcCounter)+1;
+  }
+    
+  /* decrement prescaler and counter according to the logic of this timer in spirit1 */
+  (*pcPrescaler)--;
+  if((*pcCounter)>1)
+    (*pcCounter)--;
+  else
+    (*pcCounter)=1;
+}
+
+
+/**
+ * @brief  Computes the values of the rx_timeout timer counter and prescaler from the user time expressed in millisecond.
+ *         The prescaler and the counter values are computed maintaining the prescaler value as
+ *         small as possible in order to obtain the best resolution, and in the meantime minimizing the error.
+ * @param  fDesiredMsec desired rx_timeout in millisecs.
+ *         This parameter must be a float. Since the counter and prescaler are 8 bit registers the maximum
+ *         reachable value is maxTime = fTclk x 255 x 255.
+ * @param  pcCounter pointer to the variable in which the value for the rx_timeout counter has to be stored.
+ *         This parameter must be a uint8_t*.
+ * @param  pcPrescaler pointer to the variable in which the value for the rx_timeout prescaler has to be stored.
+ *         This parameter must be an uint8_t*.
+ * @retval None
+ */
+void SpiritTimerComputeRxTimeoutValues(float fDesiredMsec , uint8_t* pcCounter , uint8_t* pcPrescaler)
+{
+  uint32_t nXtalFrequency = SpiritRadioGetXtalFrequency();
+  uint32_t n;
+  float err;
+  
+  /* if xtal is doubled divide it by 2 */
+  if(nXtalFrequency>DOUBLE_XTAL_THR) {
+    nXtalFrequency >>= 1;
+  }
+  
+  /* N cycles in the time base of the timer: 
+     - clock of the timer is xtal/1210
+     - divide times 1000 more because we have an input in ms
+  */
+  n=(uint32_t)(fDesiredMsec*nXtalFrequency/1210000);
+  
+  /* check if it is possible to reach that target with prescaler and counter of spirit1 */
+  if(n/0xFF>0xFD)
+  {
+    /* if not return the maximum possible value */
+    (*pcCounter) = 0xFF;
+    (*pcPrescaler) = 0xFF;
+    return;
+  }
+  
+  /* prescaler is really 2 as min value */
+  (*pcPrescaler)=(n/0xFF)+2;
+  (*pcCounter) = n / (*pcPrescaler);
+  
+  /* check if the error is minimum */
+  err=S_ABS((float)(*pcCounter)*(*pcPrescaler)*1210000/nXtalFrequency-fDesiredMsec);
+  
+  if((*pcCounter)<=254)
+  {
+    if(S_ABS((float)((*pcCounter)+1)*(*pcPrescaler)*1210000/nXtalFrequency-fDesiredMsec)<err)
+      (*pcCounter)=(*pcCounter)+1;
+  }
+    
+  /* decrement prescaler and counter according to the logic of this timer in spirit1 */
+  (*pcPrescaler)--;
+  if((*pcCounter)>1)
+    (*pcCounter)--;
+  else
+    (*pcCounter)=1;
+}
+
+
+/**
+ * @brief  Sets the RX timeout stop conditions.
+ * @param  xStopCondition new stop condition.
+ *         This parameter can be any value of @ref RxTimeoutStopCondition.
+ * @retval None
+ */
+void SpiritTimerSetRxTimeoutStopCondition(RxTimeoutStopCondition xStopCondition)
+{
+  uint8_t tempRegValue[2];
+
+  /* Check the parameters */
+  s_assert_param(IS_RX_TIMEOUT_STOP_CONDITION(xStopCondition));
+
+  /* Reads value on the PKT_FLT_OPTIONS and PROTOCOL2 register */
+  g_xStatus = SpiritSpiReadRegisters(PCKT_FLT_OPTIONS_BASE, 2, tempRegValue);
+
+  tempRegValue[0] &= 0xBF;
+  tempRegValue[0] |= ((xStopCondition & 0x08)  << 3);
+
+  tempRegValue[1] &= 0x1F;
+  tempRegValue[1] |= (xStopCondition << 5);
+
+  /* Writes value on the PKT_FLT_OPTIONS and PROTOCOL2 register */
+  g_xStatus = SpiritSpiWriteRegisters(PCKT_FLT_OPTIONS_BASE, 2, tempRegValue);
+
+}
+
+/**
+ * @brief  Sends the LDC_RELOAD command to SPIRIT. Reload the LDC timer with the value stored in the LDC_PRESCALER / COUNTER registers.
+ * @param  None.
+ * @retval None
+ */
+void SpiritTimerReloadStrobe(void)
+{
+  /* Sends the CMD_LDC_RELOAD command */
+  g_xStatus = SpiritSpiCommandStrobes(COMMAND_LDC_RELOAD);
+
+}
+
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+/**
+ *@}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Types.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/SPIRIT1_Library/Src/SPIRIT_Types.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,225 @@
+/**
+  ******************************************************************************
+  * @file    SPIRIT_Types.c
+  * @author  VMA division - AMS
+  * @version 3.2.2
+  * @date    08-July-2015
+  * @brief   File for SPIRIT types.
+  * @details
+  *
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "SPIRIT_Types.h"
+#include "MCU_Interface.h"
+
+
+/** @addtogroup SPIRIT_Libraries
+ * @{
+ */
+
+
+/** @addtogroup SPIRIT_Types
+ * @{
+ */
+
+
+/** @defgroup Types_Private_TypesDefinitions    Types Private Types Definitions
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Types_Private_Defines             Types Private Defines
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Types_Private_Macros               Types Private Macros
+ * @{
+ */
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Types_Private_Variables             Types Private Variables
+ * @{
+ */
+
+/**
+ * @brief  Spirit Status global variable.
+ *         This global variable of @ref SpiritStatus type is updated on every SPI transaction
+ *         to maintain memory of Spirit Status.
+ */
+
+volatile SpiritStatus g_xStatus;
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Types_Private_FunctionPrototypes       Types Private FunctionPrototypes
+ * @{
+ */
+
+
+
+/**
+ * @}
+ */
+
+
+
+/** @defgroup Types_Private_Functions                 Types Private Functions
+ * @{
+ */
+
+#ifdef  SPIRIT_USE_FULL_ASSERT
+/**
+ * @brief  Reports the name of the source file and the source line number
+ *         where the assert_param error has occurred.
+ * @param file  pointer to the source file name
+ * @param line  assert_param error line source number
+ * @retval : None
+ */
+void s_assert_failed(uint8_t* file, uint32_t line)
+{
+  /* User can add his own implementation to report the file name and line number */
+  printf("Wrong parameters value: file %s on line %d\r\n", file, (int)line);
+
+  /* Infinite loop */
+  while (1)
+  {
+  }
+}
+#elif SPIRIT_USE_VCOM_ASSERT
+
+#include "SDK_EVAL_VC_General.h"
+
+/**
+ * @brief  Reports the name of the source file and the source line number
+ *         where the assert_param error has occurred.
+ * @param file pointer to the source file name
+ * @param line  assert_param error line source number
+ * @param expression: string representing the assert failed expression
+ * @retval : None
+ */
+void s_assert_failed(uint8_t* file, uint32_t line, char* expression)
+{
+
+  printf("\n\rVCOM DEBUG: Incorrect parameter. Please reboot.\n\r");
+  printf("%s:%d \n\r",file,line);
+  printf("The expression %s returned FALSE.\n\r", expression);
+
+  /* Infinite loop */
+  while (1)
+  {
+  }
+}
+
+#elif SPIRIT_USE_FRAME_ASSERT
+
+#include "SdkUsbProtocol.h"
+
+/**
+ * @brief Sends a notify frame with a payload indicating the name 
+ *        of the assert failed.
+ * @param expression: string representing the assert failed expression
+ * @retval : None
+ */
+void s_assert_failed(char* expression)
+{
+  char pcPayload[100];
+  uint16_t i;
+  
+  for(i = 0 ; expression[i]!='(' ; i++);
+  expression[i]='\0';
+  
+  strcpy(pcPayload, &expression[3]);
+  
+  //sprintf(pcPayload, "The expression %s returned FALSE.\n\r", expression);
+  SpiritNotifyAssertFailed(pcPayload);
+
+}
+
+#endif
+
+
+/**
+ * @brief  Updates the gState (the global variable used to maintain memory of Spirit Status)
+ *         reading the MC_STATE register of SPIRIT.
+ * @param  None
+ * @retval None
+ */
+void SpiritRefreshStatus(void)
+{
+  uint8_t tempRegValue;
+
+  /* Reads the MC_STATUS register to update the g_xStatus */
+  g_xStatus = SpiritSpiReadRegisters(MC_STATE1_BASE, 1, &tempRegValue);
+}
+
+
+/**
+ * @}
+ */
+
+
+
+/**
+ * @}
+ */
+
+
+
+/**
+ * @}
+ */
+
+
+
+/******************* (C) COPYRIGHT 2015 STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/X-NUCLEO-IDS01Ax/radio_gpio.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/X-NUCLEO-IDS01Ax/radio_gpio.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,224 @@
+/**
+******************************************************************************
+* @file    radio_gpio.h
+* @author  System Lab - NOIDA
+* @version V1.0.0
+* @date    15-May-2014
+* @brief   This file contains all the functions prototypes for the gpio  
+******************************************************************************
+* @attention
+*
+* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice,
+*      this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation
+*      and/or other materials provided with the distribution.
+*   3. Neither the name of STMicroelectronics nor the names of its contributors
+*      may be used to endorse or promote products derived from this software
+*      without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+******************************************************************************
+*/
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported Variables ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __RADIO_GPIO_H
+#define __RADIO_GPIO_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+/* Includes ------------------------------------------------------------------*/
+#ifdef USE_STM32L1XX_NUCLEO
+#include "stm32l1xx_hal.h"
+#endif
+
+#ifdef USE_STM32F4XX_NUCLEO
+#include "stm32f4xx_hal.h"
+#endif
+#include "SPIRIT_Types.h"
+  
+/**
+ * @addtogroup BSP
+ * @{
+ */
+
+
+/* Exported types ------------------------------------------------------------*/
+  /* MCU GPIO pin working mode for GPIO */
+typedef enum                                                                                          
+{
+    RADIO_MODE_GPIO_IN  = 0x00,   /*!< Work as GPIO input */
+    RADIO_MODE_EXTI_IN,           /*!< Work as EXTI */
+    RADIO_MODE_GPIO_OUT,          /*!< Work as GPIO output */
+}RadioGpioMode;  
+
+ /* MCU GPIO pin enumeration for GPIO */
+typedef enum 
+{
+  RADIO_GPIO_0     = 0x00, /*!< GPIO_0 selected */
+  RADIO_GPIO_1     = 0x01, /*!< GPIO_1 selected */
+  RADIO_GPIO_2     = 0x02, /*!< GPIO_2 selected */
+  RADIO_GPIO_3     = 0x03, /*!< GPIO_3 selected */
+  RADIO_GPIO_SDN   = 0x04, /*!< GPIO_SDN selected */
+} 
+RadioGpioPin;   
+
+  
+/* Exported constants --------------------------------------------------------*/
+  
+  
+/* Exported macro ------------------------------------------------------------*/
+ /* MCU GPIO pin working mode for GPIO */
+#define IS_RADIO_GPIO_MODE(MODE) (((MODE) == RADIO_MODE_GPIO_IN) || \
+                               ((MODE) == RADIO_MODE_EXTI_IN) || \
+                               ((MODE) == RADIO_MODE_GPIO_OUT))
+
+/* Number of Arduino pins used for RADIO GPIO interface */
+#define RADIO_GPIO_NUMBER    ((uint8_t)5)
+
+/* MCU GPIO pin enumeration for GPIO */
+#define IS_RADIO_GPIO_PIN(PIN)   (((PIN) == RADIO_GPIO_0) || \
+                               ((PIN) == RADIO_GPIO_1) || \
+                               ((PIN) == RADIO_GPIO_2) || \
+                               ((PIN) == RADIO_GPIO_3) || \
+                               ((PIN) == RADIO_GPIO_SDN))
+
+/* Define for RADIO board */
+#if !defined (USE_SPIRIT1_DEFAULT)
+ #define USE_SPIRIT1_DEFAULT
+#endif  
+
+/* @defgroup Radio_Gpio_config_Define */
+/*NOTE: GPIO0, GPIO1, GPIO2 of SPIRIT1 is not used in the shield*/
+
+#define RADIO_GPIO_0_PORT                          GPIOC
+#define RADIO_GPIO_0_PIN                           GPIO_PIN_1
+#define RADIO_GPIO_0_CLOCK_ENABLE()                __GPIOC_CLK_ENABLE()
+#define RADIO_GPIO_0_CLOCK_DISABLE()               __GPIOC_CLK_ENABLE()   
+#define RADIO_GPIO_0_SPEED                         GPIO_SPEED_HIGH
+#define RADIO_GPIO_0_PUPD                          GPIO_NOPULL
+#define RADIO_GPIO_0_EXTI_LINE                     GPIO_PIN_1
+#define RADIO_GPIO_0_EXTI_MODE                     GPIO_MODE_IT_FALLING
+#define RADIO_GPIO_0_EXTI_IRQN                     EXTI1_IRQn 
+#define RADIO_GPIO_0_EXTI_PREEMPTION_PRIORITY      2
+#define RADIO_GPIO_0_EXTI_SUB_PRIORITY             2
+#define RADIO_GPIO_0_EXTI_IRQ_HANDLER              EXTI1_IRQHandler
+
+#define RADIO_GPIO_1_PORT                          GPIOB
+#define RADIO_GPIO_1_PIN                           GPIO_PIN_0
+#define RADIO_GPIO_1_CLOCK_ENABLE()                __GPIOB_CLK_ENABLE()
+#define RADIO_GPIO_1_CLOCK_DISABLE()               __GPIOB_CLK_ENABLE()   
+#define RADIO_GPIO_1_SPEED                         GPIO_SPEED_HIGH
+#define RADIO_GPIO_1_PUPD                          GPIO_NOPULL
+#define RADIO_GPIO_1_EXTI_LINE                     GPIO_PIN_0
+#define RADIO_GPIO_1_EXTI_MODE                     GPIO_MODE_IT_FALLING
+#define RADIO_GPIO_1_EXTI_IRQN                     EXTI0_IRQn 
+#define RADIO_GPIO_1_EXTI_PREEMPTION_PRIORITY      2
+#define RADIO_GPIO_1_EXTI_SUB_PRIORITY             2
+#define RADIO_GPIO_1_EXTI_IRQ_HANDLER              EXTI0_IRQHandler
+
+#define RADIO_GPIO_2_PORT                          GPIOA
+#define RADIO_GPIO_2_PIN                           GPIO_PIN_4
+#define RADIO_GPIO_2_CLOCK_ENABLE()                __GPIOA_CLK_ENABLE()
+#define RADIO_GPIO_2_CLOCK_DISABLE()               __GPIOA_CLK_ENABLE()   
+#define RADIO_GPIO_2_SPEED                         GPIO_SPEED_HIGH
+#define RADIO_GPIO_2_PUPD                          GPIO_NOPULL
+#define RADIO_GPIO_2_EXTI_LINE                     GPIO_PIN_4
+#define RADIO_GPIO_2_EXTI_MODE                     GPIO_MODE_IT_FALLING
+#define RADIO_GPIO_2_EXTI_IRQN                     EXTI4_IRQn 
+#define RADIO_GPIO_2_EXTI_PREEMPTION_PRIORITY      2
+#define RADIO_GPIO_2_EXTI_SUB_PRIORITY             2
+#define RADIO_GPIO_2_EXTI_IRQ_HANDLER              EXTI4_IRQHandler
+
+
+#if defined (USE_SPIRIT1_DEFAULT)
+
+
+#define RADIO_GPIO_3_PORT                          GPIOC
+#define RADIO_GPIO_3_PIN                           GPIO_PIN_7
+#define RADIO_GPIO_3_CLOCK_ENABLE()              __GPIOC_CLK_ENABLE()
+#define RADIO_GPIO_3_CLOCK_DISABLE()             __GPIOC_CLK_DISABLE()   
+#define RADIO_GPIO_3_SPEED                         GPIO_SPEED_HIGH
+#define RADIO_GPIO_3_PUPD                          GPIO_NOPULL
+#define RADIO_GPIO_3_EXTI_LINE                     GPIO_PIN_7
+#define RADIO_GPIO_3_EXTI_MODE                     GPIO_MODE_IT_FALLING
+#define RADIO_GPIO_3_EXTI_IRQN                     EXTI9_5_IRQn 
+#define RADIO_GPIO_3_EXTI_PREEMPTION_PRIORITY      2
+#define RADIO_GPIO_3_EXTI_SUB_PRIORITY             2
+#define RADIO_GPIO_3_EXTI_IRQ_HANDLER              EXTI9_5_IRQHandler
+
+#else
+
+#define RADIO_GPIO_3_PORT                        GPIOA
+#define RADIO_GPIO_3_PIN                         GPIO_PIN_0
+#define RADIO_GPIO_3_CLOCK_ENABLE()                __GPIOA_CLK_ENABLE()
+#define RADIO_GPIO_3_CLOCK_DISABLE()               __GPIOA_CLK_DISABLE() 
+#define RADIO_GPIO_3_SPEED                       GPIO_SPEED_HIGH
+#define RADIO_GPIO_3_PUPD                        GPIO_NOPULL
+#define RADIO_GPIO_3_EXTI_LINE                   GPIO_PIN_0
+#define RADIO_GPIO_3_EXTI_MODE                   GPIO_MODE_IT_FALLING
+#define RADIO_GPIO_3_EXTI_IRQN                   EXTI0_IRQn
+#define RADIO_GPIO_3_EXTI_PREEMPTION_PRIORITY    2
+#define RADIO_GPIO_3_EXTI_SUB_PRIORITY           2
+#define RADIO_GPIO_3_EXTI_IRQ_HANDLER            EXTI0_IRQHandler
+
+#endif
+
+#define RADIO_GPIO_SDN_PORT                        GPIOA
+#define RADIO_GPIO_SDN_PIN                         GPIO_PIN_10
+#define RADIO_GPIO_SDN_CLOCK_ENABLE()            __GPIOA_CLK_ENABLE()
+#define RADIO_GPIO_SDN_CLOCK_DISABLE()           __GPIOA_CLK_DISABLE()
+#define RADIO_GPIO_SDN_SPEED                       GPIO_SPEED_HIGH
+#define RADIO_GPIO_SDN_PUPD                        GPIO_PULLUP
+
+
+#define RADIO_GPIO_IRQ		RADIO_GPIO_3
+#define SPIRIT_GPIO_IRQ         SPIRIT_GPIO_3
+
+/* Exported Variables ------------------------------------------------------------*/
+  
+  
+/* Exported functions ------------------------------------------------------- */
+FlagStatus RadioGpioGetLevel(RadioGpioPin xGpio);
+void RadioGpioSetLevel(RadioGpioPin xGpio, GPIO_PinState xState);
+void SdkEvalEnterShutdown(void);
+void SdkEvalExitShutdown(void);
+SpiritFlagStatus SdkEvalCheckShutdown(void);
+void RadioGpioInit(RadioGpioPin xGpio, RadioGpioMode xGpioMode);
+void RadioGpioInterruptCmd(RadioGpioPin xGpio, uint8_t nPreemption, uint8_t nSubpriority, FunctionalState xNewState);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__RADIO_GPIO_H */
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/X-NUCLEO-IDS01Ax/radio_shield_config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/X-NUCLEO-IDS01Ax/radio_shield_config.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,120 @@
+/**
+******************************************************************************
+* @file    radio_shield_config.h
+* @author  System Lab - NOIDA
+* @version V1.0.0
+* @date    15-May-2014
+* @brief   This file contains definitions for:
+*          - LEDs and push-button available on RF shields
+******************************************************************************
+* @attention
+*
+* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice,
+*      this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation
+*      and/or other materials provided with the distribution.
+*   3. Neither the name of STMicroelectronics nor the names of its contributors
+*      may be used to endorse or promote products derived from this software
+*       without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+******************************************************************************
+*/ 
+  
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __RADIO_SHIELD_CONFIG_H
+#define __RADIO_SHIELD_CONFIG_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#ifdef USE_STM32L1XX_NUCLEO
+// #include "stm32l1xx_hal.h"
+#endif
+
+#ifdef USE_STM32F4XX_NUCLEO
+// #include "stm32f4xx_hal.h"
+#endif
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup X-NUCLEO-IDS02Ax
+  * @{
+  */
+
+/** @addtogroup RADIO_SHILED_LOW_LEVEL
+  * @{
+  */   
+   
+/* Exported types ------------------------------------------------------------*/
+typedef enum 
+{
+  RADIO_SHIELD_LED = 0
+} Led_t;
+ 
+
+
+/* Exported constants --------------------------------------------------------*/
+
+
+/* Exported macro ------------------------------------------------------------*/
+ /** @addtogroup RF_SHIELD_CONFIG_LOW_LEVEL_LED
+ * @{
+ */
+#define RADIO_SHIELD_LEDn                               ((uint8_t)1)
+
+#define RADIO_SHIELD_LED_GPIO_PIN                      GPIO_PIN_4                         /*Rx Indicator LED*/
+#define RADIO_SHIELD_LED_GPIO_PORT                     GPIOB
+#define RADIO_SHIELD_LED_GPIO_CLK_ENABLE()           __GPIOB_CLK_ENABLE()  
+#define RADIO_SHIELD_LED_GPIO_CLK_DISABLE()          __GPIOB_CLK_DISABLE()
+
+
+/* Exported Variables ------------------------------------------------------------*/
+
+
+/* Exported functions ------------------------------------------------------- */
+void RadioShieldLedInit(Led_t Led);
+void RadioShieldLedOn(Led_t Led);
+void RadioShieldLedOff(Led_t Led);
+void RadioShieldLedToggle(Led_t Led);                 
+                
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RADIO_SHIELD_CONFIG_H */
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+    
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/source/radio_spi.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/source/radio_spi.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,335 @@
+/**
+******************************************************************************
+* @file    radio_spi.c
+* @author  System Lab - NOIDA
+* @version V1.0.0
+* @date    15-May-2014
+* @brief   This file provides code for the configuration of the SPI instances.
+******************************************************************************
+* @attention
+*
+* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice,
+*      this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation
+*      and/or other materials provided with the distribution.
+*   3. Neither the name of STMicroelectronics nor the names of its contributors
+*      may be used to endorse or promote products derived from this software
+*     without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+******************************************************************************
+*/
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "radio_spi.h"
+
+#include "SimpleSpirit1.h"
+
+
+/**
+ * @addtogroup BSP
+ * @{
+ */
+
+
+/**
+ * @addtogroup X-NUCLEO-IDS02Ax
+ * @{
+ */
+
+
+/**
+ * @defgroup RADIO_SPI_Private_TypesDefinitions       RADIO_SPI Private Types Definitions
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup RADIO_SPI_Private_Defines                RADIO_SPI Private Defines
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup RADIO_SPI_Private_Macros                 RADIO_SPI Private Macros
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup RADIO_SPI_Private_Variables              RADIO_SPI Private Variables
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+
+/**
+ * @defgroup RADIO_SPI_Private_FunctionPrototypes     RADIO_SPI Private Function Prototypes
+ * @{
+ */
+
+/**
+ * @}
+ */
+
+/**
+ * @defgroup RADIO_SPI_Private_Functions              RADIO_SPI Private Functions
+ * @{
+ */
+
+/**
+* @}
+*/
+
+/**
+* @brief  Write single or multiple RF Transceivers register
+* @param  cRegAddress: base register's address to be write
+* @param  cNbBytes: number of registers and bytes to be write
+* @param  pcBuffer: pointer to the buffer of values have to be written into registers
+* @retval StatusBytes
+*/
+StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer)
+{
+	return SimpleSpirit1::Instance().SdkEvalSpiWriteRegisters(cRegAddress, cNbBytes, pcBuffer);
+}
+
+StatusBytes SimpleSpirit1::SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer)
+{
+  uint8_t aHeader[2] = {0};
+  uint16_t tmpstatus = 0x0000;
+  StatusBytes *pStatus=(StatusBytes *)&tmpstatus;
+
+  /* Built the aHeader bytes */
+  aHeader[0] = WRITE_HEADER;
+  aHeader[1] = cRegAddress;
+
+  /* Puts the SPI chip select low to start the transaction */
+  chip_sync_select();
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus = _spi.write(aHeader[0]);
+  tmpstatus = tmpstatus << 8;
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus |= _spi.write(aHeader[1]);
+
+  /* Writes the registers according to the number of bytes */
+  for (int index = 0; index < cNbBytes; index++)
+  {
+	  _spi.write(pcBuffer[index]);
+  }
+
+  /* Puts the SPI chip select high to end the transaction */
+  chip_sync_unselect();
+
+  return *pStatus;
+}
+
+
+/**
+* @brief  Read single or multiple SPIRIT1 register
+* @param  cRegAddress: base register's address to be read
+* @param  cNbBytes: number of registers and bytes to be read
+* @param  pcBuffer: pointer to the buffer of registers' values read
+* @retval StatusBytes
+*/
+StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer)
+{
+	return SimpleSpirit1::Instance().SdkEvalSpiReadRegisters(cRegAddress, cNbBytes, pcBuffer);
+}
+
+StatusBytes SimpleSpirit1::SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer)
+{
+  uint16_t tmpstatus = 0x00;
+  StatusBytes *pStatus = (StatusBytes *)&tmpstatus;
+
+  uint8_t aHeader[2] = {0};
+
+  /* Built the aHeader bytes */
+  aHeader[0] = READ_HEADER;
+  aHeader[1] = cRegAddress;
+
+  /* Put the SPI chip select low to start the transaction */
+  chip_sync_select();
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus = _spi.write(aHeader[0]);
+  tmpstatus = tmpstatus << 8;
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus |= _spi.write(aHeader[1]);
+
+  for (int index = 0; index < cNbBytes; index++)
+  {
+	  pcBuffer[index] = _spi.write(0xFF);
+  }
+
+  /* Put the SPI chip select high to end the transaction */
+  chip_sync_unselect();
+
+  return *pStatus;
+}
+
+
+/**
+* @brief  Send a command
+* @param  cCommandCode: command code to be sent
+* @retval StatusBytes
+*/
+StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode)
+{
+	return SimpleSpirit1::Instance().SdkEvalSpiCommandStrobes(cCommandCode);
+}
+
+StatusBytes SimpleSpirit1::SdkEvalSpiCommandStrobes(uint8_t cCommandCode)
+{
+  uint8_t aHeader[2] = {0};
+  uint16_t tmpstatus = 0x0000;
+
+  StatusBytes *pStatus = (StatusBytes *)&tmpstatus;
+
+  /* Built the aHeader bytes */
+  aHeader[0] = COMMAND_HEADER;
+  aHeader[1] = cCommandCode;
+
+  /* Puts the SPI chip select low to start the transaction */
+  chip_sync_select();
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus = _spi.write(aHeader[0]);
+  tmpstatus = tmpstatus<<8;
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus |= _spi.write(aHeader[1]);
+
+  /* Puts the SPI chip select high to end the transaction */
+  chip_sync_unselect();
+
+  return *pStatus;
+}
+
+
+/**
+* @brief  Write data into TX FIFO
+* @param  cNbBytes: number of bytes to be written into TX FIFO
+* @param  pcBuffer: pointer to data to write
+* @retval StatusBytes
+*/
+StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer)
+{
+	return SimpleSpirit1::Instance().SdkEvalSpiWriteFifo(cNbBytes, pcBuffer);
+}
+
+StatusBytes SimpleSpirit1::SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer)
+{
+  uint16_t tmpstatus = 0x0000;
+  StatusBytes *pStatus = (StatusBytes *)&tmpstatus;
+
+  uint8_t aHeader[2] = {0};
+
+  /* Built the aHeader bytes */
+  aHeader[0] = WRITE_HEADER;
+  aHeader[1] = LINEAR_FIFO_ADDRESS;
+
+  /* Put the SPI chip select low to start the transaction */
+  chip_sync_select();
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus = _spi.write(aHeader[0]);
+  tmpstatus = tmpstatus<<8;
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus |= _spi.write(aHeader[1]);
+
+  /* Writes the registers according to the number of bytes */
+  for (int index = 0; index < cNbBytes; index++)
+  {
+	  _spi.write(pcBuffer[index]);
+  }
+
+  /* Put the SPI chip select high to end the transaction */
+  chip_sync_unselect();
+
+  return *pStatus;
+}
+
+/**
+* @brief  Read data from RX FIFO
+* @param  cNbBytes: number of bytes to read from RX FIFO
+* @param  pcBuffer: pointer to data read from RX FIFO
+* @retval StatusBytes
+*/
+StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer)
+{
+	return SimpleSpirit1::Instance().SdkEvalSpiReadFifo(cNbBytes, pcBuffer);
+}
+
+StatusBytes SimpleSpirit1::SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer)
+{
+  uint16_t tmpstatus = 0x0000;
+  StatusBytes *pStatus = (StatusBytes *)&tmpstatus;
+
+  uint8_t aHeader[2];
+
+  /* Built the aHeader bytes */
+  aHeader[0]=READ_HEADER;
+  aHeader[1]=LINEAR_FIFO_ADDRESS;
+
+  /* Put the SPI chip select low to start the transaction */
+  chip_sync_select();
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus = _spi.write(aHeader[0]);
+  tmpstatus = tmpstatus<<8;
+
+  /* Write the aHeader bytes and read the SPIRIT1 status bytes */
+  tmpstatus |= _spi.write(aHeader[1]);
+
+  for (int index = 0; index < cNbBytes; index++)
+  {
+	  pcBuffer[index] = _spi.write(0xFF);
+  }
+
+  /* Put the SPI chip select high to end the transaction */
+  chip_sync_unselect();
+
+  return *pStatus;
+}
+
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/NanostackRfPhySpirit1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/NanostackRfPhySpirit1.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,54 @@
+#ifndef NANOSTACK_RF_PHY_SPIRIT1_H_
+#define NANOSTACK_RF_PHY_SPIRIT1_H_
+
+#include <stdint.h>
+
+#include "NanostackRfPhy.h"
+#include "PinNames.h"
+
+// Arduino pin defaults for convenience
+#if !defined(SPIRIT1_SPI_MOSI)
+#define SPIRIT1_SPI_MOSI   D11
+#endif
+#if !defined(SPIRIT1_SPI_MISO)
+#define SPIRIT1_SPI_MISO   D12
+#endif
+#if !defined(SPIRIT1_SPI_SCLK)
+#define SPIRIT1_SPI_SCLK   D13
+#endif
+#if !defined(SPIRIT1_DEV_IRQ)
+#define SPIRIT1_DEV_IRQ    D9
+#endif
+#if !defined(SPIRIT1_DEV_CS)
+#define SPIRIT1_DEV_CS     D10
+#endif
+#if !defined(SPIRIT1_DEV_SDN)
+#define SPIRIT1_DEV_SDN    D2
+#endif
+#if !defined(SPIRIT1_BRD_LED)
+#define SPIRIT1_BRD_LED    NC
+#endif
+
+class NanostackRfPhySpirit1 : public NanostackRfPhy {
+public:
+    NanostackRfPhySpirit1(PinName spi_mosi, PinName spi_miso, PinName spi_sclk,
+    		PinName dev_irq,  PinName dev_cs, PinName dev_sdn, PinName brd_led);
+    ~NanostackRfPhySpirit1();
+    int8_t rf_register();
+    void rf_unregister();
+    void get_mac_address(uint8_t *mac);
+    void set_mac_address(uint8_t *mac);
+
+private:
+    void rf_init(void);
+
+    const PinName _spi_mosi;
+    const PinName _spi_miso;
+    const PinName _spi_sclk;
+    const PinName _dev_irq;
+    const PinName _dev_cs;
+    const PinName _dev_sdn;
+    const PinName _brd_led;
+};
+
+#endif /* NANOSTACK_RF_PHY_SPIRIT1_H_ */
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/SimpleSpirit1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/SimpleSpirit1.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,467 @@
+/*** Mbed Includes ***/
+#include "mbed.h"
+#include "mbed_debug.h"
+
+
+/*** Cube Includes ***/
+#include "SPIRIT_Radio.h"
+#include "SPIRIT_Management.h"
+#include "SPIRIT_Commands.h"
+#include "MCU_Interface.h"
+
+
+/*** Contiki Lib Includes ***/
+#include "spirit1.h"
+#include "spirit1-config.h"
+#include "spirit1-const.h"
+
+
+// betzw: enable beyond macro if you want debug messages also from IRQ handler
+// #define DEBUG_IRQ
+
+
+/*** Macros from Cube Implementation ***/
+#define CLEAR_TXBUF()			(spirit_tx_len = 0)
+#define IS_RXBUF_EMPTY()        (spirit_rx_len == 0)
+#define CLEAR_RXBUF()			do { 					\
+									spirit_rx_len = 0;	\
+									_spirit_rx_pos = 0; \
+								} while(0)
+
+
+/*** Macros from Cube Implementation ***/
+/* transceiver state. */
+#define ON     0
+#define OFF    1
+
+
+/*** Missing Cube External Declarations ***/
+extern "C" void SpiritManagementSetFrequencyBase(uint32_t);
+
+
+/*** UnlockedSPI for Performance (due to singleton) ***/
+class UnlockedSPI : public SPI {
+public:
+    UnlockedSPI(PinName mosi, PinName miso, PinName sclk) :
+        SPI(mosi, miso, sclk) { }
+    virtual ~UnlockedSPI() {}
+    virtual void lock() { }
+    virtual void unlock() { }
+};
+
+
+/*** A Simple Spirit1 Class ***/
+// NOTE: must be a singleton (due to mix of MBED/CUBE code)!!!
+// NOTE: implementation is IRQ-save but (intentionally) NOT thread-safe!!!
+class SimpleSpirit1 {
+ protected:
+	static SimpleSpirit1 *_singleton;
+
+    /** Communication Interface Instance Variables **/
+	UnlockedSPI _spi; // betzw - NOTE: Morpho/Zio pins are valid only for NUCLEO-F401RE
+              	  	  // mosi: PA_7 (D11)
+					  // miso: PA_6 (D12)
+              	  	  // sclk: PB_3 (D3) or
+              	  	  //       PA_5 (D13) (only in case you unmount R4 & mount R7,
+              	  	  //                  (note: in this case you may not use LED1 on some platforms)
+              	  	  // bits: 8-bit
+              	  	  // mode: 0
+              	  	  // ordr: MSB
+              	  	  // freq: max 10MHz
+    InterruptIn _irq; // PC_7 (D9) (falling)
+    DigitalOut _chip_select; // PB_6 (D10) ('1' == chip unselected)
+    DigitalOut _shut_down; // PA_10 (D2) ('1' == shut_down)
+    DigitalOut _led; // PB_4 (D5) (optional)
+
+    Callback<void(int)> _current_irq_callback;
+    Timeout _rx_receiving_timeout;
+
+    void rx_timeout_handler(void) {
+    	set_ready_state();
+	    cmd_strobe(SPIRIT1_STROBE_RX);
+#ifdef DEBUG_IRQ
+	    debug("\n\r%s (%d)\n\r", __func__, __LINE__);
+#endif
+    }
+
+    void start_rx_timeout(void) {
+    	_rx_receiving_timeout.attach_us(Callback<void()>(this, &SimpleSpirit1::rx_timeout_handler), 100 * 1000); // 100ms
+    }
+
+    void stop_rx_timeout(void) {
+    	_rx_receiving_timeout.detach();
+    }
+
+    /** Static Variables from Cube Implementation **/
+    /*
+     * The buffers which hold incoming data.
+     * The +1 because of the first byte,
+     * which will contain the length of the packet.
+     */
+    volatile uint16_t spirit_tx_len;
+    volatile bool _spirit_tx_started;
+    volatile uint16_t spirit_rx_len;
+    volatile uint16_t _spirit_rx_pos;
+    volatile bool _spirit_rx_err;
+    uint8_t spirit_rx_buf[MAX_PACKET_LEN];
+    volatile bool _is_receiving;
+
+    /** Status Variables from Cube Implementation **/
+    unsigned int spirit_on;
+    uint8_t last_rssi; //MGR
+    uint8_t last_sqi;  //MGR
+
+    /** Low Level Instance Variables **/
+    unsigned int _nr_of_irq_disables;
+
+    /** Low Level Instance Methods **/
+    void disable_spirit_irq(void) {
+    	_irq.disable_irq();
+    	_nr_of_irq_disables++;
+#ifndef NDEBUG
+    	debug_if(_nr_of_irq_disables == 0, "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+    }
+
+    void enable_spirit_irq(void) {
+#ifndef NDEBUG
+    	debug_if(_nr_of_irq_disables == 0, "\n\rassert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+    	if(--_nr_of_irq_disables == 0)
+    		_irq.enable_irq();
+    }
+
+    void chip_select() { _chip_select = 0; }
+    void chip_unselect() { _chip_select = 1; }
+
+    void enter_shutdown() {
+    	_shut_down = 1;
+    	wait_ms(5); // wait 5 milliseconds (to allow Spirit1 to shut down)
+    }
+
+    void exit_shutdown() {
+    	_shut_down = 0;
+    	wait_ms(10); // wait 10 milliseconds (to allow Spirit1 a proper boot-up sequence)
+    }
+
+    void cs_to_sclk_delay(void) {
+    	wait_us(1); // heuristic value
+    }
+
+    /**
+     * @brief      Write and read a buffer to/from the SPI peripheral device at the same time
+     *             in 8-bit data mode using synchronous SPI communication.
+     * @param[in]  pBufferToWrite pointer to the buffer of data to send.
+     * @param[out] pBufferToRead pointer to the buffer to read data into.
+     * @param[in]  NumBytes number of bytes to read and write.
+     * @retval     0 if ok.
+     * @retval     -1 if data format error.
+     * @note       When using the SPI in Interrupt-mode, remember to disable interrupts
+     *             before calling this function and to enable them again after.
+     */
+    void spi_write_read(uint8_t* pBufferToWrite, uint8_t* pBufferToRead, uint16_t NumBytes)
+    {
+        /* Read and write data at the same time. */
+    	for (int i = 0; i < NumBytes; i++) {
+            pBufferToRead[i] = _spi.write(pBufferToWrite[i]);
+    	}
+    }
+
+    /** Radio Instance Methods **/
+    void radio_set_xtal_freq(uint32_t freq) {
+    	SpiritRadioSetXtalFrequency(freq);
+    }
+
+    void radio_set_pa_level_dbm(uint8_t cIndex, float fPowerdBm) {
+    	SpiritRadioSetPALeveldBm(cIndex, fPowerdBm);
+    }
+
+    void radio_set_pa_level_max_index(uint8_t cIndex) {
+    	SpiritRadioSetPALevelMaxIndex(cIndex);
+    }
+
+    uint8_t radio_init(SRadioInit *init_struct) {
+    	return SpiritRadioInit(init_struct);
+    }
+
+    void radio_persistent_rx(SpiritFunctionalState xNewState) {
+    	SpiritRadioPersistenRx(xNewState);
+    }
+
+    void radio_afc_freeze_on_sync(SpiritFunctionalState xNewState) {
+    	SpiritRadioAFCFreezeOnSync(xNewState);
+    }
+
+    /** Packet System Instance Methods **/
+    void pkt_basic_init(PktBasicInit* pxPktBasicInit) {
+    	SpiritPktBasicInit(pxPktBasicInit);
+    }
+
+    void pkt_basic_set_payload_length(uint16_t nPayloadLength) {
+    	SpiritPktBasicSetPayloadLength(nPayloadLength);
+    }
+
+    uint16_t pkt_basic_get_received_pkt_length(void) {
+    	return SpiritPktBasicGetReceivedPktLength();
+    }
+
+	/** IRQ Instance Methods **/
+    void irq_de_init(SpiritIrqs* pxIrqInit) {
+    	SpiritIrqDeInit(pxIrqInit);
+    }
+
+    void irq_clear_status(void) {
+    	SpiritIrqClearStatus();
+    }
+
+    void irq_set_status(IrqList xIrq, SpiritFunctionalState xNewState) {
+    	SpiritIrq(xIrq, xNewState);
+    }
+
+    void irq_get_status(SpiritIrqs* pxIrqStatus) {
+    	SpiritIrqGetStatus(pxIrqStatus);
+    }
+
+    /** Management Instance Methods **/
+    void mgmt_set_freq_base(uint32_t freq) {
+    	SpiritManagementSetFrequencyBase(freq);
+    }
+
+    void mgmt_refresh_status(void) {
+    	SpiritRefreshStatus();
+    }
+
+    /** Spirit GPIO Instance Methods **/
+    void spirit_gpio_init(SGpioInit* pxGpioInitStruct) {
+    	SpiritGpioInit(pxGpioInitStruct);
+    }
+
+	/** Qi Instance Methods **/
+    void qi_set_sqi_threshold(SqiThreshold xSqiThr) {
+    	SpiritQiSetSqiThreshold(xSqiThr);
+    }
+
+    void qi_sqi_check(SpiritFunctionalState xNewState) {
+    	SpiritQiSqiCheck(xNewState);
+    }
+
+    void qi_set_rssi_threshold_dbm(int nDbmValue) {
+    	SpiritQiSetRssiThresholddBm(nDbmValue);
+    }
+
+    float qi_get_rssi_dbm() {
+    	last_rssi = qi_get_rssi();
+    	return get_last_rssi_dbm();
+    }
+
+    uint8_t qi_get_rssi() {
+    	return SpiritQiGetRssi();
+    }
+
+    uint8_t qi_get_sqi() {
+    	return SpiritQiGetSqi();
+    }
+
+    /** Timer Instance Methods **/
+    void timer_set_rx_timeout_stop_condition(RxTimeoutStopCondition xStopCondition) {
+    	SpiritTimerSetRxTimeoutStopCondition(xStopCondition);
+    }
+
+    void timer_set_rx_timeout_counter(uint8_t cCounter) {
+    	SpiritTimerSetRxTimeoutCounter(cCounter);
+    }
+
+    void timer_set_infinite_rx_timeout(void) {
+    	timer_set_rx_timeout_counter(0);
+    }
+
+    /** CSMA/CA Instance Methods **/
+    void csma_ca_state(SpiritFunctionalState xNewState) {
+    	SpiritCsma(xNewState);
+    }
+
+    void csma_ca_init(CsmaInit* pxCsmaInit) {
+    	csma_ca_state(S_DISABLE); // Disabled at init
+    	SpiritCsmaInit(pxCsmaInit);
+    	SpiritCsmaSeedReloadMode(S_DISABLE); // always disable seed reload
+    }
+
+    /** Command Instance Methods**/
+    void cmd_strobe(uint8_t cmd) {
+    	SpiritCmdStrobeCommand((SpiritCmd)cmd);
+    }
+
+    void cmd_strobe_flush_rx_fifo() {
+    	SpiritCmdStrobeCommand(CMD_FLUSHRXFIFO);
+    }
+
+    /** SPI Instance Methods **/
+    StatusBytes spi_write_linear_fifo(uint8_t cNbBytes, uint8_t* pcBuffer) {
+    	return SdkEvalSpiWriteFifo(cNbBytes, pcBuffer);
+    }
+
+    StatusBytes spi_read_linear_fifo(uint8_t cNbBytes, uint8_t* pcBuffer) {
+    	return SdkEvalSpiReadFifo(cNbBytes, pcBuffer);
+    }
+
+    /** Linear FIFO Instance Methods **/
+    uint8_t linear_fifo_read_num_elements_rx_fifo(void) {
+    	return SpiritLinearFifoReadNumElementsRxFifo();
+    }
+
+    uint8_t linear_fifo_read_num_elements_tx_fifo(void) {
+    	return SpiritLinearFifoReadNumElementsTxFifo();
+    }
+
+    void linear_fifo_set_almost_full_thr_rx(uint8_t cThrRxFifo) {
+    	SpiritLinearFifoSetAlmostFullThresholdRx(cThrRxFifo);
+    }
+
+    /** Calibration Instance Methods **/
+    void calibration_rco(SpiritFunctionalState xNewState) {
+    	SpiritCalibrationRco(xNewState);
+    }
+
+    /** Internal Spirit Methods */
+    void set_ready_state(void);
+    uint8_t refresh_state(void);
+
+    /** Friend Functions **/
+    friend StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
+    friend StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
+    friend StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode);
+    friend StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
+    friend StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
+
+    /** Sdk Instance Methods **/
+    StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
+    StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
+    StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode);
+    StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
+    StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
+
+    /** Helper Instance Methods **/
+    void chip_sync_select() {
+    	disable_spirit_irq();
+    	chip_select();
+    	cs_to_sclk_delay();
+    }
+
+    void chip_sync_unselect() {
+    	chip_unselect();
+    	enable_spirit_irq();
+    }
+
+    /** Init Instance Method **/
+    void init();
+
+    /** Spirit Irq Callback */
+    void IrqHandler();
+
+    /** Constructor **/
+    SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
+		  PinName irq, PinName cs, PinName sdn,
+		  PinName led);
+
+    /** Destructor **/
+    ~SimpleSpirit1(void); // should never be called!
+
+public:
+    enum {
+    	RX_DONE,
+    	TX_DONE,
+		TX_ERR
+    };
+
+    static SimpleSpirit1& CreateInstance(PinName mosi, PinName miso, PinName sclk,
+    		PinName irq, PinName cs, PinName sdn,
+			PinName led = NC) {
+
+    	if(_singleton == NULL) {
+    		_singleton = new SimpleSpirit1(mosi, miso, sclk,
+    				irq, cs, sdn, led);
+    		_singleton->init();
+    	} else {
+    		error("SimpleSpirit1 singleton already created!\n");
+    	}
+
+    	return *_singleton;
+    }
+
+    static SimpleSpirit1& Instance() {
+    	if(_singleton == NULL) {
+    		error("SimpleSpirit1 must be created before used!\n");
+    	}
+
+    	return *_singleton;
+    }
+
+    /** Attach a function to be called by the Spirit Irq handler when packet has arrived
+     *
+     *  @param func A void() callback, or 0 to set as none
+     *
+     *  @note  Function 'func' will be executed in interrupt context!
+     */
+    void attach_irq_callback(Callback<void(int)> func) {
+    	_current_irq_callback = func;
+    }
+
+    /** Switch Radio On/Off **/
+    int on(void);
+    int off(void);
+
+    /** Set Channel **/
+    void set_channel(uint8_t channel) {
+    	SpiritRadioSetChannel(channel);
+    }
+
+    /** Send a Buffer **/
+    int send(const void *payload, unsigned int payload_len);
+
+    /** Read into Buffer **/
+    int read(void *buf, unsigned int bufsize);
+
+    /** Perform a Clear-Channel Assessment (CCA) to find out if there is
+        a packet in the air or not.
+        Returns 1 if packet has been seen.
+      */
+    int channel_clear(void);
+
+    /** Check if the radio driver has just received a packet **/
+    int get_pending_packet(void);
+
+    /** Is radio currently receiving **/
+    bool is_receiving(void) {
+    	return _is_receiving;
+    }
+
+    /** Get latest value of RSSI (in dBm) **/
+    float get_last_rssi_dbm(void) {
+    	get_last_rssi_raw();
+		return (-120.0+((float)(last_rssi-20))/2);
+    }
+
+    /** Get latest value of RSSI (as Spirit1 raw value) **/
+    uint8_t get_last_rssi_raw(void) {
+    	if(last_rssi == 0) {
+    		last_rssi = qi_get_rssi();
+    	}
+    	return last_rssi;
+    }
+
+    /** Get latest value of LQI (scaled to 8-bit) **/
+    uint8_t get_last_sqi(void) {
+    	const uint8_t max_sqi = 8 * ((SYNC_LENGTH>>1)+1);
+    	if(last_sqi == 0) {
+    		last_sqi = qi_get_sqi();
+    	}
+    	if(last_sqi > max_sqi) last_sqi = max_sqi;
+
+    	return (last_sqi * 255 / max_sqi);
+    }
+
+    /** Reset Board **/
+    void reset_board() {
+    	init();
+    }
+};
diff -r 000000000000 -r a1734fe1ec4b easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/radio_spi.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/radio_spi.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,185 @@
+/**
+******************************************************************************
+* @file    radio_spi.h
+* @author  System Lab - NOIDA
+* @version V1.0.0
+* @date    15-May-2014
+* @brief   This file contains all the functions prototypes for SPI .
+******************************************************************************
+* @attention
+*
+* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
+*
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+*   1. Redistributions of source code must retain the above copyright notice,
+*      this list of conditions and the following disclaimer.
+*   2. Redistributions in binary form must reproduce the above copyright notice,
+*      this list of conditions and the following disclaimer in the documentation
+*      and/or other materials provided with the distribution.
+*   3. Neither the name of STMicroelectronics nor the names of its contributors
+*      may be used to endorse or promote products derived from this software
+*      without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+******************************************************************************
+*/
+
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __RADIO_SPI_H
+#define __RADIO_SPI_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+  
+/* Includes ------------------------------------------------------------------*/
+#ifdef USE_STM32L1XX_NUCLEO
+// #include "stm32l1xx_hal.h"
+#endif
+
+#ifdef USE_STM32F4XX_NUCLEO
+// #include "stm32f4xx_hal.h"
+#endif
+#include "SPIRIT_Config.h"
+#include "radio_spi.h" 
+// #include "spirit1-arch.h"
+
+/**
+ * @addtogroup BSP
+ * @{
+ */ 
+  
+/* Exported types ------------------------------------------------------------*/
+
+  
+/* Exported constants --------------------------------------------------------*/
+  
+  
+/* Exported macro ------------------------------------------------------------*/
+  /* Define for SPIRIT1 board  */  
+ #if !defined (USE_SPIRIT1_DEFAULT)
+ #define USE_SPIRIT1_DEFAULT
+#endif
+  
+/* SPIRIT1_Spi_config */ 
+/* SPI1 */  
+#define RADIO_SPI                                 SPI1
+#define RADIO_SPI_CLK_ENABLE()                  __SPI1_CLK_ENABLE()
+#define RADIO_SPI_CLK_DISABLE()                 __SPI1_CLK_DISABLE()
+
+#define RADIO_SPI_MISO_PORT                      GPIOA
+#define RADIO_SPI_MISO_PIN                       GPIO_PIN_6
+#define RADIO_SPI_MISO_CLOCK_ENABLE()            __GPIOA_CLK_ENABLE()
+#define RADIO_SPI_MISO_CLOCK_DISABLE()           __GPIOA_CLK_DISABLE() 
+  
+#define RADIO_SPI_MOSI_PORT                      GPIOA
+#define RADIO_SPI_MOSI_PIN                       GPIO_PIN_7
+#define RADIO_SPI_MOSI_CLOCK_ENABLE()            __GPIOA_CLK_ENABLE()
+#define RADIO_SPI_MOSI_CLOCK_DISABLE()           __GPIOA_CLK_DISABLE()   
+  
+ 
+ 
+#ifdef USE_SPIRIT1_DEFAULT    
+
+#define RADIO_SPI_SCK_PORT                      GPIOB
+#define RADIO_SPI_SCK_PIN                       GPIO_PIN_3
+#define RADIO_SPI_SCK_CLOCK_ENABLE()            __GPIOB_CLK_ENABLE()
+#define RADIO_SPI_SCK_CLOCK_DISABLE()           __GPIOB_CLK_DISABLE()
+
+  
+#define RADIO_SPI_CS_PORT                        GPIOB
+#define RADIO_SPI_CS_PIN                         GPIO_PIN_6
+#define RADIO_SPI_CS_CLOCK_ENABLE()            __GPIOB_CLK_ENABLE()
+#define RADIO_SPI_CS_CLOCK_DISABLE()           __GPIOB_CLK_DISABLE()
+ 
+#else 
+ 
+#define RADIO_SPI_SCK_PORT                      GPIOB
+#define RADIO_SPI_SCK_PIN                       GPIO_PIN_3
+#define RADIO_SPI_SCK_CLOCK_ENABLE()            __GPIOB_CLK_ENABLE()
+#define RADIO_SPI_SCK_CLOCK_DISABLE()           __GPIOB_CLK_DISABLE()
+
+  
+#define RADIO_SPI_CS_PORT                        GPIOB
+#define RADIO_SPI_CS_PIN                         GPIO_PIN_6
+#define RADIO_SPI_CS_CLOCK_ENABLE()            __GPIOB_CLK_ENABLE()
+#define RADIO_SPI_CS_CLOCK_DISABLE()           __GPIOB_CLK_DISABLE()
+    
+#endif  
+  
+/* Maximum Timeout values for flags waiting loops. These timeouts are not based
+   on accurate values, they just guarantee that the application will not remain
+   stuck if the SPI communication is corrupted.
+   You may modify these timeout values depending on CPU frequency and application
+   conditions (interrupts routines ...) */    
+#define RADIO_SPI_TIMEOUT_MAX                   ((uint32_t)1000)
+
+/* SPIRIT1_Spi_config_Private_Defines */  
+#define CS_TO_SCLK_DELAY     0x0200//FIXME what is this doing?
+#define CLK_TO_CS_DELAY      0x0001
+  
+/* SPIRIT1_Spi_config_Headers */
+#define HEADER_WRITE_MASK     0x00                                /*!< Write mask for header byte*/
+#define HEADER_READ_MASK      0x01                                /*!< Read mask for header byte*/
+#define HEADER_ADDRESS_MASK   0x00                                /*!< Address mask for header byte*/
+#define HEADER_COMMAND_MASK   0x80                                /*!< Command mask for header byte*/
+  
+#define LINEAR_FIFO_ADDRESS 0xFF                                  /*!< Linear FIFO address*/
+  
+/* SPIRIT1_Spi_config_Private_FunctionPrototypes */
+#define SPI_ENTER_CRITICAL()         IRQ_DISABLE()
+#define SPI_EXIT_CRITICAL()          IRQ_ENABLE()
+  
+/* SPIRIT1_Spi_config_Private_Functions */
+#define RadioSpiCSLow()        HAL_GPIO_WritePin(RADIO_SPI_CS_PORT, RADIO_SPI_CS_PIN, GPIO_PIN_RESET)
+#define RadioSpiCSHigh()       HAL_GPIO_WritePin(RADIO_SPI_CS_PORT, RADIO_SPI_CS_PIN, GPIO_PIN_SET)
+  
+/* SPIRIT1_Spi_config_Private_Macros */
+#define BUILT_HEADER(add_comm, w_r) (add_comm | w_r)                             /*!< macro to build the header byte*/
+#define WRITE_HEADER        BUILT_HEADER(HEADER_ADDRESS_MASK, HEADER_WRITE_MASK) /*!< macro to build the write 
+                                                                                                         header byte*/
+#define READ_HEADER         BUILT_HEADER(HEADER_ADDRESS_MASK, HEADER_READ_MASK)  /*!< macro to build the read 
+                                                                                                         header byte*/
+#define COMMAND_HEADER      BUILT_HEADER(HEADER_COMMAND_MASK, HEADER_WRITE_MASK) /*!< macro to build the command 
+                                                                                                         header byte*/
+  
+  
+  
+/* Exported Variables --------------------------------------------------------*/
+  
+  
+/* Exported functions ------------------------------------------------------- */ 
+void SdkEvalSpiInit(void);
+// void SpiCSGpioSetLevel(GPIO_PinState xState);
+StatusBytes SdkEvalSpiWriteRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
+StatusBytes SdkEvalSpiReadRegisters(uint8_t cRegAddress, uint8_t cNbBytes, uint8_t* pcBuffer);
+StatusBytes SdkEvalSpiCommandStrobes(uint8_t cCommandCode);
+StatusBytes SdkEvalSpiWriteFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
+StatusBytes SdkEvalSpiReadFifo(uint8_t cNbBytes, uint8_t* pcBuffer);
+
+  
+#ifdef __cplusplus
+}
+#endif
+#endif /*__RADIO_SPI_H */
+
+/**
+* @}
+*/
+
+/**
+* @}
+*/
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff -r 000000000000 -r a1734fe1ec4b jsmn/LICENSE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/LICENSE	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,20 @@
+Copyright (c) 2010 Serge A. Zaitsev
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff -r 000000000000 -r a1734fe1ec4b jsmn/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,167 @@
+
+JSMN
+====
+
+jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C.  It can be
+easily integrated into resource-limited or embedded projects.
+
+You can find more information about JSON format at [json.org][1]
+
+Library sources are available at https://github.com/zserge/jsmn
+
+The web page with some information about jsmn can be found at
+[http://zserge.com/jsmn.html][2]
+
+Philosophy
+----------
+
+Most JSON parsers offer you a bunch of functions to load JSON data, parse it
+and extract any value by its name. jsmn proves that checking the correctness of
+every JSON packet or allocating temporary objects to store parsed JSON fields
+often is an overkill. 
+
+JSON format itself is extremely simple, so why should we complicate it?
+
+jsmn is designed to be	**robust** (it should work fine even with erroneous
+data), **fast** (it should parse data on the fly), **portable** (no superfluous
+dependencies or non-standard C extensions). And of course, **simplicity** is a
+key feature - simple code style, simple algorithm, simple integration into
+other projects.
+
+Features
+--------
+
+* compatible with C89
+* no dependencies (even libc!)
+* highly portable (tested on x86/amd64, ARM, AVR)
+* about 200 lines of code
+* extremely small code footprint
+* API contains only 2 functions
+* no dynamic memory allocation
+* incremental single-pass parsing
+* library code is covered with unit-tests
+
+Design
+------
+
+The rudimentary jsmn object is a **token**. Let's consider a JSON string:
+
+	'{ "name" : "Jack", "age" : 27 }'
+
+It holds the following tokens:
+
+* Object: `{ "name" : "Jack", "age" : 27}` (the whole object)
+* Strings: `"name"`, `"Jack"`, `"age"` (keys and some values)
+* Number: `27`
+
+In jsmn, tokens do not hold any data, but point to token boundaries in JSON
+string instead. In the example above jsmn will create tokens like: Object
+[0..31], String [3..7], String [12..16], String [20..23], Number [27..29].
+
+Every jsmn token has a type, which indicates the type of corresponding JSON
+token. jsmn supports the following token types:
+
+* Object - a container of key-value pairs, e.g.:
+	`{ "foo":"bar", "x":0.3 }`
+* Array - a sequence of values, e.g.:
+	`[ 1, 2, 3 ]`
+* String - a quoted sequence of chars, e.g.: `"foo"`
+* Primitive - a number, a boolean (`true`, `false`) or `null`
+
+Besides start/end positions, jsmn tokens for complex types (like arrays
+or objects) also contain a number of child items, so you can easily follow
+object hierarchy.
+
+This approach provides enough information for parsing any JSON data and makes
+it possible to use zero-copy techniques.
+
+Install
+-------
+
+To clone the repository you should have Git installed. Just run:
+
+	$ git clone https://github.com/zserge/jsmn
+
+Repository layout is simple: jsmn.c and jsmn.h are library files, tests are in
+the jsmn\_test.c, you will also find README, LICENSE and Makefile files inside.
+
+To build the library, run `make`. It is also recommended to run `make test`.
+Let me know, if some tests fail.
+
+If build was successful, you should get a `libjsmn.a` library.
+The header file you should include is called `"jsmn.h"`.
+
+API
+---
+
+Token types are described by `jsmntype_t`:
+
+	typedef enum {
+		JSMN_UNDEFINED = 0,
+		JSMN_OBJECT = 1,
+		JSMN_ARRAY = 2,
+		JSMN_STRING = 3,
+		JSMN_PRIMITIVE = 4
+	} jsmntype_t;
+
+**Note:** Unlike JSON data types, primitive tokens are not divided into
+numbers, booleans and null, because one can easily tell the type using the
+first character:
+
+* <code>'t', 'f'</code> - boolean 
+* <code>'n'</code> - null
+* <code>'-', '0'..'9'</code> - number
+
+Token is an object of `jsmntok_t` type:
+
+	typedef struct {
+		jsmntype_t type; // Token type
+		int start;       // Token start position
+		int end;         // Token end position
+		int size;        // Number of child (nested) tokens
+	} jsmntok_t;
+
+**Note:** string tokens point to the first character after
+the opening quote and the previous symbol before final quote. This was made 
+to simplify string extraction from JSON data.
+
+All job is done by `jsmn_parser` object. You can initialize a new parser using:
+
+	jsmn_parser parser;
+	jsmntok_t tokens[10];
+
+	jsmn_init(&parser);
+
+	// js - pointer to JSON string
+	// tokens - an array of tokens available
+	// 10 - number of tokens available
+	jsmn_parse(&parser, js, strlen(js), tokens, 10);
+
+This will create a parser, and then it tries to parse up to 10 JSON tokens from
+the `js` string.
+
+A non-negative return value of `jsmn_parse` is the number of tokens actually
+used by the parser.
+Passing NULL instead of the tokens array would not store parsing results, but
+instead the function will return the value of tokens needed to parse the given
+string. This can be useful if you don't know yet how many tokens to allocate.
+
+If something goes wrong, you will get an error. Error will be one of these:
+
+* `JSMN_ERROR_INVAL` - bad token, JSON string is corrupted
+* `JSMN_ERROR_NOMEM` - not enough tokens, JSON string is too large
+* `JSMN_ERROR_PART` - JSON string is too short, expecting more JSON data
+
+If you get `JSON_ERROR_NOMEM`, you can re-allocate more tokens and call
+`jsmn_parse` once more.  If you read json data from the stream, you can
+periodically call `jsmn_parse` and check if return value is `JSON_ERROR_PART`.
+You will get this error until you reach the end of JSON data.
+
+Other info
+----------
+
+This software is distributed under [MIT license](http://www.opensource.org/licenses/mit-license.php),
+ so feel free to integrate it in your commercial products.
+
+[1]: http://www.json.org/
+[2]: http://zserge.com/jsmn.html
diff -r 000000000000 -r a1734fe1ec4b jsmn/RadioCfg.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/RadioCfg.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,157 @@
+#include "RadioCfg.h"
+#include <string.h>
+#include <stdlib.h>
+
+static char tempstr[100];
+
+static int jsoneq(const char * json, jsmntok_t * tok, const char * s)
+{
+    if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
+        strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
+            return 0;
+    }
+    return -1;    
+}
+
+int parseradioconfig(const char * jsonstring, RadioCfg & radiocfg)
+{
+    int i, r;
+    
+    jsmn_parser p;
+    jsmntok_t t[128];
+    
+    jsmn_init(&p);
+    r = jsmn_parse(&p, jsonstring, strlen(jsonstring), t, sizeof(t)/sizeof(t[0]));
+    if ( r < 0 )
+        return -1;
+    
+    /* Top level element is an object */
+    if (r < 1 || t[0].type != JSMN_OBJECT)
+    {
+        return -1;
+    }
+    
+    /* Loop over all tokens */
+    for (i = 1; i < r; i++)
+    {
+        if (jsoneq(jsonstring, &t[i], "error") == 0)
+        {
+            // Query returned an error ...
+            return -1;
+        }
+        else if (jsoneq(jsonstring, &t[i], "id") == 0)
+        {
+            memset(&tempstr[0], 0, sizeof(tempstr));
+            strncpy(&tempstr[0], jsonstring + t[i+1].start, (t[i+1].end - t[i+1].start));  
+            // Store the radio id ...
+            radiocfg.radioID = strtoull(tempstr, NULL, 0);
+            i++;
+        }
+        else if (jsoneq(jsonstring, &t[i], "name") == 0)
+        {
+            memset(&radiocfg.name[0], 0, RADIO_NAME_LEN);
+            strncpy(&radiocfg.name[0], jsonstring + t[i+1].start, (t[i+1].end - t[i+1].start));
+            i++;
+        }
+        else if (jsoneq(jsonstring, &t[i], "country") == 0)
+        {
+            memset(&radiocfg.country[0], 0, RADIO_NAME_LEN);
+            strncpy(&radiocfg.country[0], jsonstring + t[i+1].start, (t[i+1].end - t[i+1].start));
+            i++;
+        }
+        else if (jsoneq(jsonstring, &t[i], "utc_offset") == 0)
+        {
+            memset(&tempstr[0], 0, sizeof(tempstr));
+            strncpy(&tempstr[0], jsonstring + t[i+1].start, (t[i+1].end - t[i+1].start));  
+            // Store the radio id ...
+            radiocfg.utc_offset = strtoul(&tempstr[0], NULL, 0);            
+            i++;
+        }                
+        else if (jsoneq(jsonstring, &t[i], "radios") == 0)
+        {
+            int j;
+            // Radios is an array of radio objects
+            if (t[i+1].type != JSMN_ARRAY){
+                continue;
+            }
+            
+            int arrsize = t[i+1].size;
+            // Move to the start of the array
+            i += 2;
+            for (j = 0; j < arrsize; j++)
+            {
+                RadioSlave slv;                
+                int r = t[i + j].size;
+                //jsmntok_t * g = &t[i + j];                
+                //printf(" * %.*s\n", g->end - g->start, jsonstring + g->start);
+                // Enumerate objects within the array
+                for (int z = 0; z < r ; z++)
+                {
+
+                    if (jsoneq(jsonstring, &t[i+j+(z*2)+1], "id") == 0)
+                    {
+                        jsmntok_t * o = &t[i+j+(z*2)+2];
+                        memset(&tempstr[0], 0, sizeof(tempstr));
+                        strncpy(&tempstr[0], jsonstring + o->start, o->end - o->start);
+                        slv.radioID = strtoull(&tempstr[0], NULL, 0);
+                    }
+                    else if (jsoneq(jsonstring, &t[i+j+(z*2)+1], "name") == 0)
+                    {
+                        jsmntok_t * o = &t[i+j+(z*2)+2];
+                        memset(&slv.name[0], 0, RADIO_NAME_LEN);
+                        strncpy(&slv.name[0], jsonstring + o->start, o->end - o->start);
+                    }
+                    if (jsoneq(jsonstring, &t[i+j+(z*2)+1], "temp_pin") == 0)
+                    {
+                        jsmntok_t * o = &t[i+j+(z*2)+2];
+                        memset(&tempstr[0], 0, sizeof(tempstr));
+                        strncpy(&tempstr[0], jsonstring + o->start, o->end - o->start);
+                        slv.temp_pin = strtoul(&tempstr[0], NULL, 0);
+                    }
+                    if (jsoneq(jsonstring, &t[i+j+(z*2)+1], "humid_pin") == 0)
+                    {
+                        jsmntok_t * o = &t[i+j+(z*2)+2];
+                        memset(&tempstr[0], 0, sizeof(tempstr));
+                        strncpy(&tempstr[0], jsonstring + o->start, o->end - o->start);
+                        slv.humid_pin = strtoul(&tempstr[0], NULL, 0);
+                    }
+                    if (jsoneq(jsonstring, &t[i+j+(z*2)+1], "lumin_pin") == 0)
+                    {
+                        jsmntok_t * o = &t[i+j+(z*2)+2];
+                        memset(&tempstr[0], 0, sizeof(tempstr));
+                        strncpy(&tempstr[0], jsonstring + o->start, o->end - o->start);
+                        slv.lumin_pin = strtoul(&tempstr[0], NULL, 0);
+                    }                
+                    if (jsoneq(jsonstring, &t[i+j+(z*2)+1], "spinkler_pin") == 0)
+                    {
+                        jsmntok_t * o = &t[i+j+(z*2)+2];
+                        memset(&tempstr[0], 0, sizeof(tempstr));
+                        strncpy(&tempstr[0], jsonstring + o->start, o->end - o->start);                                
+                        slv.sprinkler_pin = strtoul(&tempstr[0], NULL, 0);
+                    }     
+                    if (jsoneq(jsonstring, &t[i+j+(z*2)+1], "hthreshold") == 0)
+                    {
+                        jsmntok_t * o = &t[i+j+(z*2)+2];
+                        memset(&tempstr[0], 0, sizeof(tempstr));
+                        strncpy(&tempstr[0], jsonstring + o->start, o->end - o->start);                                
+                        slv.hthreshold = strtoul(&tempstr[0], NULL, 0);
+                    }                                             
+                    else
+                    {
+                        // TODO:
+                    }
+                }
+                // Add the radio slave to the vector                
+                radiocfg.radios.push_back(slv);                
+                i += (t[i+j].size) * 2;
+            }
+            // Move to the end of the object
+            i += 4;
+        }else
+        {
+            
+        }
+    }
+    
+    return 0;    
+}
diff -r 000000000000 -r a1734fe1ec4b jsmn/RadioCfg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/RadioCfg.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,79 @@
+#ifndef _RADIO_CONFIG_H_
+#define _RADIO_CONFIG_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vector>
+#include "stdint.h"
+#include "jsmn.h"
+
+#define RADIO_NAME_LEN 100
+struct RadioSlave
+{
+    uint64_t radioID;
+    char name[RADIO_NAME_LEN];
+    
+    uint16_t temp_pin;
+    uint16_t humid_pin;
+    uint16_t lumin_pin;
+    uint16_t sprinkler_pin;    
+    uint16_t hthreshold;
+    
+    RadioSlave()
+        :radioID(0),
+        temp_pin(0),
+        humid_pin(0),
+        lumin_pin(0),
+        sprinkler_pin(0),
+        hthreshold(0)
+    {
+        memset(&name[0], 0, RADIO_NAME_LEN);
+    }   
+    void debug()
+    {
+        printf("Slave ID : %lld\r\n", radioID);
+        printf("Name : \"%s\"\r\n", &name[0]);
+        printf("Temperature Pin: %d\r\n", temp_pin);
+        printf("Humidity Pin: %d\r\n", humid_pin);
+        printf("Luminance Pin: %d\r\n", lumin_pin);
+        printf("Sprinkler Pin: %d\r\n", sprinkler_pin);
+        printf("Humidity Threshold: %d\r\n", hthreshold);
+    }
+};
+
+struct RadioCfg
+{
+    uint64_t    radioID;
+    char name[RADIO_NAME_LEN];
+    char country[RADIO_NAME_LEN];
+    uint32_t utc_offset;    
+    std::vector<RadioSlave> radios;
+    
+    RadioCfg()
+        :radioID(0),
+        utc_offset(0)
+    {
+        memset(&name[0], 0, RADIO_NAME_LEN);
+        memset(&country[0], 0, RADIO_NAME_LEN);
+        radios.clear();
+    }
+       
+    inline void debug()
+    {
+        printf("Radio ID: %lld\r\n", radioID);
+        printf("Name : \"%s\"\r\n", &name[0]);
+        printf("Country : \"%s\"\r\n", &country[0]);
+        printf("UTC Offset: %d\r\n", utc_offset);        
+        std::vector<RadioSlave>::iterator it;
+        for(it = radios.begin(); it != radios.end(); it++)
+        {
+            (*it).debug();
+        }
+    }
+    
+};
+
+int parseradioconfig(const char * jsonstring, RadioCfg &);
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b jsmn/WeatherInfo.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/WeatherInfo.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,63 @@
+#include "WeatherInfo.h"
+#include <string.h>
+#include <stdlib.h>
+
+static int jsoneq(const char * json, jsmntok_t * tok, const char * s)
+{
+    if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
+        strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
+            return 0;
+    }
+    return -1;    
+}
+
+int parseweatherinfo(const char * weather, WeatherInfo & winfo)
+{
+    // Parse weather information
+    jsmn_parser p;
+    jsmntok_t t[128];
+
+    jsmn_init(&p);
+    int r = jsmn_parse(&p, weather, strlen(weather), t, sizeof(t)/sizeof(t[0]));
+    // Top level must be an object
+    if ((r > 0) && (t[0].type == JSMN_OBJECT)) 
+    { 
+        /* Loop over all keys of the root object */
+        for (int i = 1; i < r; i++)
+        {
+            if (jsoneq(weather, &t[i], "description") == 0)
+            {
+                winfo.weather = std::string((const char *)(weather + t[i+1].start), (size_t) t[i+1].end - t[i+1].start);
+                i++;
+            }
+            else if (jsoneq(weather, &t[i], "icon") == 0)
+            {
+                winfo.icon = std::string((const char *)(weather + t[i+1].start), (size_t) t[i+1].end - t[i+1].start);
+                i++;
+            }
+            else if (jsoneq(weather, &t[i], "temp") == 0)
+            {
+                std::string tempstr((const char *)(weather + t[i+1].start), (size_t) t[i+1].end - t[i+1].start);
+                winfo.temperature = strtod(tempstr.c_str(), NULL);
+                i++;
+            }
+            else if (jsoneq(weather, &t[i], "humidity") == 0)
+            {
+                std::string humidstr((const char *)(weather + t[i+1].start), (size_t) t[i+1].end - t[i+1].start);
+                winfo.humidity = strtod(humidstr.c_str(), NULL);
+                i++;
+            }            
+            else if (jsoneq(weather, &t[i], "pressure") == 0)
+            {
+                std::string pressurestr((const char *)(weather + t[i+1].start), (size_t) t[i+1].end - t[i+1].start);
+                winfo.pressure = strtod(pressurestr.c_str(), NULL);
+                i++;
+            }else
+            {
+                // discard the rest of the tokens
+            }
+        }
+        return 0;
+    }else
+        return -1;
+}
diff -r 000000000000 -r a1734fe1ec4b jsmn/WeatherInfo.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/WeatherInfo.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,19 @@
+#ifndef _WEATHER_INFO_H_
+#define _WEATHER_INFO_H_
+
+#include "jsmn.h"
+#include <string>
+
+typedef struct {
+    
+    std::string weather;
+    std::string icon;
+    
+    float temperature;
+    float pressure;
+    float humidity;    
+} WeatherInfo, *pWeatherInfo;
+
+int parseweatherinfo(const char * jsonstring, WeatherInfo &);
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b jsmn/jsmn.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/jsmn.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,314 @@
+#include "jsmn.h"
+
+/**
+ * Allocates a fresh unused token from the token pull.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+		jsmntok_t *tokens, size_t num_tokens) {
+	jsmntok_t *tok;
+	if (parser->toknext >= num_tokens) {
+		return NULL;
+	}
+	tok = &tokens[parser->toknext++];
+	tok->start = tok->end = -1;
+	tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+	tok->parent = -1;
+#endif
+	return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+                            int start, int end) {
+	token->type = type;
+	token->start = start;
+	token->end = end;
+	token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+		size_t len, jsmntok_t *tokens, size_t num_tokens) {
+	jsmntok_t *token;
+	int start;
+
+	start = parser->pos;
+
+	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+		switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+			/* In strict mode primitive must be followed by "," or "}" or "]" */
+			case ':':
+#endif
+			case '\t' : case '\r' : case '\n' : case ' ' :
+			case ','  : case ']'  : case '}' :
+				goto found;
+		}
+		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+			parser->pos = start;
+			return JSMN_ERROR_INVAL;
+		}
+	}
+#ifdef JSMN_STRICT
+	/* In strict mode primitive must be followed by a comma/object/array */
+	parser->pos = start;
+	return JSMN_ERROR_PART;
+#endif
+
+found:
+	if (tokens == NULL) {
+		parser->pos--;
+		return 0;
+	}
+	token = jsmn_alloc_token(parser, tokens, num_tokens);
+	if (token == NULL) {
+		parser->pos = start;
+		return JSMN_ERROR_NOMEM;
+	}
+	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+	token->parent = parser->toksuper;
+#endif
+	parser->pos--;
+	return 0;
+}
+
+/**
+ * Fills next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+		size_t len, jsmntok_t *tokens, size_t num_tokens) {
+	jsmntok_t *token;
+
+	int start = parser->pos;
+
+	parser->pos++;
+
+	/* Skip starting quote */
+	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+		char c = js[parser->pos];
+
+		/* Quote: end of string */
+		if (c == '\"') {
+			if (tokens == NULL) {
+				return 0;
+			}
+			token = jsmn_alloc_token(parser, tokens, num_tokens);
+			if (token == NULL) {
+				parser->pos = start;
+				return JSMN_ERROR_NOMEM;
+			}
+			jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+			token->parent = parser->toksuper;
+#endif
+			return 0;
+		}
+
+		/* Backslash: Quoted symbol expected */
+		if (c == '\\' && parser->pos + 1 < len) {
+			int i;
+			parser->pos++;
+			switch (js[parser->pos]) {
+				/* Allowed escaped symbols */
+				case '\"': case '/' : case '\\' : case 'b' :
+				case 'f' : case 'r' : case 'n'  : case 't' :
+					break;
+				/* Allows escaped symbol \uXXXX */
+				case 'u':
+					parser->pos++;
+					for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
+						/* If it isn't a hex character we have an error */
+						if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+									(js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+									(js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+							parser->pos = start;
+							return JSMN_ERROR_INVAL;
+						}
+						parser->pos++;
+					}
+					parser->pos--;
+					break;
+				/* Unexpected symbol */
+				default:
+					parser->pos = start;
+					return JSMN_ERROR_INVAL;
+			}
+		}
+	}
+	parser->pos = start;
+	return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+		jsmntok_t *tokens, unsigned int num_tokens) {
+	int r;
+	int i;
+	jsmntok_t *token;
+	int count = parser->toknext;
+
+	for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+		char c;
+		jsmntype_t type;
+
+		c = js[parser->pos];
+		switch (c) {
+			case '{': case '[':
+				count++;
+				if (tokens == NULL) {
+					break;
+				}
+				token = jsmn_alloc_token(parser, tokens, num_tokens);
+				if (token == NULL)
+					return JSMN_ERROR_NOMEM;
+				if (parser->toksuper != -1) {
+					tokens[parser->toksuper].size++;
+#ifdef JSMN_PARENT_LINKS
+					token->parent = parser->toksuper;
+#endif
+				}
+				token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+				token->start = parser->pos;
+				parser->toksuper = parser->toknext - 1;
+				break;
+			case '}': case ']':
+				if (tokens == NULL)
+					break;
+				type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+				if (parser->toknext < 1) {
+					return JSMN_ERROR_INVAL;
+				}
+				token = &tokens[parser->toknext - 1];
+				for (;;) {
+					if (token->start != -1 && token->end == -1) {
+						if (token->type != type) {
+							return JSMN_ERROR_INVAL;
+						}
+						token->end = parser->pos + 1;
+						parser->toksuper = token->parent;
+						break;
+					}
+					if (token->parent == -1) {
+						if(token->type != type || parser->toksuper == -1) {
+							return JSMN_ERROR_INVAL;
+						}
+						break;
+					}
+					token = &tokens[token->parent];
+				}
+#else
+				for (i = parser->toknext - 1; i >= 0; i--) {
+					token = &tokens[i];
+					if (token->start != -1 && token->end == -1) {
+						if (token->type != type) {
+							return JSMN_ERROR_INVAL;
+						}
+						parser->toksuper = -1;
+						token->end = parser->pos + 1;
+						break;
+					}
+				}
+				/* Error if unmatched closing bracket */
+				if (i == -1) return JSMN_ERROR_INVAL;
+				for (; i >= 0; i--) {
+					token = &tokens[i];
+					if (token->start != -1 && token->end == -1) {
+						parser->toksuper = i;
+						break;
+					}
+				}
+#endif
+				break;
+			case '\"':
+				r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+				if (r < 0) return r;
+				count++;
+				if (parser->toksuper != -1 && tokens != NULL)
+					tokens[parser->toksuper].size++;
+				break;
+			case '\t' : case '\r' : case '\n' : case ' ':
+				break;
+			case ':':
+				parser->toksuper = parser->toknext - 1;
+				break;
+			case ',':
+				if (tokens != NULL && parser->toksuper != -1 &&
+						tokens[parser->toksuper].type != JSMN_ARRAY &&
+						tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+					parser->toksuper = tokens[parser->toksuper].parent;
+#else
+					for (i = parser->toknext - 1; i >= 0; i--) {
+						if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+							if (tokens[i].start != -1 && tokens[i].end == -1) {
+								parser->toksuper = i;
+								break;
+							}
+						}
+					}
+#endif
+				}
+				break;
+#ifdef JSMN_STRICT
+			/* In strict mode primitives are: numbers and booleans */
+			case '-': case '0': case '1' : case '2': case '3' : case '4':
+			case '5': case '6': case '7' : case '8': case '9':
+			case 't': case 'f': case 'n' :
+				/* And they must not be keys of the object */
+				if (tokens != NULL && parser->toksuper != -1) {
+					jsmntok_t *t = &tokens[parser->toksuper];
+					if (t->type == JSMN_OBJECT ||
+							(t->type == JSMN_STRING && t->size != 0)) {
+						return JSMN_ERROR_INVAL;
+					}
+				}
+#else
+			/* In non-strict mode every unquoted value is a primitive */
+			default:
+#endif
+				r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+				if (r < 0) return r;
+				count++;
+				if (parser->toksuper != -1 && tokens != NULL)
+					tokens[parser->toksuper].size++;
+				break;
+
+#ifdef JSMN_STRICT
+			/* Unexpected char in strict mode */
+			default:
+				return JSMN_ERROR_INVAL;
+#endif
+		}
+	}
+
+	if (tokens != NULL) {
+		for (i = parser->toknext - 1; i >= 0; i--) {
+			/* Unmatched opened object or array */
+			if (tokens[i].start != -1 && tokens[i].end == -1) {
+				return JSMN_ERROR_PART;
+			}
+		}
+	}
+
+	return count;
+}
+
+/**
+ * Creates a new parser based over a given  buffer with an array of tokens
+ * available.
+ */
+void jsmn_init(jsmn_parser *parser) {
+	parser->pos = 0;
+	parser->toknext = 0;
+	parser->toksuper = -1;
+}
+
diff -r 000000000000 -r a1734fe1ec4b jsmn/jsmn.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/jsmn.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,76 @@
+#ifndef __JSMN_H_
+#define __JSMN_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * JSON type identifier. Basic types are:
+ * 	o Object
+ * 	o Array
+ * 	o String
+ * 	o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+	JSMN_UNDEFINED = 0,
+	JSMN_OBJECT = 1,
+	JSMN_ARRAY = 2,
+	JSMN_STRING = 3,
+	JSMN_PRIMITIVE = 4
+} jsmntype_t;
+
+enum jsmnerr {
+	/* Not enough tokens were provided */
+	JSMN_ERROR_NOMEM = -1,
+	/* Invalid character inside JSON string */
+	JSMN_ERROR_INVAL = -2,
+	/* The string is not a full JSON packet, more bytes expected */
+	JSMN_ERROR_PART = -3
+};
+
+/**
+ * JSON token description.
+ * type		type (object, array, string etc.)
+ * start	start position in JSON data string
+ * end		end position in JSON data string
+ */
+typedef struct {
+	jsmntype_t type;
+	int start;
+	int end;
+	int size;
+#ifdef JSMN_PARENT_LINKS
+	int parent;
+#endif
+} jsmntok_t;
+
+/**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+typedef struct {
+	unsigned int pos; /* offset in the JSON string */
+	unsigned int toknext; /* next token to allocate */
+	int toksuper; /* superior token node, e.g parent object or array */
+} jsmn_parser;
+
+/**
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init(jsmn_parser *parser);
+
+/**
+ * Run JSON parser. It parses a JSON data string into and array of tokens, each describing
+ * a single JSON object.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+		jsmntok_t *tokens, unsigned int num_tokens);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __JSMN_H_ */
diff -r 000000000000 -r a1734fe1ec4b jsmn/library.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jsmn/library.json	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,16 @@
+{
+  "name": "jsmn",
+  "keywords": "json",
+  "description": "Minimalistic JSON parser/tokenizer in C. It can be easily integrated into resource-limited or embedded projects",
+  "repository":
+  {
+    "type": "git",
+    "url": "https://github.com/zserge/jsmn.git"
+  },
+  "frameworks": "*",
+  "platforms": "*",
+  "examples": [
+    "example/*.c"
+  ],
+  "exclude": "test"
+}
diff -r 000000000000 -r a1734fe1ec4b main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,297 @@
+/* mbed main.cpp to test a secure MQTT connection using MBED TLS library 
+ * Copyright (c) 2017 Vergil Perez Cola
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+ 
+ /* *
+  * @note This program is derived from the MQTT sample program.
+  */
+/**
+ * @note To make this work with FRDM-K64F
+ * @note PTA0 must be disconnected from the swd clk by cutting J11.
+ * @note But to re-active SWD you need to put jumper header to J11
+ * @note so that it can be re-connected by a jumper.
+ */
+
+#include "mbed.h"
+#include "rtos.h"
+#include "XbeeMonitor.h"
+#include "easy-connect.h"
+#include "NTPClient.h"
+#include "SDBlockDevice.h"
+#include "FATFileSystem.h"
+#include "DownloadFile.h"
+#include "MQTTSManager.h"
+#include "WeatherInfo.h"
+#include "RadioCfg.h"
+#include "config.h"
+
+#include <string>
+#include <sstream>
+
+#if defined(ENABLE_LOGGING)
+#include "DigiLoggerMbedSerial.h"
+using namespace DigiLog;
+#endif
+
+#if defined(TARGET_NUCLEO_L476RG)
+//SDBlockDevice sd(D11, D12, D13, D9);
+#else
+SDBlockDevice sd(PTE3, PTE1, PTE2, PTE4);
+#endif
+
+#if !defined(TARGET_NUCLEO_L476RG)
+FATFileSystem fs("sd");
+#endif
+
+Serial pc(USBTX, USBRX, 115200);
+
+Thread xbeeThd;
+
+#if !defined(TARGET_NUCLEO_L476RG)
+static const char * radioconfigfile = "/sd/radioconfig.json";
+#endif
+
+/* List of trusted root CA certificates
+ * currently only "letsencrypt", the CA for mbedhacks.com
+ *
+ * To add more than one root, just concatenate them.
+ *
+ * TODO: Move this certificate file onto the SD card.
+ */
+static const char SSL_CA_PEM[] = "-----BEGIN CERTIFICATE-----\n"
+    "MIIFETCCA/mgAwIBAgISA2ktlb1Y6ap4GCH7dg3wS37XMA0GCSqGSIb3DQEBCwUA\n"
+    "MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD\n"
+    "ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzAzMDkwMTQ4MDBaFw0x\n"
+    "NzA2MDcwMTQ4MDBaMBgxFjAUBgNVBAMTDW1iZWRoYWNrcy5jb20wggEiMA0GCSqG\n"
+    "SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4ppYHlH8lfB7lkWOjMSnOJGaLtCBfz57I\n"
+    "VVOd1Rngsz7nE5fg3joa7lkazRY1ZqtuC2UloS+4LYoQZX4Z887dhdug/TPA4J1A\n"
+    "GppA4xVCb2kUFODMjZ2r4pMLp+MjFFMBaHrL4cgx/n4aJUB+N9Z+HW0p2Yr5TsOQ\n"
+    "ghIOPkNxFr2q6klm49+BMUbO98hAwFwsIISLf6IbHM93gx1ltqkvb55N87ZM1hYH\n"
+    "fkq+J+YqjleiLaqRN2MVlNMNfy9MDbqM5uCyGiWGtq8eiQLaWpZkxnA2MC5zPsO/\n"
+    "fzEWiVjn2uazlXZ5xZwiK22KMxVasqWMitvETtmPOl9mocRbLQdxAgMBAAGjggIh\n"
+    "MIICHTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF\n"
+    "BwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFCsgG+z1BTjrN3K+/tF0C4k818Yv\n"
+    "MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMHAGCCsGAQUFBwEBBGQw\n"
+    "YjAvBggrBgEFBQcwAYYjaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0Lm9y\n"
+    "Zy8wLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5v\n"
+    "cmcvMCsGA1UdEQQkMCKCDW1iZWRoYWNrcy5jb22CEXd3dy5tYmVkaGFja3MuY29t\n"
+    "MIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAmBggr\n"
+    "BgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwgasGCCsGAQUFBwIC\n"
+    "MIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBvbiBi\n"
+    "eSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4gYWNjb3JkYW5jZSB3aXRoIHRo\n"
+    "ZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5jcnlw\n"
+    "dC5vcmcvcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBABFH6YcvHh8foHeg\n"
+    "NM7iR9HnYRqa5gSERcCtq6jm8PcTsAbsdQ/BNpIHK7AZSg2kk17kj+JFeyMuNJWq\n"
+    "lmabV0dtzdC8ejp1d7hGb/HjuQ400th/QRayvyrDVzQPfCNyJ0C82Q2DFjeUgnqv\n"
+    "oJMcV6i4ICW0boI7GUf7oeHCmrUEHKffAbeFvx3c85c39IHJEFa59UWj1linU/Tr\n"
+    "g9i5AaSKB95d706u1XRA7WLV/Hu7yunhxEjlj33bfdifBb/ZLBd0LtrXPwtXi6E8\n"
+    "r6obp+B+Ce89G7WEhdT9BX0ck1KTK+yP7uAC7tvvsiejxXOoCtVyBAumBJS7mRuv\n"
+    "I5hmKgE=\n"
+    "-----END CERTIFICATE-----\n"
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n"
+    "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
+    "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n"
+    "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n"
+    "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
+    "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n"
+    "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n"
+    "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n"
+    "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n"
+    "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n"
+    "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n"
+    "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n"
+    "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n"
+    "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n"
+    "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n"
+    "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n"
+    "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n"
+    "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n"
+    "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n"
+    "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n"
+    "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n"
+    "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n"
+    "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n"
+    "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n"
+    "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n"
+    "-----END CERTIFICATE-----";
+
+const char * openweathermap_id = "1bfddd34faa0e0216769d688b0b0c743";
+float lastTemperature;
+
+#define BASIC_AUTH_USER         "tinong"
+#define BASIC_AUTH_PASSWORD     "tatay"
+
+template <class T>
+std::string to_string (const T& t)
+{
+    std::stringstream ss;
+    ss << t;
+    return ss.str();
+}
+
+
+void UpdateWeatherInfo(NetworkInterface* network)
+{
+    printf("Downloading weather information ...\r\n");
+    DownloadFile * wInfo = new DownloadFile(network);
+    if (wInfo)
+    {
+        std::string url = "http://api.openweathermap.org/data/2.5/weather?q=Singapore,sg&appid="; 
+        url += openweathermap_id;
+        printf("Getting weather from [%s]\r\n", url.c_str());
+        HttpResponse* result = wInfo->get_file(url.c_str());
+        if (result != NULL)
+        {
+
+            std::string content = result->get_body_as_string();
+         
+            printf("\r\n========= Weather Info =============\r\n");
+            printf("%s\r\n", content.c_str());
+            printf("==============================\r\n");
+            
+            const char * weather = content.c_str();
+            WeatherInfo info;
+            if ( parseweatherinfo(weather, info) == 0)
+            {
+                printf("Weather : %s\r\n", info.weather.c_str());
+                printf("Weather Icon : %s\r\n", info.icon.c_str());
+                printf("Current Temperature : %.2f\r\n", info.temperature - 273.15);
+                printf("Current Pressure : %.2f\r\n", info.pressure);
+                printf("Current Humidity : %.2f\r\n", info.humidity);
+        
+                // TODO: process the information and send updates
+                // to GUI  
+                lastTemperature = info.temperature - 273.15;              
+            }
+        }
+            
+        delete wInfo;
+    }
+}
+    
+int main()
+{
+    uint64_t radioID;
+    int lasthour = 0;
+    RadioCfg cfg;
+    
+#if !defined(TARGET_NUCLEO_L476RG)    
+    // Mount the SD card first!
+    printf("Mounting the filesystem on \"/sd\". ");
+    fs.mount(&sd);
+#endif
+    
+#if defined(ENABLE_LOGGING)
+    new DigiLoggerMbedSerial(&pc, LogLevelInfo);
+#endif      
+    pc.printf("Initializing XbeeMonitor ...\r\n");
+    initXbeeMonitor();
+    // TODO: get XBee radio id 
+    // and request configuration settings
+    // from the web.
+    radioID = getXbeeId();
+    cfg.radioID = radioID;
+    pc.printf("Radio ID : %llu\r\n", radioID);
+        
+    pc.printf("Connecting to ethernet ...\r\n");
+    // Get the network interface via 
+    // easy connect
+    NetworkInterface* network = easy_connect(true);
+    if (!network) {
+        return 1;
+    }
+
+    pc.printf("IP Address : %s\r\n", network->get_ip_address());
+    pc.printf("MAC Address : %s\r\n", network->get_mac_address());
+    
+    time_t ctTime;
+    ctTime = time(NULL);
+
+    printf("Getting coordinator info from the internet!...\r\n");
+#if !defined(TARGET_NUCLEO_L476RG)
+    DownloadFile * df = new DownloadFile(network, radioconfigfile, SSL_CA_PEM );
+#else
+    DownloadFile * df = new DownloadFile(network, NULL, SSL_CA_PEM );
+#endif
+    if (df)
+    {
+        std::string url = "https://www.mbedhacks.com/Garden/getconfig.php?id=";
+        url += to_string(radioID);
+        printf("Getting config from [%s]\r\n", url.c_str());
+        df->basic_auth(BASIC_AUTH_USER, BASIC_AUTH_PASSWORD);
+        HttpResponse* result = df->get_file(url.c_str());
+        if (result != NULL)
+        {
+#if defined(TARGET_NUCLEO_L476RG)                
+            std::string content = result->get_body_as_string();;
+#else
+            std::string content = df->get_file_content();
+#endif
+            printf("\r\n==========================\r\n");
+            printf("%s\r\n", content.c_str());
+            printf("==============================\r\n");
+            
+            // TODO: pass the downloaded file to the RadioCfg
+            if (parseradioconfig(content.c_str(), cfg) == 0)
+            {
+                cfg.debug();
+            }
+        }
+        delete df;
+    }
+
+    NTPClient ntp(network, cfg.utc_offset);
+    pc.printf("Initial System Time is: %s\r\n", ctime(&ctTime));
+    pc.printf("Trying to update time...\r\n");
+    if (ntp.setTime("0.pool.ntp.org") == 0) {
+        
+        pc.printf("Set time successfully\r\n");
+        pc.printf("Updated time is : %s\r\n", ctime(&ctTime));
+        
+        pc.printf("Starting the Xbee manager thread ...\r\n");
+        xbeeThd.start(runXbeeMonitor);
+        pc.printf("Starting MQTTS subscriber thread ...\r\n");
+        // Initialize MQTT
+        mqttsInit(network, SSL_CA_PEM);
+        if ( runMQTTS() != 0 )
+            pc.printf("Failed launching MQTT thread ...\r\n");
+        
+        while(true) {
+            time_t currentTime;
+            struct tm *localTime;            
+            
+            time( &currentTime );                   // Get the current time
+            localTime = localtime( &currentTime );  // Convert the current time to local time
+
+            // TODO: Update the weather information every hour ...            
+            if (lasthour != localTime->tm_hour )
+            //if (lasthour != localTime->tm_min )            
+            {
+                printf("An hour has passed!!! ...\r\n");
+                UpdateWeatherInfo(network);
+                // Update ...
+                //lasthour = localTime->tm_min;
+                lasthour = localTime->tm_hour;                
+            }
+
+            Thread::wait(10000);
+        }
+    }
+    else
+    {
+        pc.printf("Failed to setup time from NTP  ...\r\n");
+        while(true)
+        {
+            Thread::wait(100);
+        }
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b mbed-http.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-http.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/sandbox/code/mbed-http/#3004056e4661
diff -r 000000000000 -r a1734fe1ec4b mbed-os.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#f4864dc6429e1ff5474111d4e0f6bee36a759b1c
diff -r 000000000000 -r a1734fe1ec4b mbed_app.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,56 @@
+{
+    "config": {
+        "network-interface": {
+            "help": "options are ETHERNET,WIFI_ESP8266,MESH_LOWPAN_ND,MESH_THREAD",
+            "value": "ETHERNET"
+        },
+        "mesh_radio_type": {
+        	"help": "options are ATMEL, MCR20",
+        	"value": "ATMEL"
+        },
+        "esp8266-tx": {
+            "help": "Pin used as TX (connects to ESP8266 RX)",
+            "value": "D1"
+        },
+        "esp8266-rx": {
+            "help": "Pin used as RX (connects to ESP8266 TX)",
+            "value": "D0"
+        },
+        "esp8266-debug": {
+            "value": false
+        },
+        "wifi-ssid": {
+            "value": "\"VPCOLA\""
+        },
+        "wifi-password": {
+            "value": "\"AB12CD34\""
+        }
+    },
+    "macros": [ "MBEDTLS_USER_CONFIG_FILE=\"mbedtls_entropy_config.h\"", "MBEDTLS_TEST_NULL_ENTROPY", "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES" ],
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["NANOSTACK", "LOWPAN_ROUTER", "COMMON_PAL"],
+            "mbed-mesh-api.6lowpan-nd-channel-page": 0,
+            "mbed-mesh-api.6lowpan-nd-channel": 12,
+            "mbed-trace.enable": 0,
+            "mbed-http.http-buffer-size": 8192
+        },
+        "HEXIWEAR": {
+            "esp8266-tx": "PTD3",
+            "esp8266-rx": "PTD2"
+        },
+        "NUCLEO_F401RE": {
+            "esp8266-tx": "D8",
+            "esp8266-rx": "D2"
+        },
+        "NUCLEO_F411RE": {
+            "esp8266-tx": "D8",
+            "esp8266-rx": "D2"
+        },
+        "NUCLEO_L476RG": {
+            "network-interface": "WIFI_ESP8266",
+            "esp8266-tx": "A0",
+            "esp8266-rx": "A1"
+        }         
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b mbed_settings.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_settings.py	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,45 @@
+"""
+mbed SDK
+Copyright (c) 2016 ARM Limited
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+
+from os.path import join, abspath, dirname
+
+#ROOT = abspath(join(dirname(__file__), "."))
+
+##############################################################################
+# Build System Settings
+##############################################################################
+#BUILD_DIR = abspath(join(ROOT, "build"))
+
+# ARM
+#ARM_PATH = "C:/Program Files/ARM"
+
+# GCC ARM
+#GCC_ARM_PATH = ""
+
+# GCC CodeRed
+#GCC_CR_PATH = "C:/code_red/RedSuite_4.2.0_349/redsuite/Tools/bin"
+
+# IAR
+#IAR_PATH = "C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.0/arm"
+
+# Goanna static analyser. Please overload it in private_settings.py
+#GOANNA_PATH = "c:/Program Files (x86)/RedLizards/Goanna Central 3.2.3/bin"
+
+#BUILD_OPTIONS = []
+
+# mbed.org username
+#MBED_ORG_USER = ""
diff -r 000000000000 -r a1734fe1ec4b mbedtls_entropy_config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbedtls_entropy_config.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+#ifndef __MBEDTLS_ENTROPY_H__
+#define __MBEDTLS_ENTROPY_H__
+
+/* Enable entropy for K64F and K22F. This means entropy is disabled for all other targets. */
+/* Do **NOT** deploy this code in production on other targets! */
+/* See https://tls.mbed.org/kb/how-to/add-entropy-sources-to-entropy-pool */
+#if defined(TARGET_K64F) || defined(TARGET_K22F) || defined(TARGET_NUCLEO_L476RG)
+#undef MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+#undef MBEDTLS_TEST_NULL_ENTROPY
+#endif
+
+#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) && \
+    !defined(MBEDTLS_ENTROPY_NV_SEED) && !defined(MBEDTLS_TEST_NULL_ENTROPY)
+#error "This hardware does not have an entropy source."
+#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT && !MBEDTLS_ENTROPY_NV_SEED &&
+        * !MBEDTLS_TEST_NULL_ENTROPY */
+
+#if !defined(MBEDTLS_SHA1_C)
+#define MBEDTLS_SHA1_C
+#endif /* !MBEDTLS_SHA1_C */
+
+/*
+ *  This value is sufficient for handling 2048 bit RSA keys.
+ *
+ *  Set this value higher to enable handling larger keys, but be aware that this
+ *  will increase the stack usage.
+ */
+#define MBEDTLS_MPI_MAX_SIZE        256
+
+#define MBEDTLS_MPI_WINDOW_SIZE     1
+
+#endif
diff -r 000000000000 -r a1734fe1ec4b sd-driver.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver.lib	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/sd-driver/#96142e4303df6540b4b231453dd23701111dc1bb
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/FETCH_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/FETCH_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+96142e4303df6540b4b231453dd23701111dc1bb		branch 'master' of https://github.com/ARMmbed/sd-driver
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/ORIG_HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/ORIG_HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+96142e4303df6540b4b231453dd23701111dc1bb
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/config
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/config	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/sd-driver/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/description
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/description	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/hooks/applypatch-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/hooks/applypatch-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/hooks/commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/hooks/commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/hooks/post-update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/hooks/post-update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/hooks/pre-applypatch.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/hooks/pre-applypatch.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/hooks/pre-commit.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/hooks/pre-commit.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/hooks/pre-rebase.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/hooks/pre-rebase.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/hooks/prepare-commit-msg.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/hooks/prepare-commit-msg.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/hooks/update.sample
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/hooks/update.sample	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/index
Binary file sd-driver/.git/index has changed
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/info/exclude
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/info/exclude	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,25 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
\ No newline at end of file
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/logs/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/logs/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 96142e4303df6540b4b231453dd23701111dc1bb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036517 +0000	clone: from https://github.com/ARMmbed/sd-driver/
+96142e4303df6540b4b231453dd23701111dc1bb 96142e4303df6540b4b231453dd23701111dc1bb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036517 +0000	checkout: moving from master to 96142e4303df6540b4b231453dd23701111dc1bb
+96142e4303df6540b4b231453dd23701111dc1bb 96142e4303df6540b4b231453dd23701111dc1bb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036517 +0000	checkout: moving from 96142e4303df6540b4b231453dd23701111dc1bb to master
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/logs/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/logs/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 96142e4303df6540b4b231453dd23701111dc1bb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036517 +0000	clone: from https://github.com/ARMmbed/sd-driver/
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/logs/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/logs/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 96142e4303df6540b4b231453dd23701111dc1bb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1491036517 +0000	clone: from https://github.com/ARMmbed/sd-driver/
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/objects/pack/pack-3818907d42dc76a69d2f1576b67ec166057798d1.idx
Binary file sd-driver/.git/objects/pack/pack-3818907d42dc76a69d2f1576b67ec166057798d1.idx has changed
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/objects/pack/pack-3818907d42dc76a69d2f1576b67ec166057798d1.pack
Binary file sd-driver/.git/objects/pack/pack-3818907d42dc76a69d2f1576b67ec166057798d1.pack has changed
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/packed-refs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/packed-refs	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,9 @@
+# pack-refs with: peeled 
+aabeb8c7d1f60a71ba171f04a7e1f02acaa6f4ea refs/remotes/origin/g-fix-size-const
+df812d2e2ddad1afd0972876504c383ee0c1df9c refs/remotes/origin/g-remove-spif
+96142e4303df6540b4b231453dd23701111dc1bb refs/remotes/origin/master
+c5a1a88f9ef53c6bca5127acd09393a61b753a13 refs/tags/sd-driver-0.0.1-mbed-os-5.3.4
+^50dd8c39836ccbcd9c1ef7161d88ddc39a0bcaed
+b2fb4883764ebd0aa8de63a4490db38692c80b8e refs/tags/sd-driver-0.0.2-mbed-os-5.4.0
+290050ab9847aea143c79b61eca9dec25373754d refs/tags/sd-driver-0.0.3-mbed-os-5.4.1
+^a8c85d30af86a7431d85dee02d133d60dd386406
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/refs/heads/master	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+96142e4303df6540b4b231453dd23701111dc1bb
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.git/refs/remotes/origin/HEAD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.git/refs/remotes/origin/HEAD	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
diff -r 000000000000 -r a1734fe1ec4b sd-driver/.meta
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/.meta	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
diff -r 000000000000 -r a1734fe1ec4b sd-driver/README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/README.md	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,838 @@
+# mbed OS SDCard Driver (sd-driver) for FAT32 Filesystem Support
+
+
+Simon Hughes
+
+20170329
+
+Version 1.00
+
+
+# Executive Summary
+
+The purpose of this document is to describe how to use the mbed OS SDCard 
+driver (sd-driver) so applications can read/write 
+data to flash storage cards using the standard POSIX File API 
+programming interface. The sd-driver uses the SDCard SPI-mode of operation 
+which is a subset of possible SDCard functionality.  
+
+This repository contains the mbed-os SDCard driver for generic SPI 
+SDCard support and other resources, as outlined below:
+
+- `SDBlockDevice.h` and `SDBlockDevice.cpp`. This is the SDCard driver module presenting 
+  a Block Device API (derived from BlockDevice) to the underlying SDCard.
+- POSIX File API test cases for testing the FAT32 filesystem on SDCard.
+    - basic.cpp, a basic set of functional test cases.
+    - fopen.cpp, more functional tests reading/writing greater volumes of data to SDCard, for example.
+- `mbed_app.json` mbed-os application configuration file with SPI pin configurations for the CI shield and overrides for specific targets. 
+   This file allows the SPI pins to be specified for the target without having to edit the implementation files.
+- This README which includes [Summary of POSIX File API Documentation](#summary-posix-api-documentation) 
+  including detailed instruction on how to use the FAT filesystem and SDBlockDevice driver. 
+
+The SDCard driver is maintained in this repository as a component separate from the main mbed OS repository. 
+Hence the 2 repositories (mbed-os and sd-driver) have to be used together 
+to deliver the FAT32 Filesystem/SDCard support. This document explains how to do this.
+
+
+# Introduction
+
+### Overview
+
+The scope of this document is to describe how applications use the FAT filesystem and sd-driver
+components to persistently store data on SDCards. The document is intended to help developers adopt the 
+mbed OS POSIX File API support, and in particular to help explain:
+
+- How the software components work together to deliver the storage functionality. 
+- How to work with the sd-driver and mbed OS to build the examples. The example code can easily
+  be copied into your new application code.
+- How to work with the CI Test Shield, which adds an SDCard slot to those targets that do not have already have one.
+- How to run the POSIX File API mbed Greentea test cases, which provide further example code of how to use
+  the POSIX File API.
+ 
+Section 1 provides an Executive Summary, describing the purpose of the sd-driver, the supporting
+software, examples, test cases and documentation.
+
+Section 2 provides an an overview of the material covered including descriptions of the major sections. 
+
+Section 3 provides an overview of the mbed OS filesystem software components, 
+including the inter-relationships between the application, POSIX file API, the standard c-library, 
+the mbed OS filesystem and the SDCard driver (sd-driver). 
+
+Section 4 describes how to build and run an example application for reading 
+and writing data to an SDCard using the POSIX File API. The example begins by describing
+the procedure for building and testing on the K64F target. The final sub-sections
+describe how to use the test shield to add an SDCard slot to any mbed target, 
+and hence enable the persistent storage of data on any supported target.
+
+Section 5 describes an example application which uses the raw 
+BlockDevice API to read and write data to the SDCard.
+
+Section 6 describes how to build and run the SDCard POSIX File API mbed Greentea test cases.
+There are a number of functional test cases demonstrating how to use the 
+mbed OS POSIX File API. 
+
+Section 7 describes the POSIX File API and provides links to useful API documentation web pages. 
+
+
+### Known mbed-os and sd-driver Compatible Versions
+
+The following versions of the mbed-os and sd-driver repositories are known to work together: 
+
+- {mbed-os, sd-driver} = {mbed-os-5.4.0-rc2, sd-driver-0.0.1-mbed-os-5.4.0-rc2}. 
+  `K64F`, `NUCLEO_F429ZI` and `UBLOX_EVK_ODIN_W2` fopen and basic filesystem tests working.
+- {mbed-os, sd-driver} = {mbed-os-5.4.0, sd-driver-0.0.2-mbed-os-5.4.0}. 
+  `K64F`, `NUCLEO_F429ZI` and `UBLOX_EVK_ODIN_W2` fopen and basic filesystem tests working.
+- {mbed-os, sd-driver} = {mbed-os-5.4.1, sd-driver-0.0.3-mbed-os-5.4.1}. 
+
+To find the latest compatible versions, use the following command to see the messages attached to the tags
+in the sd-driver repository:
+
+	ex_app7/$ cd sd-driver
+	ex_app7/sd-driver$ git tag -n
+	sd-driver-0.0.1-mbed-os-5.3.4 Version compatible with mbed-os-5.3.4, and private_mbedos_filesystems-0.0.1-mbed-os-5.3.4.
+	sd-driver-0.0.2-mbed-os-5.4.0 Updated README.md to include worked exmaples and restructuring of information.
+	sd-driver-0.0.3-mbed-os-5.4.1 Version compatible with mbed-os-5.4.1.
+
+
+### Known Issues With This Document
+
+There are no known issues with this document.
+
+
+# Overview of mbed OS Filesystem Software Component Stack
+
+
+    ------------------------
+    |                      |
+    |    Application       |        // This application uses the POSIX File API  
+    |                      |        // to read/write data to persistent storage backends.
+    ------------------------
+
+    ------------------------        // POSIX File API (ISO).
+
+    ------------------------
+    |                      |
+    |     libc             |        // The standard c library implementation 
+    |                      |        // e.g. newlib.
+    ------------------------
+
+    ------------------------        // sys_xxx equivalent API.
+
+    ------------------------
+    |                      |
+    |  mbed_retarget.cpp   |        // Target specific mapping layer.
+    |                      |
+    ------------------------
+
+    ------------------------        // Filesystem Upper Edge API. 
+
+    ------------------------
+    |                      |
+    |     File System      |        // File system wrappers and implementation.
+    |                      |
+    ------------------------
+
+    ------------------------        // FS Lower Edge API (Block Store Interface).
+
+    ------------------------
+    |    Block API         |
+    |    Device Driver     |        // The SDCard driver, for example.
+    |  e.g. sd-driver      |        
+    ------------------------
+    
+    ------------------------        // SPI.h interface.
+
+    ------------------------
+    |                      |
+    |       SPI            |        // SPI subsystem (C++ classes and C-HAL implementation).
+    |                      |
+    ------------------------
+    
+    Figure 1. mbedOS generic architecture of filesystem software stack.
+
+The figure above shows the mbed OS software component stack used for data
+storage on SDCard:
+
+- At the top level is the application component which uses the standard POSIX File API 
+  to read and write application data to persistent storage.
+- The newlib standard library (libc) stdio.h interface (POSIX File API)  
+  implementation is used as it's optimised for resource limited embedded systems.
+- mbed_retarget.cpp implements the libc back-end file OS handlers and maps them 
+  to the FileSystem. 
+- The File System code (hosted in mbed-os) is composed of 2 parts: 
+	- The mbed OS file system wrapper classes (e.g. FileSystem, File, FileBase classes)
+	  which are used to present a consistent API to the retarget module for different 
+	  (third-party) file system implementations. 
+	- The FAT filesystem implementation code. 
+	  The [FATFS: Generic FAT File System Module](http://elm-chan.org/fsw/ff/00index_e.html)
+	  (ChanFS) has been integrated within mbed-os. 
+- The Block API Device Driver. The SDCard driver is an example of a persistent storage driver.
+  It's maintained as a separate component from the mbed OS repository (in this repository). 
+- The SPI module provides the mbed OS generic SPI API. This functionality is maintained in 
+  mbed OS. 
+
+
+# SDCard POSIX File API Example App for Reading/Writing Data
+
+### Overview
+
+This section describes how to build and run an example application that 
+uses the POSIX File API to read and write data to SDCard. The discussion begins by 
+descibing how to run the example on the FRDM K64F target, but this is later
+generalised to all target platforms that have the standard 
+Arduino form factor headers. Tthe Continuous Integration (CI) Test Shield
+can be inserted into the headers to add a SDCard slot to the target.   
+
+The example code is a modified version of the 
+[mbed-os-example-fat-filesystem](https://github.com/ARMmbed/mbed-os-example-fat-filesystem) example
+modified for use with the sd-driver.
+
+The following sub-sections describe the steps for building and running the example:
+ 
+- The [Pre-Requisites](#pre-requisites) section describes the development environment used for this example.
+  Other similar development environments can be used.
+- The [Create the Example Project](#create-the-example-project) section describes how the application project is created
+  by including the mbed-os and sd-driver code.
+- The [Build the Example Project](#build-the-example-project) section describes how to build the example application.
+- The [Insert SDCard into K64F](#insert-sdcard-into-k64f) section describes how to select a card and insert it into the
+  SDCard slot on the K64F.
+- The [Run the Example Binary on the K64F](#run-the-example-binary-on-the-k64f) section describes how to run the 
+  example binary on the target and verify the example has run correctly.
+- The [Testing with an SDCard on Target XYZ](#testing-with-an-sdcard-on-target-xyx) section describes the use 
+  of Continuous Integration Test Shield, which hosts an SDCard slot. By inserting the CI test shield into the
+  Arduino headers of an mbed target platform, the SDCard/FAT Filesystem components can be used to store data
+  persistently on any standard mbed target development board.
+
+
+### <a name="pre-requisites"></a> Pre-Requisites
+
+To work through this example, you should have a working development environment on your machine. For example, 
+the following tools should be installed:
+
+- A compiler e.g. arm-none-eabi-gcc. 
+- Python 2.7.9 or later. 
+- [mbed Greentea](https://github.com/armmbed/greentea),  the mbed OS test tool.
+- Git Bash or a similar git command line tool to interact with the ARM mbed GitHub repositories. 
+- [mbed-cli](https://github.com/armmbed/mbed-cli), the tool used to make mbed OS application and test builds.
+
+For more information on how to setup a development environment, please review the documentation on the  
+[mbed documentation site](https://docs.mbed.com).
+
+
+### <a name="create-the-example-project"></a> Create the Example Project 
+
+First create the top level application directory sd_ex1 and move into it:
+
+    simhug01@E107851:/d/demo_area$ mkdir sd_ex1
+    simhug01@E107851:/d/demo_area$ cd sd_ex1
+    simhug01@E107851:/d/demo_area/sd_ex1$ 
+
+Next, perform the "mbed new" operation to download the mbed-os repository into this directory:
+
+	simhug01@E107851:/d/demo_area/sd_ex1$ mbed new .
+	[mbed] Creating new program "ex_sdcard" (git)
+	[mbed] Adding library "mbed-os" from "https://github.com/ARMmbed/mbed-os" at branch latest
+	[mbed] Updating reference "mbed-os" -> "https://github.com/ARMmbed/mbed-os/#5faf4b26c5954d15c7c1cccac6498e0c690ad101"
+	warning: LF will be replaced by CRLF in mbed-os.lib.
+	The file will have its original line endings in your working directory.
+	(mx1_venv1) simhug01@E107851:/d/demo_area/sd_ex1$ ls -1
+	mbed-os
+	mbed-os.lib
+	mbed_settings.py
+	(mx1_venv1) simhug01@E107851:/d/demo_area/sd_ex1$
+
+Next, get add the sd-driver component to the application project: 
+
+    simhug01@E107851:/d/demo_area/sd_ex1$ mbed add sd-driver
+    <trace removed>
+    simhug01@E107851:/d/demo_area/sd_ex1$ 
+
+Next, copy the example1.cpp file and `mbed_app.json` files from inside the sd-driver directory to the top level sd_ex1 directory:
+    
+    simhug01@E107851:/d/demo_area/sd_ex1$ cp sd-driver/features/TESTS/examples/example1.cpp .
+    simhug01@E107851:/d/demo_area/sd_ex1$ cp sd-driver/config/mbed_app.json .
+    simhug01@E107851:/d/demo_area/sd_ex1$
+
+The `mbed_app.json` file specifies the SPI bus pin configuration for different targets. 
+The file includes a specific configuration of the K64F which is used
+because the mbed compile command specifies the K64F build target. The `mbed_app.json` file 
+is described in more detail in the [Testing with an SDCard on Target XYZ](#testing-with-an-sdcard-on-target-xyx) section. 
+
+### <a name="build-the-example-project"></a> Build the Example Project 
+
+Next, build the example application: 
+
+	simhug01@E107851:/d/demo_area/sd_ex1$ mbed compile -m K64F -t GCC_ARM 
+
+
+#### WARNING: "mbed new ." command and possible mbed-os sd-driver versioning incompatibilities
+
+If you experience problems building the example then it may mean the version
+of the mbed-os repository created with the "mbed new ." command is not compatible with 
+the sd-driver repository version created with "mbed add sd-driver" command. This is because:
+
+- The "mbed new ." creates the mbed-os repository at the latest "Release" e.g. `mbed-os-5.4.0`.
+- The "mbed add sd-driver" command creates the sd-driver repository at the latest version of 
+  master i.e. the tip of master. Changes may be present that are not compatible with 
+  the latest mbed-os release e.g. in preparation for the next release.
+
+This situation can be resolved by checking out compatible versions of the repositories as 
+described in the section [Setting mbed-os/sd-driver Repositories To Compatible Versions](#settting-repos-to-compatible-versions)
+
+### <a name="insert-sdcard-into-k64f"></a> Insert SDCard into K64F
+
+The examples and test cases have been run on a K64F with the following pre-formatted microSDHC cards:
+
+- Kingston 2GB mircoSDHC card.  
+- Kingston 8GB mircoSDHC card.  
+- SanDisk 16GB mircoSDHC ultra card.  
+
+If the card requires formatting then the following procedure is known to work:
+
+- Insert microSD card into SD adapter in USB stick (or similar) so the microSD card can be insert into windows PC.
+- Within file explorer, right click/Format on the USB drive.
+- Select FAT32, 4096 cluster size, Quick Format.
+- Format the drive.
+
+The microSD card should then be ready for use in the K64F. Insert the formatted card
+into the SDCard slot on the K64F PCB. 
+
+
+### <a name="run-the-example-binary-on-the-k64f"></a> Run the Example Binary on the K64F 
+
+Once the binary is built, copy the binary from `/d/demo_area/sd_ex1/BUILD/K64F/GCC_ARM/example1.bin` to the K64F. 
+After connecting a serial console and resetting the target, the following trace should be seen:
+
+	Welcome to the filesystem example.
+	Opening a new file, numbers.txt. done.
+	Writing decimal numbers to a file (20/20) done.
+	Closing file. done.
+	Re-opening file read-only. done.
+	Dumping file to screen.
+	0
+	1
+	2
+	3
+	4
+	5
+	6
+	7
+	8
+	9
+	10
+	11
+	12
+	13
+	14
+	15
+	16
+	17
+	18
+	19
+	EOF.
+	Closing file. done.
+	Opening root directory. done.
+	Printing all filenames:
+	  numbers.txt
+	Closeing root directory. done.
+	Filesystem Demo complete.
+
+
+### <a name="testing-with-an-sdcard-on-target-xyx"></a> Testing with an SDCard on Target XYZ
+
+The standard way to test is with the mbed CI Test Shield plugged into the 
+target board. This pin mapping for this configuration is parameterised in 
+the `mbed_app.json` file.
+
+The following is an example of the `mbed_app.json` file available in the repository:
+
+    {
+        "config": {
+            "UART_RX": "D0",
+            "UART_TX": "D1",
+            "DIO_0": "D0",
+            "DIO_1": "D1",
+            "DIO_2": "D2",
+            "DIO_3": "D3",
+            "DIO_4": "D4",
+            "DIO_5": "D5",
+            "DIO_6": "D6",
+            "DIO_7": "D7",
+            "DIO_8": "D8",
+            "DIO_9": "D9",
+            "SPI_CS": "D10",
+            "SPI_MOSI": "D11",
+            "SPI_MISO": "D12",
+            "SPI_CLK": "D13",
+            "I2C_SDA": "D14",
+            "I2C_SCL": "D15",
+            "I2C_TEMP_ADDR":"0x90",
+            "I2C_EEPROM_ADDR":"0xA0",
+            "AIN_0": "A0",
+            "AIN_1": "A1",
+            "AIN_2": "A2",
+            "AIN_3": "A3",
+            "AIN_4": "A4",
+            "AIN_5": "A5",
+            "AOUT" : "A5",
+            "PWM_0": "D3",
+            "PWM_1": "D5",
+            "PWM_2": "D6",
+            "PWM_3": "D9",
+            "DEBUG_MSG": 0,
+            "DEVICE_SPI": 1,
+            "FSFAT_SDCARD_INSTALLED": 1
+        },
+        "target_overrides": {
+            "DISCO_F051R8": {
+                 "SPI_MOSI": "SPI_MOSI",
+                 "SPI_MISO": "SPI_MISO",
+                 "SPI_CLK":  "SPI_SCK",
+                 "SPI_CS":   "SPI_CS"
+            },
+            "K20D50M": {
+                 "SPI_MOSI": "PTD2",
+                 "SPI_MISO": "PTD3",
+                 "SPI_CLK":  "PTD1",
+                 "SPI_CS":   "PTC2"
+            },
+            "KL22F": {
+                 "SPI_MOSI": "PTD6",
+                 "SPI_MISO": "PTD7",
+                 "SPI_CLK":  "PTD5",
+                 "SPI_CS":   "PTD4"
+            },
+            "KL25Z": {
+                 "SPI_MOSI": "PTD2",
+                 "SPI_MISO": "PTD3",
+                 "SPI_CLK":  "PTD1",
+                 "SPI_CS":   "PTD0"
+            },
+            "KL43Z": {
+                 "SPI_MOSI": "PTD6",
+                 "SPI_MISO": "PTD7",
+                 "SPI_CLK":  "PTD5",
+                 "SPI_CS":   "PTD4"
+            },
+            "KL46Z": {
+                 "SPI_MOSI": "PTD6",
+                 "SPI_MISO": "PTD7",
+                 "SPI_CLK":  "PTD5",
+                 "SPI_CS":   "PTD4"
+            },
+            "K64F": {
+                 "SPI_MOSI": "PTE3",
+                 "SPI_MISO": "PTE1",
+                 "SPI_CLK":  "PTE2",
+                 "SPI_CS":   "PTE4"
+            },
+            "K66F": {
+                 "SPI_MOSI": "PTE3",
+                 "SPI_MISO": "PTE1",
+                 "SPI_CLK":  "PTE2",
+                 "SPI_CS":   "PTE4"
+            },
+            "LPC11U37H_401": {
+                 "SPI_MOSI": "SDMOSI",
+                 "SPI_MISO": "SDMISO",
+                 "SPI_CLK":  "SDSCLK",
+                 "SPI_CS":   "SDSSEL"
+            },
+            "LPC2368": {
+                 "SPI_MOSI": "p11",
+                 "SPI_MISO": "p12",
+                 "SPI_CLK":  "p13",
+                 "SPI_CS":   "p14"
+            },
+            "NUCLEO_L031K6": {
+                 "SPI_MOSI": "SPI_MOSI",
+                 "SPI_MISO": "SPI_MISO",
+                 "SPI_CLK":  "SPI_SCK",
+                 "SPI_CS":   "SPI_CS"
+            },
+            "nRF51822": {
+                 "SPI_MOSI": "p12",
+                 "SPI_MISO": "p13",
+                 "SPI_CLK":  "p15",
+                 "SPI_CS":   "p14"
+            },
+            "RZ_A1H": {
+                 "SPI_MOSI": "P8_5",
+                 "SPI_MISO": "P8_6",
+                 "SPI_CLK":  "P8_3",
+                 "SPI_CS":   "P8_4"
+            }
+        }
+    }
+
+Note the following things about the `mbed_app.json` file:
+
+- The `mbed_app.json` file is used to define target specific symbols for the SPI pins connecting the SDCard slot to the target MCU:
+    - "SPI\_CS". This is the Chip Select line.
+    - "SPI\_MOSI". This is the Master Out Slave In data line.
+    - "SPI\_MISO". This is the Master In Slave Out data line.
+    - "SPI\_CLK".  This is the serial Clock line.
+- The default configuration defined in the "config" section is for the standard Arduino header pin mappings for the SPI bus. 
+  The "config" section defines a dictionary mapping functional names to target board Arduino header pins: 
+    - "SPI\_CS": "D10". This causes the MBED\_CONF\_APP\_SPI\_CS symbol to be defined in mbed\_config.h as D10, which is used in the filesystem test implementation.
+      D10 is defined in the target specific PinNames.h file.
+    - "SPI\_MOSI": "D11". This causes the MBED\_CONF\_APP\_SPI\_MOSI symbol to be defined in mbed\_config.h.
+    - "SPI\_MISO": "D12". This causes the MBED\_CONF\_APP\_SPI\_MISO symbol to be defined in mbed\_config.h.
+    - "SPI\_CLK": "D13". This causes the MBED\_CONF\_APP\_SPI\_CLK symbol to be defined in mbed\_config.h.
+- The `"target_overrides"` section is used to override the "SPI\_xxx" symbols for specific target boards, which may have an SDCard slot, for example.
+  This is the case for the K64F, where the "SPI\_xxx" are mapped to the pin names for the on-board SDCard.
+
+  ```
+    "K64F": {
+         "SPI_MOSI": "PTE3",
+         "SPI_MISO": "PTE1",
+         "SPI_CLK":  "PTE2",
+         "SPI_CS":   "PTE4"
+    }
+    ```  
+- Thus, in the absence of any target specific definitions in the `"target_overrides"` section, all boards will default to 
+  using the Arduino header configuration. For those platforms with a `"target_overrides"` section then this configuration
+  will be used in preference. 
+- Hence in the case that you want to test a platform with an SDCard inserted into a 
+  fitted CI test shield (rather than the on-board SDCard slot)
+  and there is a `"target_overrides"` section present in the `mbed_app.json` file, you must then delete the `"target_overrides"`
+  section before building. This will result in the default configuration being used (suitable for the CI
+  Test Shield).
+- Note when inserting the v1.0.0 CI Test Shield into the Arduino header of the target platform, the shield pins D0 and
+  D1 should be bent to be parallel to the shield PCB so they are not inserted into the Arduino header. This is because
+  some boards use the same UART on DAPLINK and D0/D1, which means the serial debug channel breaks and hence the mbed greentea
+  test suite will not work correctly. This is mainly on older ST boards and should not be a problem on 
+  `K64F`, `NUCLEO_F429ZI` and `UBLOX_EVK_ODIN_W2`. Note also that the v2.0.0 CI Test Shield doesn't suffer from this
+  problem and the pins don't need to be bent.  
+- When inserting the SDCard into the card slot on the CI test shield, make sure the card is fully inserted. 
+  On insertion, there should be a small clicking sound when the card registers, and the back edge of the card
+  should protrude no more than ~1mm over the edge of the CI test shield PCB. If the SDCard fails to register, 
+  try gently pushing the metal flexible strip in the shape of a spade at the top edge of the SDCard metal slot
+  casing with a pair of tweezers, bending it a little to lower it into the slot casing. This helps with the
+  insertion mechanism.
+
+
+### Target K64F with CI Test Shield fitted
+
+![alt text](docs/pics/sd_driver_k64_with_ci_test_shield.jpg "unseen title text")
+
+**Figure 2. The figure shows the K64F platform with the CI shield fitted.**
+
+The above figure shows the K64F with the v1.0.0 CI test shield fitted. Note:
+
+- The pins D0/D1 (top right of CI test shield) are bent sideways so as not to insert into the header.
+- The SDCard is fully inserted into the slot and overhangs the PCB by ~1mm.  
+  
+
+# SDBlockDevice Example Application 
+
+The following sample code illustrates how to use the sd-driver Block Device API: 
+
+
+    #include "mbed.h"
+    #include "SDBlockDevice.h"
+
+    // Instantiate the SDBlockDevice by specifying the SPI pins connected to the SDCard 
+    // socket. The PINS are:
+    //     MOSI (Master Out Slave In)
+    //     MISO (Master In Slave Out)
+    //     SCLK (Serial Clock)
+    //     CS (Chip Select)
+    SDBlockDevice sd(p5, p6, p7, p12); // mosi, miso, sclk, cs
+    uint8_t block[512] = "Hello World!\n";
+    
+    int main() 
+    {
+        // call the SDBlockDevice instance initialisation method.
+        sd.init();
+        
+        // Write some the data block to the device 
+        sd.program(block, 0, 512);
+        
+        // read the data block from the device
+        sd.read(block, 0, 512);
+        
+        // print the contents of the block
+        printf("%s", block);
+        
+        // call the SDBlockDevice instance de-initialisation method.
+        sd.deinit();
+    }
+
+
+# SDCard POSIX File API mbed Greentea Test Cases
+
+This section describes how to build and run the POSIX file API test cases. 
+The following steps are covered:
+
+- [Create the FAT/SDCard Application Project](#create-fat-sdcard-application-project). 
+  This section describes how to git clone the mbed OS and sd-driver repositories containing the 
+  code and test cases of interest.
+- [Build the mbed OS Test Cases](#build-the-mbedos-test-cases). This section 
+  describes how to build the mbed OS test cases.
+- [Insert a microSD Card Into the K64F for Greentea Testing](#greentea-insert-sdcard-into-k64f).This section 
+  describes how to format (if required) a microSD card prior to running the tests.
+- [Run the POSIX File Test Case](#run-the-posix-file-test-cases).This section 
+  describes how to run the POSIX file test cases.
+
+
+### <a name="create-fat-sdcard-application-project"></a> Create the FAT/SDCard Application Project
+
+This section describes how to create an application project combining the 
+mbed-os and sd-driver repositories into a single project. 
+In summary the following steps will be covered in this section:
+
+- A top level application project directory is created. The directory name is ex_app1.
+- In the ex_app1 directory, the mbed-os repository is cloned.
+- In the ex_app1 directory at the same level as the mbed-os directory, the sd-driver repository is cloned.
+- The `mbed_app.json` file is copied from the `sd-driver/config/mbed_app.json` to the ex_app1 directory.
+
+First create the top level application directory ex_app1 and move into it:
+
+    simhug01@E107851:/d/demo_area$ mkdir ex_app1
+    simhug01@E107851:/d/demo_area$ pushd ex_app1
+
+Next, get a clone of public mbed OS repository in the following way:
+
+    simhug01@E107851:/d/demo_area/ex_app1$ git clone git@github.com:/armmbed/mbed-os
+    <trace removed>
+    simhug01@E107851:/d/demo_area/ex_app1$
+
+Next, get a clone of the sd-driver repository:
+
+    simhug01@E107851:/d/demo_area/ex_app1$ git clone git@github.com:/armmbed/sd-driver
+    <trace removed>
+    simhug01@E107851:/d/demo_area/ex_app1$
+    
+Finally, copy the `mbed_app.json` application configuration file from `sd-driver/config/mbed_app.json` to the ex_app1 directory:
+
+    simhug01@E107851:/d/demo_area/ex_app1$ cp sd-driver/config/mbed_app.json .
+    simhug01@E107851:/d/demo_area/ex_app1$
+
+The `mbed_app.json` file specifies the SPI bus pin configuration for different targets, 
+and is discussed in the [Testing with an SDCard on Target XYZ](#testing-with-an-sdcard-on-target-xyx) section. 
+
+
+### <a name="build-the-mbedos-test-cases"></a> Build the mbed OS Test Cases
+
+Build the test cases for the K64F target using the following command:
+
+    simhug01@E107851:/d/demo_area/ex_app1$ mbed -v test --compile -t GCC_ARM -m K64F --app-config mbed_app.json 
+    <trace removed>
+    simhug01@E107851:/d/demo_area/ex_app1$
+
+The build trace is quite extensive but on a successful build you should see the following output at the end of the log:
+
+	Build successes:
+	  * K64F::GCC_ARM::MBED-BUILD
+	  * K64F::GCC_ARM::MBED-OS-FEATURES-FEATURE_LWIP-TESTS-MBEDMICRO-NET-CONNECTIVITY
+	  <trace removed>
+	  * K64F::GCC_ARM::MBED-OS-FEATURES-TESTS-FILESYSTEM-FAT_FILE_SYSTEM
+	  * K64F::GCC_ARM::MBED-OS-FEATURES-TESTS-FILESYSTEM-HEAP_BLOCK_DEVICE
+	  * K64F::GCC_ARM::MBED-OS-FEATURES-TESTS-FILESYSTEM-UTIL_BLOCK_DEVICE
+	  <trace removed>
+	  * K64F::GCC_ARM::SD-DRIVER-FEATURES-TESTS-FILESYSTEM-BASIC
+	  * K64F::GCC_ARM::SD-DRIVER-FEATURES-TESTS-FILESYSTEM-FOPEN
+	
+	Build skips:
+	  * K64F::GCC_ARM::MBED-OS-FEATURES-FEATURE_LWIP-TESTS-MBEDMICRO-NET-TCP_PACKET_PRESSURE
+	  <trace removed>
+
+
+Notice the following tests in the sd-driver tree are listed above:     
+
+- `K64F::GCC_ARM::SD-DRIVER-FEATURES-TESTS-FILESYSTEM-BASIC`
+- `K64F::GCC_ARM::SD-DRIVER-FEATURES-TESTS-FILESYSTEM-FOPEN`
+
+
+The FAT32/SDCard test cases are at following locations in the source code tree:
+
+    /d/demo_area/ex_app1/sd-driver/features/TESTS/filesystem/basic/basic.cpp
+    /d/demo_area/ex_app1/sd-driver/features/TESTS/filesystem/fopen/fopen.cpp
+
+
+#### <a name="settting-repos-to-compatible-versions"></a> Setting mbed-os/sd-driver Repositories To Compatible Versions 
+
+The sd-driver master HEAD and the mbed-os master HEAD should be compatible 
+with one another and therefore no specific tagged versions need to be checked out.
+However, in the case that you experience problems building, checkout out the compatible 
+tagged version of each repository, as shown below:
+
+    simhug01@E107851:/d/demo_area/ex_app1$ pushd mbed-os
+    simhug01@E107851:/d/demo_area/ex_app1$ git checkout tags/mbed-os-5.4.0
+    simhug01@E107851:/d/demo_area/ex_app1$ popd 
+    simhug01@E107851:/d/demo_area/ex_app1$ pushd sd-driver
+    simhug01@E107851:/d/demo_area/ex_app1$ git checkout tags/sd-driver-0.0.2-mbed-os-5.4.0
+    simhug01@E107851:/d/demo_area/ex_app1$ popd 
+
+In the above: 
+
+- `mbed-os-5.4.0` should be replaced with the latest mbed-os release tag.
+-  For an mbed-os release tag `mbed-os-x.y.z`, use the equivalent sd-driver tag `sd-driver-a.b.c-mbed-os-x.y.z`
+   where `a.b.c` is the latest version code for the `mbed-os-x.y.z` tag.
+
+### <a name="greentea-insert-sdcard-into-k64f"></a> Insert SDCard into K64F for Greentea Testing
+
+See the previous section for [Insert SDCard into K64F](#insert-sdcard-into-k64f) for details.
+
+
+### <a name="run-the-posix-file-test-cases"></a> Run the POSIX File Test Case
+
+To setup for running the test cases, connect the K64F development board to your 
+PC using a suitable USB cable.
+
+All tests can be run using the following command:
+
+    simhug01@E107851:/d/demo_area/ex_app1$ mbedgt -VS
+    <trace removed>
+
+However, it's possible to run a particular test case using the following form of the mbedgt command:
+
+    simhug01@E107851:/d/demo_area/ex_app1$ mbedgt -VS --test-by-names=<test-name>
+    
+The names of the tests can be listed using: 
+
+    simhug01@E107851:/d/demo_area/ex_app1$ mbedgt -VS --list
+
+For example, to run the basic test use:
+    
+    simhug01@E107851:/d/demo_area/ex_app1$ mbedgt -VS --test-by-names=sd-driver-features-tests-filesystem-basic 
+
+To run the fopen test use:
+
+    simhug01@E107851:/d/demo_area/ex_app1$ mbedgt -VS --test-by-names=sd-driver-features-tests-filesystem-fopen 
+    
+On a successful run, results similar to the following will be shown:
+
+	mbedgt: test suite report:
+	+--------------+---------------+-------------------------------------------+--------+--------------------+-------------+
+	| target       | platform_name | test suite                                | result | elapsed_time (sec) | copy_method |
+	+--------------+---------------+-------------------------------------------+--------+--------------------+-------------+
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | OK     | 151.46             | shell       |
+	+--------------+---------------+-------------------------------------------+--------+--------------------+-------------+
+	mbedgt: test suite results: 1 OK
+	mbedgt: test case report:
+	+--------------+---------------+-------------------------------------------+----------------------------------------------------------------------------------------+--------+--------+--------+--------------------+
+	| target       | platform_name | test suite                                | test case                                                                              | passed | failed | result | elapsed_time (sec) |
+	+--------------+---------------+-------------------------------------------+----------------------------------------------------------------------------------------+--------+--------+--------+--------------------+
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_01: fopen()/fwrite()/fclose() directories/file in multi-dir filepath. | 1      | 0      | OK     | 7.57               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_02: fopen(r) pre-existing file try to write it.                       | 1      | 0      | OK     | 0.2                |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_03: fopen(w+) pre-existing file try to write it.                      | 1      | 0      | OK     | 0.41               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_04: fopen() with a filename exceeding the maximum length.             | 1      | 0      | OK     | 0.11               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_06: fopen() with bad filenames (minimal).                             | 1      | 0      | OK     | 0.1                |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_07: fopen()/errno handling.                                           | 1      | 0      | OK     | 0.07               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_08: ferror()/clearerr()/errno handling.                               | 1      | 0      | OK     | 0.1                |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_09: ftell() handling.                                                 | 1      | 0      | OK     | 0.17               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_10: remove() test.                                                    | 1      | 0      | OK     | 1.28               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_11: rename().                                                         | 1      | 0      | OK     | 2.3                |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_12: opendir(), readdir(), closedir() test.                            | 1      | 0      | OK     | 3.57               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_13: mkdir() test.                                                     | 1      | 0      | OK     | 1.21               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_14: stat() test.                                                      | 1      | 0      | OK     | 1.47               |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_15: format() test.                                                    | 1      | 0      | OK     | 26.12              |
+	| K64F-GCC_ARM | K64F          | sd-driver-features-tests-filesystem-fopen | FSFAT_FOPEN_TEST_16: write/check n x 25kB data files.                                  | 1      | 0      | OK     | 87.11              |
+	+--------------+---------------+-------------------------------------------+----------------------------------------------------------------------------------------+--------+--------+--------+--------------------+
+	mbedgt: test case results: 15 OK
+	mbedgt: completed in 152.35 sec
+    
+
+# <a name="summary-posix-api-documentation"></a> Summary of POSIX File API Documentation
+
+### POSIX File API
+
+mbed OS supports a subset of the POSIX File API, as outlined below:
+
+- [clearerr()](https://linux.die.net/man/3/clearerr).
+    - STATUS: Basic testing implemented. Working.
+- [fclose()](https://linux.die.net/man/3/fclose).
+    - STATUS: Basic testing implemented. Working.
+- [ferror()](https://linux.die.net/man/3/clearerr).
+    - STATUS: Basic testing implemented. 
+    - STATUS: GCC_ARM: Working. 
+    - STATUS: ARMCC: ARMCC has problem with ferror(filep) where filep is NULL. Appears to work for non-NULL pointer.
+- [fgetc()](https://linux.die.net/man/3/fgets).
+    - STATUS: Basic testing implemented. Working.
+- [fgets()](https://linux.die.net/man/3/fgets).
+    - STATUS: Basic testing implemented. Working.
+- [fputc()](https://linux.die.net/man/3/fputs).
+    - STATUS: Unknown.
+- [fputs()](https://linux.die.net/man/3/fputs).
+    - STATUS: Basic testing implemented. Working.
+- [fprintf()](https://linux.die.net/man/3/fprintf).
+    - STATUS: Basic testing implemented. Working.
+- [fopen()](https://linux.die.net/man/3/fopen).
+    - STATUS: Basic testing implemented. Working. 
+- [freopen()](https://linux.die.net/man/3/fopen).
+    - STATUS: This is not tested.
+- [fread()](https://linux.die.net/man/3/fread).
+    - STATUS: Basic testing implemented. Working.
+    - STATUS: n x 25kB stress test working.
+- [ftell()](https://linux.die.net/man/3/ftell).
+    - STATUS: Basic testing implemented. Working.
+- [fwrite()](https://linux.die.net/man/3/fwrite).
+    - STATUS: Basic testing implemented. Working.
+    - STATUS: n x 25kB stress test working.
+- [fseek()](https://linux.die.net/man/3/fseek)
+    - STATUS: Basic testing implemented. Working.
+- [getc()](https://linux.die.net/man/3/fgets).
+    - STATUS: Basic testing implemented. Working.
+- [gets()](https://linux.die.net/man/3/fgets).
+    - STATUS: Unknown.
+- [putc()](https://linux.die.net/man/3/fputs).
+    - STATUS: Unknown.
+- [puts()](https://linux.die.net/man/3/fputs).
+    - STATUS: Unknown.
+- [remove()](https://linux.die.net/man/3/remove)
+    - STATUS: Basic testing implemented. Working.
+- [rewind()](https://linux.die.net/man/3/rewind).
+    - STATUS: Basic testing implemented. Working. 
+- [stat()](https://linux.die.net/man/2/stat)
+    - STATUS: Implemented. Working.
+    - STATUS: Not supported by ARMCC/IAR libc.
+- [tmpfile()](https://linux.die.net/man/3/tmpfile).
+    - STATUS: Not implemented.
+- [tmpnam()](https://linux.die.net/man/3/tmpnam). 
+    - STATUS: Not implemented.
+
+Supported directory related operations are as follows:
+
+- [closedir()](https://linux.die.net/man/3/closedir).
+    - STATUS: Implemented. Working.
+- [mkdir()](https://linux.die.net/man/3/mkdir). 
+    - STATUS: Basic testing implemented. Working.
+- [opendir()](https://linux.die.net/man/3/opendir). 
+    - STATUS: Implemented. Working.
+- [readdir()](https://linux.die.net/man/3/readdir).
+    - STATUS: Implemented. Working.
+- [remove()](https://linux.die.net/man/3/remove).
+    - STATUS: Basic testing implemented. Working.
+- [rename()](https://linux.die.net/man/3/rename).
+    - STATUS: Implemented. Not tested.
+- [rewinddir()](https://linux.die.net/man/3/rewinddir).
+    - STATUS: Implemented. Found not to work. Test case not present in repo.
+- [seekdir()](https://linux.die.net/man/3/seekdir).
+    - STATUS: Implemented. Found not to work. Test case not present in repo. 
+- [telldir()](https://linux.die.net/man/3/telldir).
+    - STATUS: Implemented. Found not to work. Test case not present in repo.
+
+### errno 
+
+Basic errno reporting is supported, tested and known to be working.
+
+
+# Related Projects Resources
+
+The following are related mbed storage projects and useful resources:
+
+- The [mbed-os](https://github.com/ARMmbed/mbed-os) main repository.
+- The [mbed-os-example-fat-filesystem](https://github.com/ARMmbed/mbed-os-example-fat-filesystem) repository.
+  This is an example project for the mbed OS FAT filesystem.
+- The [spiflash-driver](https://github.com/armmbed/spiflash-driver) repository.
+- The [i2ceeprom-driver](https://github.com/ARMmbed/i2ceeprom-driver.git) repository.
+- The [ci-test-shield](https://github.com/ARMmbed/ci-test-shield)  repository. This is the project describing 
+  the mbed-os Continuous Integration test shield, together with standard tests.
+- The [mbed-HDK](https://github.com/ARMmbed/mbed-HDK) repository containing Hardware Development Kit resources
+  including the schematics for the CI test shield. 
+- [POSIX File Interface ISO/IEC 9899:TC2 Documentation](http://www.eng.utah.edu/~cs5785/slides-f10/n1124.pdf).
+- [FATFS: Generic FAT File System Module used in mbed OS](http://elm-chan.org/fsw/ff/00index_e.html)
+
+
diff -r 000000000000 -r a1734fe1ec4b sd-driver/config/mbed_app.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/config/mbed_app.json	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,130 @@
+{
+    "config": {
+        "UART_RX": "D0",
+        "UART_TX": "D1",
+        "DIO_0": "D0",
+        "DIO_1": "D1",
+        "DIO_2": "D2",
+        "DIO_3": "D3",
+        "DIO_4": "D4",
+        "DIO_5": "D5",
+        "DIO_6": "D6",
+        "DIO_7": "D7",
+        "DIO_8": "D8",
+        "DIO_9": "D9",
+        "SPI_CS": "D10",
+        "SPI_MOSI": "D11",
+        "SPI_MISO": "D12",
+        "SPI_CLK": "D13",
+        "I2C_SDA": "D14",
+        "I2C_SCL": "D15",
+        "I2C_TEMP_ADDR":"0x90",
+        "I2C_EEPROM_ADDR":"0xA0",
+        "AIN_0": "A0",
+        "AIN_1": "A1",
+        "AIN_2": "A2",
+        "AIN_3": "A3",
+        "AIN_4": "A4",
+        "AIN_5": "A5",
+        "AOUT" : "A5",
+        "PWM_0": "D3",
+        "PWM_1": "D5",
+        "PWM_2": "D6",
+        "PWM_3": "D9",
+        "DEBUG_MSG": 0,
+        "DEVICE_SPI": 1,
+        "FSFAT_SDCARD_INSTALLED": 1
+    },
+    "target_overrides": {
+        "DISCO_F051R8": {
+             "SPI_MOSI": "SPI_MOSI",
+             "SPI_MISO": "SPI_MISO",
+             "SPI_CLK":  "SPI_SCK",
+             "SPI_CS":   "SPI_CS"
+        },
+        "K20D50M": {
+             "SPI_MOSI": "PTD2",
+             "SPI_MISO": "PTD3",
+             "SPI_CLK":  "PTD1",
+             "SPI_CS":   "PTC2"
+        },
+        "KL22F": {
+             "SPI_MOSI": "PTD6",
+             "SPI_MISO": "PTD7",
+             "SPI_CLK":  "PTD5",
+             "SPI_CS":   "PTD4"
+        },
+        "KL25Z": {
+             "SPI_MOSI": "PTD2",
+             "SPI_MISO": "PTD3",
+             "SPI_CLK":  "PTD1",
+             "SPI_CS":   "PTD0"
+        },
+        "KL43Z": {
+             "SPI_MOSI": "PTD6",
+             "SPI_MISO": "PTD7",
+             "SPI_CLK":  "PTD5",
+             "SPI_CS":   "PTD4"
+        },
+        "KL46Z": {
+             "SPI_MOSI": "PTD6",
+             "SPI_MISO": "PTD7",
+             "SPI_CLK":  "PTD5",
+             "SPI_CS":   "PTD4"
+        },
+        "K64F": {
+             "SPI_MOSI": "PTE3",
+             "SPI_MISO": "PTE1",
+             "SPI_CLK":  "PTE2",
+             "SPI_CS":   "PTE4"
+        },
+        "K66F": {
+             "SPI_MOSI": "PTE3",
+             "SPI_MISO": "PTE1",
+             "SPI_CLK":  "PTE2",
+             "SPI_CS":   "PTE4"
+        },
+        "LPC11U37H_401": {
+             "SPI_MOSI": "SDMOSI",
+             "SPI_MISO": "SDMISO",
+             "SPI_CLK":  "SDSCLK",
+             "SPI_CS":   "SDSSEL"
+        },
+        "LPC2368": {
+             "SPI_MOSI": "p11",
+             "SPI_MISO": "p12",
+             "SPI_CLK":  "p13",
+             "SPI_CS":   "p14"
+        },
+        "NUCLEO_L031K6": {
+             "SPI_MOSI": "SPI_MOSI",
+             "SPI_MISO": "SPI_MISO",
+             "SPI_CLK":  "SPI_SCK",
+             "SPI_CS":   "SPI_CS"
+        },
+        "NUMAKER_PFM_M453": {
+             "SPI_MOSI": "PD_13",
+             "SPI_MISO": "PD_14",
+             "SPI_CLK":  "PD_15",
+             "SPI_CS":   "PD_12"
+        },
+        "NUMAKER_PFM_NUC472": {
+             "SPI_MOSI": "PF_0",
+             "SPI_MISO": "PD_15",
+             "SPI_CLK":  "PD_14",
+             "SPI_CS":   "PD_13"
+        },
+        "nRF51822": {
+             "SPI_MOSI": "p12",
+             "SPI_MISO": "p13",
+             "SPI_CLK":  "p15",
+             "SPI_CS":   "p14"
+        },
+        "RZ_A1H": {
+             "SPI_MOSI": "P8_5",
+             "SPI_MISO": "P8_6",
+             "SPI_CLK":  "P8_3",
+             "SPI_CS":   "P8_4"
+        }
+    }
+}
diff -r 000000000000 -r a1734fe1ec4b sd-driver/docs/pics/sd_driver_k64_with_ci_test_shield.jpg
Binary file sd-driver/docs/pics/sd_driver_k64_with_ci_test_shield.jpg has changed
diff -r 000000000000 -r a1734fe1ec4b sd-driver/features/TESTS/examples/example1/example1.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/features/TESTS/examples/example1/example1.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,80 @@
+#include "mbed.h"
+#include "FATFileSystem.h"
+#include "SDBlockDevice.h"
+#include <stdio.h>
+#include <errno.h>
+/* mbed_retarget.h is included after errno.h so symbols are mapped to
+ * consistent values for all toolchains */
+#include "platform/mbed_retarget.h"
+
+
+SDBlockDevice sd(MBED_CONF_APP_SPI_MOSI, MBED_CONF_APP_SPI_MISO, MBED_CONF_APP_SPI_CLK, MBED_CONF_APP_SPI_CS);
+FATFileSystem fs("sd", &sd);
+
+void return_error(int ret_val){
+  if (ret_val)
+    printf("Failure. %d\n", ret_val);
+  else
+    printf("done.\n");
+}
+
+void errno_error(void* ret_val){
+  if (ret_val == NULL)
+    printf(" Failure. %d \n", errno);
+  else
+    printf(" done.\n");
+}
+
+int main()
+{
+	int error = 0;
+	printf("Welcome to the filesystem example.\n");
+
+	printf("Opening a new file, numbers.txt.");
+	FILE* fd = fopen("/sd/numbers.txt", "w+");
+	errno_error(fd);
+
+	for (int i = 0; i < 20; i++){
+		printf("Writing decimal numbers to a file (%d/20)\r", i);
+		fprintf(fd, "%d\n", i);
+	}
+	printf("Writing decimal numbers to a file (20/20) done.\n");
+
+	printf("Closing file.");
+	fclose(fd);
+	printf(" done.\n");
+
+	printf("Re-opening file read-only.");
+	fd = fopen("/sd/numbers.txt", "r");
+	errno_error(fd);
+
+	printf("Dumping file to screen.\n");
+	char buff[16] = {0};
+	while (!feof(fd)){
+		int size = fread(&buff[0], 1, 15, fd);
+		fwrite(&buff[0], 1, size, stdout);
+	}
+	printf("EOF.\n");
+
+	printf("Closing file.");
+	fclose(fd);
+	printf(" done.\n");
+
+	printf("Opening root directory.");
+	DIR* dir = opendir("/sd/");
+	errno_error(fd);
+
+	struct dirent* de;
+	printf("Printing all filenames:\n");
+	while((de = readdir(dir)) != NULL){
+		printf("  %s\n", &(de->d_name)[0]);
+	}
+
+	printf("Closeing root directory. ");
+	error = closedir(dir);
+	return_error(error);
+	printf("Filesystem Demo complete.\n");
+
+	while (true) {}
+}
+
diff -r 000000000000 -r a1734fe1ec4b sd-driver/features/TESTS/filesystem/basic/basic.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/features/TESTS/filesystem/basic/basic.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,923 @@
+/*
+ * mbed Microcontroller Library
+ * Copyright (c) 2006-2016 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/* The following copyright notice is reproduced from the glibc project
+ * REF_LICENCE_GLIBC
+ *
+ * Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the GNU C Library; see the file COPYING.LIB.  If
+ * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+ * Cambridge, MA 02139, USA.
+ */
+
+
+/** @file basic.cpp POSIX File API (stdio) test cases
+ *
+ * Consult the documentation under the test-case functions for
+ * a description of the individual test case.
+ *
+ * this file includes ports for the mbed 2 test cases from the following locations:
+ *  - https://github.com:/armmbed/mbed-os/features/unsupported/tests/mbed/dir_sd/main.cpp.
+ *  - https://github.com:/armmbed/mbed-os/features/unsupported/tests/mbed/file/main.cpp.
+ *  - https://github.com:/armmbed/mbed-os/features/unsupported/tests/mbed/sd/main.cpp
+ *  - https://github.com:/armmbed/mbed-os/features/unsupported/tests/mbed/sd_perf_handle/main.cpp
+ *  - https://github.com:/armmbed/mbed-os/features/unsupported/tests/mbed/sd_perf_stdio/main.cpp.
+ */
+
+#include "mbed.h"
+#include "mbed_config.h"
+#include "FATFileSystem.h"
+#include "SDBlockDevice.h"
+#include "test_env.h"
+#include "fsfat_debug.h"
+#include "fsfat_test.h"
+#include "utest/utest.h"
+#include "unity/unity.h"
+#include "greentea-client/test_env.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <algorithm>
+/* retarget.h is included after errno.h so symbols are mapped to
+ * consistent values for all toolchains */
+#include "platform/mbed_retarget.h"
+
+using namespace utest::v1;
+
+/* DEVICE_SPI
+ *  This symbol is defined in targets.json if the target has a SPI interface, which is required for SDCard support.
+ *
+ * MBED_CONF_APP_FSFAT_SDCARD_INSTALLED
+ *  For testing purposes, an SDCard must be installed on the target for the test cases in this file to succeed.
+ *  If the target has an SD card installed then the MBED_CONF_APP_FSFAT_SDCARD_INSTALLED will be generated
+ *  from the mbed_app.json, which includes the line
+ *    {
+ *    "config": {
+ *        "UART_RX": "D0",
+ *        <<< lines removed >>>
+ *        "DEVICE_SPI": 1,
+ *        "MBED_CONF_APP_FSFAT_SDCARD_INSTALLED": 1
+ *      },
+ *      <<< lines removed >>>
+ */
+#if defined(DEVICE_SPI) && defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED)
+
+#define FSFAT_BASIC_TEST_00      fsfat_basic_test_00
+#define FSFAT_BASIC_TEST_01      fsfat_basic_test_01
+#define FSFAT_BASIC_TEST_02      fsfat_basic_test_02
+#define FSFAT_BASIC_TEST_03      fsfat_basic_test_03
+#define FSFAT_BASIC_TEST_04      fsfat_basic_test_04
+#define FSFAT_BASIC_TEST_05      fsfat_basic_test_05
+#define FSFAT_BASIC_TEST_06      fsfat_basic_test_06
+#define FSFAT_BASIC_TEST_07      fsfat_basic_test_07
+#define FSFAT_BASIC_TEST_08      fsfat_basic_test_08
+#define FSFAT_BASIC_TEST_09      fsfat_basic_test_09
+#define FSFAT_BASIC_TEST_10      fsfat_basic_test_10
+
+#define FSFAT_BASIC_MSG_BUF_SIZE              256
+#define FSFAT_BASIC_TEST_05_TEST_STRING   "Hello World!"
+
+static const char *sd_file_path = "/sd/out.txt";
+static const char *sd_mount_pt = "sd";
+static const int FSFAT_BASIC_DATA_SIZE = 256;
+static char fsfat_basic_msg_g[FSFAT_BASIC_MSG_BUF_SIZE];
+static char fsfat_basic_buffer[1024];
+static const int FSFAT_BASIC_KIB_RW = 128;
+static Timer fsfat_basic_timer;
+static const char *fsfat_basic_bin_filename = "/sd/testfile.bin";
+static const char *fsfat_basic_bin_filename_test_08 = "testfile.bin";
+static const char *fsfat_basic_bin_filename_test_10 = "0:testfile.bin";
+
+
+
+SDBlockDevice sd(MBED_CONF_APP_SPI_MOSI, MBED_CONF_APP_SPI_MISO, MBED_CONF_APP_SPI_CLK, MBED_CONF_APP_SPI_CS);
+FATFileSystem fs(sd_mount_pt, &sd);
+
+#define FSFAT_BASIC_MSG(_buf, _max_len, _fmt, ...)   \
+  do                                                            \
+  {                                                             \
+      snprintf((_buf), (_max_len), (_fmt), __VA_ARGS__);        \
+  }while(0);
+
+/** @brief  fopen test case
+ *
+ * - open a file
+ * - generate random data items, write the item to the file and store a coy in a buffer for later use.
+ * - close the file.
+ * - open the file.
+ * - read the data items from the file and check they are the same as write.
+ * - close the file.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_00()
+{
+
+    uint8_t data_written[FSFAT_BASIC_DATA_SIZE] = { 0 };
+    bool read_result = false;
+    bool write_result = false;
+
+    // Fill data_written buffer with random data
+    // Write these data into the file
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    {
+        FSFAT_DBGLOG("%s:SD: Writing ... ", __func__);
+        FILE *f = fopen(sd_file_path, "w");
+        if (f) {
+            for (int i = 0; i < FSFAT_BASIC_DATA_SIZE; i++) {
+                data_written[i] = rand() % 0XFF;
+                fprintf(f, "%c", data_written[i]);
+            }
+            write_result = true;
+            fclose(f);
+        }
+        FSFAT_DBGLOG("[%s]\n", write_result ? "OK" : "FAIL");
+    }
+    TEST_ASSERT_MESSAGE(write_result == true, "Error: write_result is set to false.");
+
+    // Read back the data from the file and store them in data_read
+    {
+        FSFAT_DBGLOG("%s:SD: Reading data ... ", __func__);
+        FILE *f = fopen(sd_file_path, "r");
+        if (f) {
+            read_result = true;
+            for (int i = 0; i < FSFAT_BASIC_DATA_SIZE; i++) {
+                uint8_t data = fgetc(f);
+                if (data != data_written[i]) {
+                    read_result = false;
+                    break;
+                }
+            }
+            fclose(f);
+        }
+        FSFAT_DBGLOG("[%s]\n", read_result ? "OK" : "FAIL");
+    }
+    TEST_ASSERT_MESSAGE(read_result == true, "Error: read_result is set to false.");
+    return CaseNext;
+}
+
+
+/** @brief  test-fseek.c test ported from glibc project. See the licence at REF_LICENCE_GLIBC.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_01()
+{
+    FILE *fp, *fp1;
+    int i, j;
+    int ret = 0;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    fp = fopen (sd_file_path, "w+");
+    if (fp == NULL) {
+        FSFAT_DBGLOG("errno=%d\n", errno);
+        TEST_ASSERT_MESSAGE(false, "error");
+        return CaseNext;
+    }
+
+    for (i = 0; i < 256; i++) {
+        putc (i, fp);
+    }
+    /* FIXME: freopen() should open the specified file closing the first stream. As can be seen from the
+     * code below, the old file descriptor fp can still be used, and this should not happen.
+     */
+    fp1 = freopen (sd_file_path, "r", fp);
+    TEST_ASSERT_MESSAGE(fp1 == fp, "Error: cannot open file for reading");
+
+    for (i = 1; i <= 255; i++) {
+        ret = fseek (fp, (long) -i, SEEK_END);
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s:Error: fseek() failed (ret=%d).\n", __func__, (int) ret);
+        TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+
+        if ((j = getc (fp)) != 256 - i) {
+            FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: SEEK_END failed (j=%d)\n",  __func__, j);
+            TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
+        }
+        ret = fseek (fp, (long) i, SEEK_SET);
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_SET (ret=%d).\n", __func__, (int) ret);
+        TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+
+        if ((j = getc (fp)) != i) {
+            FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_SET (j=%d).\n", __func__, j);
+            TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+        }
+        if ((ret = fseek (fp, (long) i, SEEK_SET))) {
+            FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_SET (ret=%d).\n", __func__, (int) ret);
+            TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+        }
+        if ((ret = fseek (fp, (long) (i >= 128 ? -128 : 128), SEEK_CUR))) {
+            FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_CUR (ret=%d).\n", __func__, (int) ret);
+            TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+        }
+        if ((j = getc (fp)) != (i >= 128 ? i - 128 : i + 128)) {
+            FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_CUR (j=%d).\n", __func__, j);
+            TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+        }
+    }
+    fclose (fp);
+    remove(sd_file_path);
+    return CaseNext;
+}
+
+
+/** @brief  test_rdwr.c test ported from glibc project. See the licence at REF_LICENCE_GLIBC.
+ *
+ * WARNING: this test does not currently work. See WARNING comments below.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_02()
+{
+    static const char hello[] = "Hello, world.\n";
+    static const char replace[] = "Hewwo, world.\n";
+    static const size_t replace_from = 2, replace_to = 4;
+    const char *filename = sd_file_path;
+    char buf[BUFSIZ];
+    FILE *f;
+    int lose = 0;
+    int32_t ret = 0;
+    char *rets = NULL;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    f = fopen(filename, "w+");
+    if (f == NULL) {
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot open file for writing (filename=%s).\n", __func__, filename);
+        TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
+    }
+
+    ret = fputs(hello, f);
+    if (ret == EOF) {
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fputs() failed to write string to file (filename=%s, string=%s).\n", __func__, filename, hello);
+        TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
+    }
+
+    rewind(f);
+    rets = fgets(buf, sizeof(buf), f);
+    if (rets == NULL) {
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fgets() failed to get string from file (filename=%s).\n", __func__, filename);
+        TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
+    }
+    rets = NULL;
+
+    rewind(f);
+    ret = fputs(buf, f);
+    if (ret == EOF) {
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fputs() failed to write string to file (filename=%s, string=%s).\n", __func__, filename, buf);
+        TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
+    }
+
+    rewind(f);
+    {
+        register size_t i;
+        for (i = 0; i < replace_from; ++i)
+        {
+            int c = getc(f);
+            if (c == EOF)
+            {
+                FSFAT_DBGLOG("EOF at %u.\n", i);
+                lose = 1;
+                break;
+            }
+            else if (c != hello[i])
+            {
+                FSFAT_DBGLOG("Got '%c' instead of '%c' at %u.\n",
+                (unsigned char) c, hello[i], i);
+                lose = 1;
+                break;
+            }
+        }
+    }
+    /* WARNING: printf("%s: here1. (lose = %d)\n", __func__, lose); */
+    {
+        long int where = ftell(f);
+        if (where == replace_from)
+        {
+            register size_t i;
+            for (i = replace_from; i < replace_to; ++i) {
+                if (putc(replace[i], f) == EOF) {
+                    FSFAT_DBGLOG("putc('%c') got %s at %u.\n",
+                    replace[i], strerror(errno), i);
+                    lose = 1;
+                    break;
+                }
+                /* WARNING: The problem seems to be that putc() is not writing the 'w' chars into the file
+                 * FSFAT_DBGLOG("%s: here1.5. (char = %c, char as int=%d, ret=%d) \n", __func__, replace[i], (int) replace[i], ret);
+                 */
+            }
+        }
+        else if (where == -1L)
+        {
+            FSFAT_DBGLOG("ftell got %s (should be at %u).\n",
+            strerror(errno), replace_from);
+            lose = 1;
+        }
+        else
+        {
+            FSFAT_DBGLOG("ftell returns %ld; should be %u.\n", where, replace_from);
+            lose = 1;
+        }
+    }
+
+    if (!lose)
+    {
+        rewind(f);
+        memset(buf, 0, BUFSIZ);
+        if (fgets(buf, sizeof(buf), f) == NULL)
+        {
+            FSFAT_DBGLOG("fgets got %s.\n", strerror(errno));
+            lose = 1;
+        }
+        else if (strcmp(buf, replace))
+        {
+            FSFAT_DBGLOG("Read \"%s\" instead of \"%s\".\n", buf, replace);
+            lose = 1;
+        }
+    }
+
+    if (lose) {
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Test Failed. Losing file (filename=%s).\n", __func__, filename);
+        TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
+    }
+    remove(filename);
+    return CaseNext;
+}
+
+/** @brief  temptest.c test ported from glibc project. See the licence at REF_LICENCE_GLIBC.
+ *
+ * tmpnam() is currently not implemented
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_03()
+{
+    char *fn = NULL;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    fn = tmpnam((char *) NULL);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: appeared to generate a filename when function is not implemented.\n", __func__);
+    TEST_ASSERT_MESSAGE(fn == NULL, fsfat_basic_msg_g);
+    return CaseNext;
+}
+
+
+static bool fsfat_basic_fileno_check(const char *name, FILE *stream, int fd)
+{
+    /* ARMCC stdio.h currently does not define fileno() */
+#ifndef __ARMCC_VERSION
+    int sfd = fileno (stream);
+    FSFAT_DBGLOG("(fileno (%s) = %d) %c= %d\n", name, sfd, sfd == fd ? '=' : '!', fd);
+
+    if (sfd == fd) {
+        return true;
+    } else {
+        return false;
+    }
+#else
+    /* For ARMCC behave as though test had passed. */
+    return true;
+#endif  /* __ARMCC_VERSION */
+}
+
+/* defines for next test case */
+#ifndef STDIN_FILENO
+#define STDIN_FILENO     0
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO    1
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO    2
+#endif
+
+
+/** @brief  tst-fileno.c test ported from glibc project. See the licence at REF_LICENCE_GLIBC.
+ *
+ * WARNING: this test does not currently work. See WARNING comments below.
+ *
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_04()
+{
+    /* ARMCC stdio.h currently does not define fileno() */
+#ifndef __ARMCC_VERSION
+    int ret = -1;
+    ret = fsfat_basic_fileno_check("stdin", stdin, STDIN_FILENO);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: stdin does not have expected file number (expected=%d, fileno=%d.\n", __func__, stdin, fileno(stdin));
+    TEST_ASSERT_MESSAGE(ret == true, fsfat_basic_msg_g);
+
+    ret = fsfat_basic_fileno_check("stdout", stdout, STDOUT_FILENO);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: stdout does not have expected file number (expected=%d, fileno=%d.\n", __func__, stdout, fileno(stdout));
+    TEST_ASSERT_MESSAGE(ret == true, fsfat_basic_msg_g);
+
+    ret = fsfat_basic_fileno_check("stderr", stderr, STDERR_FILENO);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: stderr does not have expected file number (expected=%d, fileno=%d.\n", __func__, stderr, fileno(stderr));
+    TEST_ASSERT_MESSAGE(ret == true, fsfat_basic_msg_g);
+#endif  /* __ARMCC_VERSION */
+    return CaseNext;
+}
+
+
+/** @brief  basic test to opendir() on a directory.
+ *
+ * This test has been ported from armmbed/mbed-os/features/unsupported/tests/mbed/dir_sd/main.cpp.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_05()
+{
+    FILE *f;
+    char *str = FSFAT_BASIC_TEST_05_TEST_STRING;
+    char *buffer = (char *)malloc(sizeof(unsigned char) * strlen(FSFAT_BASIC_TEST_05_TEST_STRING));
+    int str_len = strlen(FSFAT_BASIC_TEST_05_TEST_STRING);
+    int ret = 0;
+
+    FSFAT_DBGLOG("%s:Write files\n", __func__);
+    char filename[32];
+    for (int i = 0; i < 10; i++) {
+        sprintf(filename, "/sd/test_%d.txt", i);
+        FSFAT_DBGLOG("Creating file: %s\n", filename);
+        f = fopen(filename, "w");
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fopen() failed.\n", __func__);
+        TEST_ASSERT_MESSAGE(f != NULL, fsfat_basic_msg_g);
+
+        ret = fprintf(f, str);
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: writing file.\n", __func__);
+        TEST_ASSERT_MESSAGE(ret == strlen(str), fsfat_basic_msg_g);
+
+        ret = fclose(f);
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fclose() failed.\n", __func__);
+        TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+    }
+
+    FSFAT_DBGLOG("%s:List files:\n", __func__);
+    DIR *d = opendir("/sd");
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: opendir() failed.\n", __func__);
+    TEST_ASSERT_MESSAGE(d != NULL, fsfat_basic_msg_g);
+
+    struct dirent *p;
+    while ((p = readdir(d)) != NULL)
+        FSFAT_DBGLOG("%s\n", p->d_name);
+    closedir(d);
+
+    return CaseNext;
+}
+
+
+/** @brief  basic test to write a file to sd card, and read it back again
+ *
+ * This test has been ported from armmbed/mbed-os/features/unsupported/tests/mbed/file/main.cpp.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_06()
+{
+    int ret = -1;
+    char mac[16];
+    mbed_mac_address(mac);
+    FSFAT_DBGLOG("mac address: %02x,%02x,%02x,%02x,%02x,%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+    FILE *f;
+    char *str = FSFAT_BASIC_TEST_05_TEST_STRING;
+    char *buffer = (char *)malloc(sizeof(unsigned char) * strlen(FSFAT_BASIC_TEST_05_TEST_STRING));
+    int str_len = strlen(FSFAT_BASIC_TEST_05_TEST_STRING);
+
+    f = fopen(sd_file_path, "w");
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fopen() failed.\n", __func__);
+    TEST_ASSERT_MESSAGE(f != NULL, fsfat_basic_msg_g);
+
+    ret = fprintf(f, str);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: writing file.\n", __func__);
+    TEST_ASSERT_MESSAGE(ret == strlen(str), fsfat_basic_msg_g);
+
+    ret = fclose(f);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fclose() failed.\n", __func__);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+
+    // Read
+    f = fopen(sd_file_path, "r");
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fopen() failed.\n", __func__);
+    TEST_ASSERT_MESSAGE(f != NULL, fsfat_basic_msg_g);
+
+    int n = fread(fsfat_basic_buffer, sizeof(unsigned char), str_len, f);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fread() failed.\n", __func__);
+    TEST_ASSERT_MESSAGE(n == str_len, fsfat_basic_msg_g);
+
+    ret = fclose(f);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fclose() failed.\n", __func__);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+
+    return CaseNext;
+}
+
+
+/** @brief  basic test to write a file to sd card.
+ *
+ * This test has been ported from armmbed/mbed-os/features/unsupported/tests/mbed/sd/main.cpp.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_07()
+{
+    uint8_t data_written[FSFAT_BASIC_DATA_SIZE] = { 0 };
+
+    // Fill data_written buffer with random data
+    // Write these data into the file
+    bool write_result = false;
+    {
+        FSFAT_DBGLOG("%s:SD: Writing ... ", __func__);
+        FILE *f = fopen(sd_file_path, "w");
+        if (f) {
+            for (int i = 0; i < FSFAT_BASIC_DATA_SIZE; i++) {
+                data_written[i] = rand() % 0XFF;
+                fprintf(f, "%c", data_written[i]);
+            }
+            write_result = true;
+            fclose(f);
+        }
+        FSFAT_DBGLOG("[%s]\n", write_result ? "OK" : "FAIL");
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: unexpected write failure.\n", __func__);
+        TEST_ASSERT_MESSAGE(write_result == true, fsfat_basic_msg_g);
+    }
+
+    // Read back the data from the file and store them in data_read
+    bool read_result = false;
+    {
+        FSFAT_DBGLOG("%s:SD: Reading data ... ", __func__);
+        FILE *f = fopen(sd_file_path, "r");
+        if (f) {
+            read_result = true;
+            for (int i = 0; i < FSFAT_BASIC_DATA_SIZE; i++) {
+                uint8_t data = fgetc(f);
+                if (data != data_written[i]) {
+                    read_result = false;
+                    break;
+                }
+            }
+            fclose(f);
+        }
+        FSFAT_DBGLOG("[%s]\n", read_result ? "OK" : "FAIL");
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: unexpected read failure.\n", __func__);
+        TEST_ASSERT_MESSAGE(read_result == true, fsfat_basic_msg_g);
+    }
+    return CaseNext;
+}
+
+
+static bool fsfat_basic_test_file_write_fhandle(const char *filename, const int kib_rw)
+{
+    int ret = -1;
+    File file;
+
+    ret = file.open(&fs, filename, O_WRONLY | O_CREAT | O_TRUNC);
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to open file.\n", __func__);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+
+    int byte_write = 0;
+    fsfat_basic_timer.start();
+    for (int i = 0; i < kib_rw; i++) {
+        ret = file.write(fsfat_basic_buffer, sizeof(fsfat_basic_buffer));
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to write to file.\n", __func__);
+        TEST_ASSERT_MESSAGE(ret == sizeof(fsfat_basic_buffer), fsfat_basic_msg_g);
+        byte_write++;
+    }
+    fsfat_basic_timer.stop();
+    file.close();
+    double test_time_sec = fsfat_basic_timer.read_us() / 1000000.0;
+    double speed = kib_rw / test_time_sec;
+    FSFAT_DBGLOG("%d KiB write in %.3f sec with speed of %.4f KiB/s\n", byte_write, test_time_sec, speed);
+    fsfat_basic_timer.reset();
+    return true;
+}
+
+
+static bool fsfat_basic_test_file_read_fhandle(const char *filename, const int kib_rw)
+{
+    int ret = -1;
+    File file;
+    ret = file.open(&fs, filename, O_RDONLY);
+
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to open file.\n", __func__);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
+
+    fsfat_basic_timer.start();
+    int byte_read = 0;
+    while (file.read(fsfat_basic_buffer, sizeof(fsfat_basic_buffer)) == sizeof(fsfat_basic_buffer)) {
+        byte_read++;
+    }
+    fsfat_basic_timer.stop();
+    file.close();
+    double test_time_sec = fsfat_basic_timer.read_us() / 1000000.0;
+    double speed = kib_rw / test_time_sec;
+    FSFAT_DBGLOG("%d KiB read in %.3f sec with speed of %.4f KiB/s\n", byte_read, test_time_sec, speed);
+    fsfat_basic_timer.reset();
+    return true;
+}
+
+
+static char fsfat_basic_test_random_char()
+{
+    return rand() % 100;
+}
+
+
+/** @brief  basic sd card performance test
+ *
+ * This test has been ported from armmbed/mbed-os/features/unsupported/tests/mbed/sd_perf_handle/main.cpp.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_08()
+{
+    // Test header
+    FSFAT_DBGLOG("\n%s:SD Card FileHandle Performance Test\n", __func__);
+    FSFAT_DBGLOG("File name: %s\n", fsfat_basic_bin_filename);
+    FSFAT_DBGLOG("Buffer size: %d KiB\n", (FSFAT_BASIC_KIB_RW * sizeof(fsfat_basic_buffer)) / 1024);
+
+    // Initialize buffer
+    srand(0);
+    char *buffer_end = fsfat_basic_buffer + sizeof(fsfat_basic_buffer);
+    std::generate (fsfat_basic_buffer, buffer_end, fsfat_basic_test_random_char);
+
+    bool result = true;
+    for (;;) {
+        FSFAT_DBGLOG("%s:Write test...\n", __func__);
+        if (fsfat_basic_test_file_write_fhandle(fsfat_basic_bin_filename_test_08, FSFAT_BASIC_KIB_RW) == false) {
+            result = false;
+            break;
+        }
+
+        FSFAT_DBGLOG("%s:Read test...\n", __func__);
+        if (fsfat_basic_test_file_read_fhandle(fsfat_basic_bin_filename_test_08, FSFAT_BASIC_KIB_RW) == false) {
+            result = false;
+            break;
+        }
+        break;
+    }
+    return CaseNext;
+}
+
+
+bool fsfat_basic_test_sf_file_write_stdio(const char *filename, const int kib_rw)
+{
+    int ret = -1;
+    FILE* file = fopen(filename, "w");
+
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to open file.\n", __func__);
+    TEST_ASSERT_MESSAGE(file != NULL, fsfat_basic_msg_g);
+
+    int byte_write = 0;
+    fsfat_basic_timer.start();
+    for (int i = 0; i < kib_rw; i++) {
+        ret = fwrite(fsfat_basic_buffer, sizeof(char), sizeof(fsfat_basic_buffer), file);
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to write to file.\n", __func__);
+        TEST_ASSERT_MESSAGE(ret == sizeof(fsfat_basic_buffer), fsfat_basic_msg_g);
+        byte_write++;
+    }
+    fsfat_basic_timer.stop();
+    fclose(file);
+    double test_time_sec = fsfat_basic_timer.read_us() / 1000000.0;
+    double speed = kib_rw / test_time_sec;
+    FSFAT_DBGLOG("%d KiB write in %.3f sec with speed of %.4f KiB/s\n", byte_write, test_time_sec, speed);
+    fsfat_basic_timer.reset();
+    return true;
+}
+
+
+bool fsfat_basic_test_sf_file_read_stdio(const char *filename, const int kib_rw)
+{
+    bool result = true;
+    FILE* file = fopen(filename, "r");
+
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to open file.\n", __func__);
+    TEST_ASSERT_MESSAGE(file != NULL, fsfat_basic_msg_g);
+    fsfat_basic_timer.start();
+    int byte_read = 0;
+    while (fread(fsfat_basic_buffer, sizeof(char), sizeof(fsfat_basic_buffer), file) == sizeof(fsfat_basic_buffer)) {
+        byte_read++;
+    }
+    fsfat_basic_timer.stop();
+    fclose(file);
+    double test_time_sec = fsfat_basic_timer.read_us() / 1000000.0;
+    double speed = kib_rw / test_time_sec;
+    FSFAT_DBGLOG("%d KiB read in %.3f sec with speed of %.4f KiB/s\n", byte_read, test_time_sec, speed);
+
+    fsfat_basic_timer.reset();
+    return true;
+}
+
+
+/** @brief  basic test to write a file to sd card.
+ *
+ * This test has been ported from armmbed/mbed-os/features/unsupported/tests/mbed/sd_perf_stdio/main.cpp.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_09()
+{
+    // Test header
+    FSFAT_DBGLOG("\n%s:SD Card Stdio Performance Test\n", __func__);
+    FSFAT_DBGLOG("File name: %s\n", fsfat_basic_bin_filename);
+    FSFAT_DBGLOG("Buffer size: %d KiB\n", (FSFAT_BASIC_KIB_RW * sizeof(fsfat_basic_buffer)) / 1024);
+
+    // Initialize buffer
+    srand(0);
+    char *buffer_end = fsfat_basic_buffer + sizeof(fsfat_basic_buffer);
+    std::generate (fsfat_basic_buffer, buffer_end, fsfat_basic_test_random_char);
+
+    bool result = true;
+    for (;;) {
+        FSFAT_DBGLOG("%s:Write test...\n", __func__);
+        if (fsfat_basic_test_sf_file_write_stdio(fsfat_basic_bin_filename, FSFAT_BASIC_KIB_RW) == false) {
+            result = false;
+            break;
+        }
+
+        FSFAT_DBGLOG("%s:Read test...\n", __func__);
+        if (fsfat_basic_test_sf_file_read_stdio(fsfat_basic_bin_filename, FSFAT_BASIC_KIB_RW) == false) {
+            result = false;
+            break;
+        }
+        break;
+    }
+    return CaseNext;
+}
+
+
+bool fsfat_basic_test_file_write_fatfs(const char *filename, const int kib_rw)
+{
+    FIL file;
+    FRESULT res = f_open(&file, filename, FA_WRITE | FA_CREATE_ALWAYS);
+
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to open file.\n", __func__);
+    TEST_ASSERT_MESSAGE(res == FR_OK, fsfat_basic_msg_g);
+
+    int byte_write = 0;
+    unsigned int bytes = 0;
+    fsfat_basic_timer.start();
+    for (int i = 0; i < kib_rw; i++) {
+        res = f_write(&file, fsfat_basic_buffer, sizeof(fsfat_basic_buffer), &bytes);
+        FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to write to file.\n", __func__);
+        TEST_ASSERT_MESSAGE(res == FR_OK, fsfat_basic_msg_g);
+        byte_write++;
+    }
+    fsfat_basic_timer.stop();
+    f_close(&file);
+    double test_time_sec = fsfat_basic_timer.read_us() / 1000000.0;
+    double speed = kib_rw / test_time_sec;
+    FSFAT_DBGLOG("%d KiB write in %.3f sec with speed of %.4f KiB/s\n", byte_write, test_time_sec, speed);
+    fsfat_basic_timer.reset();
+    return true;
+}
+
+bool fsfat_basic_test_file_read_fatfs(const char *filename, const int kib_rw)
+{
+    FIL file;
+    FRESULT res = f_open(&file, filename, FA_READ | FA_OPEN_EXISTING);
+
+    FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: failed to open file.\n", __func__);
+    TEST_ASSERT_MESSAGE(res == FR_OK, fsfat_basic_msg_g);
+
+    fsfat_basic_timer.start();
+    int byte_read = 0;
+    unsigned int bytes = 0;
+    do {
+        res = f_read(&file, fsfat_basic_buffer, sizeof(fsfat_basic_buffer), &bytes);
+        byte_read++;
+    } while (res == FR_OK && bytes == sizeof(fsfat_basic_buffer));
+    fsfat_basic_timer.stop();
+    f_close(&file);
+    double test_time_sec = fsfat_basic_timer.read_us() / 1000000.0;
+    double speed = kib_rw / test_time_sec;
+    FSFAT_DBGLOG("%d KiB read in %.3f sec with speed of %.4f KiB/s\n", byte_read, test_time_sec, speed);
+    fsfat_basic_timer.reset();
+    return true;
+}
+
+/** @brief  basic test to write a file to sd card.
+ *
+ * This test has been ported from armmbed/mbed-os/features/unsupported/tests/mbed/sd_perf_stdio/main.cpp.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_basic_test_10()
+{
+    // Test header
+    FSFAT_DBGLOG("\n%sSD Card FatFS Performance Test\n", __func__);
+    FSFAT_DBGLOG("File name: %s\n", fsfat_basic_bin_filename_test_10);
+    FSFAT_DBGLOG("Buffer size: %d KiB\n", (FSFAT_BASIC_KIB_RW * sizeof(fsfat_basic_buffer)) / 1024);
+
+    // Initialize buffer
+    srand(1);
+    char *buffer_end = fsfat_basic_buffer + sizeof(fsfat_basic_buffer);
+    std::generate (fsfat_basic_buffer, buffer_end, fsfat_basic_test_random_char);
+
+    bool result = true;
+    for (;;) {
+        FSFAT_DBGLOG("%s:Write test...\n", __func__);
+        if (fsfat_basic_test_file_write_fatfs(fsfat_basic_bin_filename_test_10, FSFAT_BASIC_KIB_RW) == false) {
+            result = false;
+            break;
+        }
+
+        FSFAT_DBGLOG("%s:Read test...\n", __func__);
+        if (fsfat_basic_test_file_read_fatfs(fsfat_basic_bin_filename_test_10, FSFAT_BASIC_KIB_RW) == false) {
+            result = false;
+            break;
+        }
+        break;
+    }
+    return CaseNext;
+}
+
+#else
+
+#define FSFAT_BASIC_TEST_00      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_01      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_02      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_03      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_04      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_05      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_06      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_07      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_08      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_09      fsfat_basic_test_dummy
+#define FSFAT_BASIC_TEST_10      fsfat_basic_test_dummy
+
+
+/** @brief  fsfat_basic_test_dummy    Dummy test case for testing when platform doesnt have an SDCard installed.
+ *
+ * @return success always
+ */
+static control_t fsfat_basic_test_dummy()
+{
+    printf("Null test\n");
+    return CaseNext;
+}
+
+#endif  /* defined(DEVICE_SPI) && defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED) */
+
+utest::v1::status_t greentea_setup(const size_t number_of_cases)
+{
+    GREENTEA_SETUP(300, "default_auto");
+    return greentea_test_setup_handler(number_of_cases);
+}
+
+
+Case cases[] = {
+           /*          1         2         3         4         5         6        7  */
+           /* 1234567890123456789012345678901234567890123456789012345678901234567890 */
+        Case("FSFAT_BASIC_TEST_00: fopen()/fgetc()/fprintf()/fclose() test.", FSFAT_BASIC_TEST_00),
+        Case("FSFAT_BASIC_TEST_01: fopen()/fseek()/fclose() test.", FSFAT_BASIC_TEST_01),
+        /* WARNING: Test case not working but currently not required for PAL support
+         * Case("FSFAT_BASIC_TEST_02: fopen()/fgets()/fputs()/ftell()/rewind()/remove() test.", FSFAT_BASIC_TEST_02) */
+        Case("FSFAT_BASIC_TEST_03: tmpnam() test.", FSFAT_BASIC_TEST_03),
+        Case("FSFAT_BASIC_TEST_04: fileno() test.", FSFAT_BASIC_TEST_04),
+        Case("FSFAT_BASIC_TEST_05: opendir() basic test.", FSFAT_BASIC_TEST_05),
+        Case("FSFAT_BASIC_TEST_06: fread()/fwrite() file to sdcard.", FSFAT_BASIC_TEST_06),
+        Case("FSFAT_BASIC_TEST_07: sdcard fwrite() file test.", FSFAT_BASIC_TEST_07),
+        Case("FSFAT_BASIC_TEST_08: FATFileSystem::read()/write() test.", FSFAT_BASIC_TEST_08),
+        Case("FSFAT_BASIC_TEST_09: POSIX FILE API fread()/fwrite() test.", FSFAT_BASIC_TEST_09),
+        Case("FSFAT_BASIC_TEST_10: ChanFS read()/write()) test.", FSFAT_BASIC_TEST_10),
+};
+
+
+/* Declare your test specification with a custom setup handler */
+Specification specification(greentea_setup, cases);
+
+int main()
+{
+    return !Harness::run(specification);
+}
diff -r 000000000000 -r a1734fe1ec4b sd-driver/features/TESTS/filesystem/fopen/fopen.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/features/TESTS/filesystem/fopen/fopen.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,1530 @@
+/*
+ * mbed Microcontroller Library
+ * Copyright (c) 2006-2016 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** @file fopen.cpp Test cases to POSIX file fopen() interface.
+ *
+ * Please consult the documentation under the test-case functions for
+ * a description of the individual test case.
+ */
+
+#include "mbed.h"
+#include "mbed_config.h"
+#include "SDBlockDevice.h"
+#include "FATFileSystem.h"
+#include "fsfat_debug.h"
+#include "fsfat_test.h"
+#include "utest/utest.h"
+#include "unity/unity.h"
+#include "greentea-client/test_env.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>     /*rand()*/
+#include <inttypes.h>
+#include <errno.h>
+/* mbed_retarget.h is included after errno.h so symbols are mapped to
+ * consistent values for all toolchains */
+#include "platform/mbed_retarget.h"
+
+/* This is needed for stat() test, but is not available on ARMCC.
+ * The following checks whether GCC_ARM compiler is being used because:
+ * - both the ARMCC compiler and the GCC_ARM compile define __GNUC__.
+ * - only the ARMCC compiler defines __ARMCC_VERSION.
+ * - hence if __ARMCC_VERSION is not defined and __GNUC__ is defined, it must be GCC_ARM. */
+#if ! defined(__ARMCC_VERSION) && defined(__GNUC__)
+#include <sys/stat.h>
+#endif
+using namespace utest::v1;
+
+/// @cond FSFAT_DOXYGEN_DISABLE
+#ifdef FSFAT_DEBUG
+#define FSFAT_FOPEN_GREENTEA_TIMEOUT_S     3000
+#else
+#define FSFAT_FOPEN_GREENTEA_TIMEOUT_S     1000
+#endif
+/// @endcond
+
+
+/* DEVICE_SPI
+ *  This symbol is defined in targets.json if the target has a SPI interface, which is required for SDCard support.
+ *
+ * MBED_CONF_APP_FSFAT_SDCARD_INSTALLED
+ *  For testing purposes, an SDCard must be installed on the target for the test cases in this file to succeed.
+ *  If the target has an SD card installed then the MBED_CONF_APP_FSFAT_SDCARD_INSTALLED will be generated
+ *  from the mbed_app.json, which includes the line
+ *    {
+ *    "config": {
+ *        "UART_RX": "D0",
+ *        <<< lines removed >>>
+ *        "DEVICE_SPI": 1,
+ *        "FSFAT_SDCARD_INSTALLED": 1
+ *      },
+ *  	<<< lines removed >>>
+ */
+#if defined(DEVICE_SPI) && defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED)
+
+static char fsfat_fopen_utest_msg_g[FSFAT_UTEST_MSG_BUF_SIZE];
+#define FSFAT_FOPEN_TEST_MOUNT_PT_NAME      "sd"
+#define FSFAT_FOPEN_TEST_MOUNT_PT_PATH      "/"FSFAT_FOPEN_TEST_MOUNT_PT_NAME
+#define FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1    64
+#define FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH 20
+static const char *sd_badfile_path = "/sd/badfile.txt";
+static const char *sd_testfile_path = "/sd/test.txt";
+
+SDBlockDevice sd(MBED_CONF_APP_SPI_MOSI, MBED_CONF_APP_SPI_MISO, MBED_CONF_APP_SPI_CLK, MBED_CONF_APP_SPI_CS);
+FATFileSystem fs("sd", &sd);
+
+#define FSFAT_FOPEN_TEST_01      fsfat_fopen_test_01
+#define FSFAT_FOPEN_TEST_02      fsfat_fopen_test_02
+#define FSFAT_FOPEN_TEST_03      fsfat_fopen_test_03
+#define FSFAT_FOPEN_TEST_04      fsfat_fopen_test_04
+#define FSFAT_FOPEN_TEST_05      fsfat_fopen_test_05
+#define FSFAT_FOPEN_TEST_06      fsfat_fopen_test_06
+#define FSFAT_FOPEN_TEST_07      fsfat_fopen_test_07
+#define FSFAT_FOPEN_TEST_08      fsfat_fopen_test_08
+#define FSFAT_FOPEN_TEST_09      fsfat_fopen_test_09
+#define FSFAT_FOPEN_TEST_10      fsfat_fopen_test_10
+#define FSFAT_FOPEN_TEST_11      fsfat_fopen_test_11
+#define FSFAT_FOPEN_TEST_12      fsfat_fopen_test_12
+#define FSFAT_FOPEN_TEST_13      fsfat_fopen_test_13
+#define FSFAT_FOPEN_TEST_14      fsfat_fopen_test_14
+#define FSFAT_FOPEN_TEST_15      fsfat_fopen_test_15
+#define FSFAT_FOPEN_TEST_16      fsfat_fopen_test_16
+#define FSFAT_FOPEN_TEST_17      fsfat_fopen_test_17
+#define FSFAT_FOPEN_TEST_18      fsfat_fopen_test_18
+#define FSFAT_FOPEN_TEST_19      fsfat_fopen_test_19
+#define FSFAT_FOPEN_TEST_20      fsfat_fopen_test_20
+#define FSFAT_FOPEN_TEST_21      fsfat_fopen_test_21
+#define FSFAT_FOPEN_TEST_22      fsfat_fopen_test_22
+#define FSFAT_FOPEN_TEST_23      fsfat_fopen_test_23
+#define FSFAT_FOPEN_TEST_24      fsfat_fopen_test_24
+#define FSFAT_FOPEN_TEST_25      fsfat_fopen_test_25
+#define FSFAT_FOPEN_TEST_26      fsfat_fopen_test_26
+#define FSFAT_FOPEN_TEST_27      fsfat_fopen_test_27
+#define FSFAT_FOPEN_TEST_28      fsfat_fopen_test_28
+#define FSFAT_FOPEN_TEST_29      fsfat_fopen_test_29
+#define FSFAT_FOPEN_TEST_30      fsfat_fopen_test_30
+
+
+/* support functions */
+
+/*
+ * open tests that focus on testing fopen()
+ * fsfat_handle_t fopen(const char* filename, char* data, size_t* len, fsfat_key_desc_t* kdesc)
+ */
+
+/* file data for test_01 */
+static fsfat_kv_data_t fsfat_fopen_test_01_kv_data[] = {
+        { "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt", "missing"},
+        { NULL, NULL},
+};
+
+
+/** @brief
+ * Split a file path into its component parts, setting '/' characters to '\0', and returning
+ * pointers to the file path components in the parts array. For example, if
+ * filepath = "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt" then
+ *  *parts[0] = "sd"
+ *  *parts[1] = "fopentst"
+ *  *parts[2] = "hello"
+ *  *parts[3] = "world"
+ *  *parts[4] = "animal"
+ *  *parts[5] = "wobbly"
+ *  *parts[6] = "dog"
+ *  *parts[7] = "foot"
+ *  *parts[8] = "frontlft.txt"
+ *   parts[9] = NULL
+ *
+ * ARGUMENTS
+ *  @param  filepath     IN file path string to split into component parts. Expected to start with '/'
+ *  @param  parts        IN OUT array to hold pointers to parts
+ *  @param  num          IN number of components available in parts
+ *
+ * @return  On success, this returns the number of components in the filepath Returns number of compoee
+ */
+static int32_t fsfat_filepath_split(char* filepath, char* parts[], uint32_t num)
+{
+    uint32_t i = 0;
+    int32_t ret = -1;
+    char* z = filepath;
+
+    while (i < num && *z != '\0') {
+        if (*z == '/' ) {
+            *z = '\0';
+            parts[i] = ++z;
+            i++;
+        } else {
+            z++;
+        }
+    }
+    if (*z == '\0' && i > 0) {
+        ret = (int32_t) i;
+    }
+    return ret;
+}
+
+
+/** @brief
+ * remove all directories and file in the given filepath
+ *
+ * ARGUMENTS
+ *  @param  filepath     IN file path string to split into component parts. Expected to start with '/'
+ *
+ * @return  On success, this returns 0, otherwise < 0 is returned;
+ */
+int32_t fsfat_filepath_remove_all(char* filepath)
+{
+    int32_t ret = -1;
+    int32_t len = 0;
+    char *fpathbuf = NULL;
+    char *pos = NULL;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    len = strlen(filepath);
+    fpathbuf = (char*) malloc(len+1);
+    if (fpathbuf == NULL) {
+        FSFAT_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__);
+        return ret;
+    }
+    memset(fpathbuf, 0, len+1);
+    memcpy(fpathbuf, filepath, len);
+
+    /* delete the leaf node first, and then successively parent directories. */
+    pos = fpathbuf + strlen(fpathbuf);
+    while (pos != fpathbuf) {
+        /* If the remaining file path is the mount point path then finish as the mount point cannot be removed */
+        if (strlen(fpathbuf) == strlen(FSFAT_FOPEN_TEST_MOUNT_PT_PATH) && strncmp(fpathbuf, FSFAT_FOPEN_TEST_MOUNT_PT_PATH, strlen(fpathbuf)) == 0) {
+            break;
+        }
+        ret = remove(fpathbuf);
+        pos = strrchr(fpathbuf, '/');
+        *pos = '\0';
+    }
+    if (fpathbuf) {
+        free(fpathbuf);
+    }
+    return ret;
+}
+
+
+/** @brief
+ * make all directories in the given filepath. Do not create the file if present at end of filepath
+ *
+ * ARGUMENTS
+ *  @param  filepath     IN file path containing directories and file
+ *  @param  do_asserts   IN set to true if function should assert on errors
+ *
+ * @return  On success, this returns 0, otherwise < 0 is returned;
+ */
+static int32_t fsfat_filepath_make_dirs(char* filepath, bool do_asserts)
+{
+    int32_t i = 0;
+    int32_t num_parts = 0;
+    int32_t len = 0;
+    int32_t ret = -1;
+    char *fpathbuf = NULL;
+    char *buf = NULL;
+    int pos = 0;
+    char *parts[FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH];
+
+    FSFAT_DBGLOG("%s:entered\n", __func__);
+    /* find the dirs to create*/
+    memset(parts, 0, sizeof(parts));
+    len = strlen(filepath);
+    fpathbuf = (char*) malloc(len+1);
+    if (fpathbuf == NULL) {
+        FSFAT_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__);
+        return ret;
+    }
+    memset(fpathbuf, 0, len+1);
+    memcpy(fpathbuf, filepath, len);
+    num_parts = fsfat_filepath_split(fpathbuf, parts, FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to split filepath (filename=\"%s\", num_parts=%d)\n", __func__, filepath, (int) num_parts);
+    TEST_ASSERT_MESSAGE(num_parts > 0, fsfat_fopen_utest_msg_g);
+
+    /* Now create the directories on the directory path.
+     * Skip creating dir for "/sd" which must be present */
+    buf = (char*) malloc(strlen(filepath)+1);
+    memset(buf, 0, strlen(filepath)+1);
+    pos = sprintf(buf, "/%s", parts[0]);
+    for (i = 1; i < num_parts - 1; i++) {
+        pos += sprintf(buf+pos, "/%s", parts[i]);
+        FSFAT_DBGLOG("mkdir(%s)\n", buf);
+        ret = mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+        if (do_asserts == true) {
+            FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create directory (filepath2=\"%s\", ret=%d, errno=%d)\n", __func__, buf, (int) ret, errno);
+            TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+        }
+    }
+
+    if (buf) {
+        free(buf);
+    }
+    if (fpathbuf) {
+        free(fpathbuf);
+    }
+    return ret;
+}
+
+
+/* FIX ME: errno not set correctly when error occurs. This indicates a problem with the implementation. */
+
+/** @brief
+ * Basic fopen test which does the following:
+ * - creates file and writes some data to the value blob.
+ * - closes the newly created file.
+ * - opens the file (r-only)
+ * - reads the file data and checks its the same as the previously created data.
+ * - closes the opened file
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+static control_t fsfat_fopen_test_01(const size_t call_count)
+{
+    char* read_buf;
+    int32_t ret = 0;
+    size_t len = 0;
+    fsfat_kv_data_t *node;
+    FILE *fp = NULL;
+
+    FSFAT_DBGLOG("%s:entered\n", __func__);
+    (void) call_count;
+    node = fsfat_fopen_test_01_kv_data;
+
+    /* remove file and directory from a previous failed test run, if present */
+    fsfat_filepath_remove_all((char*) node->filename);
+
+    /* create dirs */
+    ret = fsfat_filepath_make_dirs((char*) node->filename, true);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    FSFAT_DBGLOG("%s:About to create new file (filename=\"%s\", data=\"%s\")\n", __func__, node->filename, node->value);
+    fp = fopen(node->filename, "w+");
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (filename=\"%s\", data=\"%s\")(ret=%d, errno=%d)\n", __func__, node->filename, node->value, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g);
+
+    FSFAT_DBGLOG("%s:length of file=%d (filename=\"%s\", data=\"%s\")\n", __func__, (int) len, node->filename, node->value);
+    len = strlen(node->value);
+    ret = fwrite((const void*) node->value, len, 1, fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write file (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, node->value, (int) ret);
+    TEST_ASSERT_MESSAGE(ret == 1, fsfat_fopen_utest_msg_g);
+
+    FSFAT_DBGLOG("Created file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value);
+    ret = fclose(fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    /* now open the newly created key */
+    fp = NULL;
+    fp = fopen(node->filename, "r");
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open file for reading (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, node->value, (int) ret);
+    TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g);
+
+    len = strlen(node->value) + 1;
+    read_buf = (char*) malloc(len);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to allocated read buffer \n", __func__);
+    TEST_ASSERT_MESSAGE(read_buf != NULL, fsfat_fopen_utest_msg_g);
+
+    FSFAT_DBGLOG("Opened file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value);
+    memset(read_buf, 0, len);
+    ret = fread((void*) read_buf, len, 1, fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to read file (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", __func__, node->filename, node->value, read_buf, (int) ret);
+    /* FIX ME: fread should return the number of items read, not 0 when an item is read successfully.
+     * This indicates a problem with the implementation, as the correct data is read. The correct assert should be:
+     *   TEST_ASSERT_MESSAGE(ret == 1, fsfat_fopen_utest_msg_g);
+     * The following assert is curerntly used until the implementation is fixed
+     */
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    /* check read data is as expected */
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: read value data (%s) != expected value data (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", __func__, read_buf, node->filename, node->value, read_buf, (int) ret);
+    TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, fsfat_fopen_utest_msg_g);
+
+    if(read_buf){
+        free(read_buf);
+    }
+    ret = fclose(fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed (ret=%d, errno=%d).\n", __func__, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+    return CaseNext;
+}
+
+static fsfat_kv_data_t fsfat_fopen_test_02_data[] = {
+        FSFAT_INIT_1_TABLE_MID_NODE,
+        { NULL, NULL},
+};
+
+/**
+ * @brief   test to fopen() a pre-existing key and try to write it, which should fail
+ *          as by default pre-existing keys are opened read-only
+ *
+ * Basic open test which does the following:
+ * - creates file with default rw perms and writes some data to the value blob.
+ * - closes the newly created file.
+ * - opens the file with the default permissions (read-only)
+ * - tries to write the file data which should fail because file was not opened with write flag set.
+ * - closes the opened key
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_02(const size_t call_count)
+{
+    int32_t ret = -1;
+    size_t len = 0;
+    FILE *fp = NULL;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+    len = strlen(fsfat_fopen_test_02_data[0].value);
+    ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char*) fsfat_fopen_test_02_data[0].value, len);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    /* by default, owner of key opens with read-only permissions*/
+    fp = fopen(fsfat_fopen_test_02_data[0].filename, "r");
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open file (filename=\"%s\", ret=%d)\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret);
+    TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g);
+
+    len = strlen(fsfat_fopen_test_02_data[0].value);
+    ret = fwrite((const void*) fsfat_fopen_test_02_data[0].value, len, 1, fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: call to fwrite() succeeded when should have failed for read-only file (filename=\"%s\")(ret=%d).\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret);
+    TEST_ASSERT_MESSAGE(ret <= 0, fsfat_fopen_utest_msg_g);
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed.\n", __func__);
+    TEST_ASSERT_MESSAGE(fclose(fp) == 0, fsfat_fopen_utest_msg_g);
+
+    return CaseNext;
+}
+
+
+/**
+ * @brief   test to fopen() a pre-existing file and try to write it, which should succeed
+ *          because the key was opened read-write permissions explicitly
+ *
+ * Basic open test which does the following:
+ * - creates file with default rw perms and writes some data to the value blob.
+ * - closes the newly created file.
+ * - opens the file with the rw permissions (non default)
+ * - tries to write the file data which should succeeds because file was opened with write flag set.
+ * - closes the opened key
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_03(const size_t call_count)
+{
+    int32_t ret = -1;
+    size_t len = 0;
+    FILE *fp = NULL;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+    len = strlen(fsfat_fopen_test_02_data[0].value);
+    ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char*) fsfat_fopen_test_02_data[0].value, len);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file in store (ret=%d).\n", __func__, (int) ret);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    /* opens with read-write permissions*/
+    fp = fopen(fsfat_fopen_test_02_data[0].filename, "w+");
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open file (filename=\"%s\")(ret=%d)\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    len = strlen(fsfat_fopen_test_02_data[0].value);
+    ret = fwrite((const void*) fsfat_fopen_test_02_data[0].value, len, 1, fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: call to fwrite() failed when should have succeeded (filename=\"%s\", ret=%d).\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed.\n", __func__);
+    TEST_ASSERT_MESSAGE(fclose(fp) >= 0, fsfat_fopen_utest_msg_g);
+
+    /* clean-up */
+    ret = remove(fsfat_fopen_test_02_data[0].filename);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unable to delete file (filename=%s, ret=%d) .\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    return CaseNext;
+}
+
+
+/** @brief  test to call fopen() with a filename string that exceeds the maximum length
+ * - chanFS supports the exFAT format which should support 255 char filenames
+ * - check that filenames of this length can be created
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_04(const size_t call_count)
+{
+    char filename_good[FSFAT_FILENAME_MAX_LENGTH+1];
+    char filename_bad[FSFAT_FILENAME_MAX_LENGTH+2];
+    int32_t ret = -1;
+    size_t len = 0;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    memset(filename_good, 0, FSFAT_FILENAME_MAX_LENGTH+1);
+    memset(filename_bad, 0, FSFAT_FILENAME_MAX_LENGTH+2);
+    ret = fsfat_test_filename_gen(filename_good, FSFAT_FILENAME_MAX_LENGTH);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate filename_good.\n", __func__);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: filename_good is not the correct length (filename_good=%s, len=%d, expected=%d).\n", __func__, filename_good, (int) strlen(filename_good), (int) FSFAT_FILENAME_MAX_LENGTH);
+    TEST_ASSERT_MESSAGE(strlen(filename_good) == FSFAT_FILENAME_MAX_LENGTH, fsfat_fopen_utest_msg_g);
+
+    ret = fsfat_test_filename_gen(filename_bad, FSFAT_FILENAME_MAX_LENGTH+1);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate filename_bad.\n", __func__);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: filename_bad is not the correct length (len=%d, expected=%d).\n", __func__, (int) strlen(filename_bad), (int) FSFAT_FILENAME_MAX_LENGTH+1);
+    TEST_ASSERT_MESSAGE(strlen(filename_bad) == FSFAT_FILENAME_MAX_LENGTH+1, fsfat_fopen_utest_msg_g);
+
+    len = strlen(filename_good);
+    ret = fsfat_test_create(filename_good, filename_good, len);
+    /* FIXME:
+     * The current implementation can create file with a filename with 9 chars (more than the 8 restriction of FAT32 Short File Names).
+     * However, the exFAT 255 char filesnames is not supported and hence the following is commented out. Find out what is
+     * the supported max filename length and change this testcase according.
+     *
+     *  FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (filename=%s, ret=%d).\n", __func__, filename_good, (int) ret);
+     *  TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+     */
+
+    len = strlen(filename_bad);
+    ret = fsfat_test_create(filename_bad, filename_bad, len);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: created file in store for filename_bad when should have failed (filename=%s, ret=%d).\n", __func__, filename_bad, (int) ret);
+    TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g);
+    return CaseNext;
+}
+
+
+/// @cond FSFAT_DOXYGEN_DISABLE
+typedef struct fsfat_fopen_kv_name_ascii_node {
+    uint32_t code;
+    uint32_t f_allowed : 1;
+} fsfat_fopen_kv_name_ascii_node;
+/// @endcond
+
+static const uint32_t fsfat_fopen_kv_name_ascii_table_code_sentinel_g = 256;
+
+/*@brief    table recording ascii character codes permitted in kv names */
+static fsfat_fopen_kv_name_ascii_node fsfat_fopen_kv_name_ascii_table[] =
+{
+        {0 , true},         /* code 0-33 allowed*/
+        {34, false},        /* '"' not allowed */
+        {35, true},         /* allowed */
+        {42, false},        /* '*' not allowed */
+        {43, true},         /* allowed */
+        {47, false},        /* '/' not allowed */
+        {48, true},         /* allowed */
+        {58, false},        /* ':' not allowed */
+        {59, true},         /* allowed */
+        {60, false},        /* '<' not allowed */
+        {61, true},         /* allowed */
+        {62, false},        /* '?', '>' not allowed */
+        {64, true},         /* allowed */
+        {92, false},        /* '\' not allowed */
+        {93, true},         /* allowed */
+        {124, false},        /* '!' not allowed */
+        {125, true},         /* allowed */
+        {127, false},        /* DEL not allowed */
+        {128, true},         /* allowed */
+        {fsfat_fopen_kv_name_ascii_table_code_sentinel_g, false},       /* sentinel */
+};
+
+
+/// @cond FSFAT_DOXYGEN_DISABLE
+enum fsfat_fopen_kv_name_pos {
+    fsfat_fopen_kv_name_pos_start = 0x0,
+    fsfat_fopen_kv_name_pos_mid,
+    fsfat_fopen_kv_name_pos_end,
+    fsfat_fopen_kv_name_pos_max
+};
+/// @endcond
+
+/** @brief  test to call fopen() with filename that in includes illegal characters
+ *          - the character(s) can be at the beginning of the filename
+ *          - the character(s) can be at the end of the filename
+ *          - the character(s) can be somewhere within the filename string
+ *          - a max-length string of random characters (legal and illegal)
+ *          - a max-length string of random illegal characters only
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_05(const size_t call_count)
+{
+    bool f_allowed = false;
+    const char *mnt_pt = FSFAT_FOPEN_TEST_MOUNT_PT_PATH;
+    const char *basename = "goodfile";
+    const char *extname = "txt";
+    const size_t basename_len = strlen(basename);
+    const size_t filename_len = strlen(mnt_pt)+strlen(basename)+strlen(extname)+2;  /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */
+    char filename[FSFAT_BUF_MAX_LENGTH];
+    size_t len = 0;
+    uint32_t j = 0;
+    int32_t ret = 0;
+    fsfat_fopen_kv_name_ascii_node* node = NULL;
+    uint32_t pos;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+#ifdef FSFAT_DEBUG
+    /* symbol only used why debug is enabled */
+    const char* pos_str = NULL;
+#endif
+
+    /* create bad keyname strings with invalid character code at start of keyname */
+    node = fsfat_fopen_kv_name_ascii_table;
+    memset(filename, 0, FSFAT_BUF_MAX_LENGTH);
+    while(node->code !=  fsfat_fopen_kv_name_ascii_table_code_sentinel_g)
+    {
+        /* loop over range */
+        for(j = node->code; j < (node+1)->code; j++)
+        {
+            if( (j >= 48 && j <= 57) || (j >= 65 && j <= 90) || (j >= 97 && j <= 122)) {
+                FSFAT_DBGLOG("%s: skipping alpha-numeric ascii character code %d (%c).\n", __func__, (int) j, (char) j);
+                continue;
+            }
+
+            /* set the start, mid, last character of the name to the test char code */
+            for(pos = (uint32_t) fsfat_fopen_kv_name_pos_start; pos < (uint32_t) fsfat_fopen_kv_name_pos_max; pos++)
+            {
+                len = snprintf(filename, filename_len+1, "%s/%s.%s", mnt_pt, basename, extname);
+                /* overwrite a char at the pos start, mid, end of the filename with an ascii char code (both illegal and legal)*/
+                switch(pos)
+                {
+                case fsfat_fopen_kv_name_pos_start:
+                    filename[5] = (char) j; /* 5 so at to write the second basename char (bad chars as first char not accepted)*/
+                    break;
+                case fsfat_fopen_kv_name_pos_mid:
+                    /* create bad keyname strings with invalid character code in the middle of keyname */
+                    filename[5+basename_len/2] = (char) j;
+                    break;
+                case fsfat_fopen_kv_name_pos_end:
+                    /* create bad keyname strings with invalid character code at end of keyname */
+                    filename[5+basename_len-1] = (char) j;
+                    break;
+                default:
+                    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unexpected value of pos (pos=%d).\n", __func__, (int) pos);
+                    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+                    break;
+                }
+
+#ifdef FSFAT_DEBUG
+                /* processing only required when debug trace enabled */
+                switch(pos)
+                {
+                case fsfat_fopen_kv_name_pos_start:
+                    pos_str = "start";
+                    break;
+                case fsfat_fopen_kv_name_pos_mid:
+                    pos_str = "middle";
+                    break;
+                case fsfat_fopen_kv_name_pos_end:
+                    pos_str = "end";
+                    break;
+                default:
+                    break;
+                }
+#endif
+                ret = fsfat_test_create(filename, (const char*) filename, len);
+
+                /* special cases */
+                switch(j)
+                {
+                //case 0 :
+				//case 46 :
+                //    switch(pos)
+                //    {
+                //    /* for code = 0 (null terminator). permitted at mid and end of string */
+                //    /* for code = 46 ('.'). permitted at mid and end of string but not at start */
+                //    case fsfat_fopen_kv_name_pos_start:
+                //        f_allowed = false;
+                //        break;
+                //    case fsfat_fopen_kv_name_pos_mid:
+                //    case fsfat_fopen_kv_name_pos_end:
+                //    default:
+                //        f_allowed = true;
+                //        break;
+                //    }
+                //    break;
+				default:
+					f_allowed = node->f_allowed;
+					break;
+                }
+                if(f_allowed == true)
+                {
+                    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file in store when filename contains valid characters (code=%d, ret=%d).\n", __func__, (int) j, (int) ret);
+                    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+                    /* revert FSFAT_LOG for more trace */
+                    FSFAT_DBGLOG("Successfully created a file with valid keyname containing ascii character code %d (%c) at the %s of the keyname.\n", (int) j, (int) j, pos_str);
+                    FSFAT_LOG("%c", '.');
+
+                    ret = fsfat_test_delete(filename);
+                    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete file previously created (code=%d, ret=%d).\n", __func__, (int) j, (int) ret);
+                    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+                }
+                else
+                {   /*node->f_allowed == false => not allowed to create kv name with ascii code */
+                    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: created file in store when filename contains an invalid character (code=%d, ret=%d).\n", __func__, (int) j, (int) ret);
+                    TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g);
+                    /* revert FSFAT_LOG for more trace */
+                    FSFAT_DBGLOG("Successfully failed to create a file with an invalid keyname containing ascii character code %d at the %s of the keyname.\n", (int) j, pos_str);
+                    FSFAT_LOG("%c", '.');
+                }
+            }
+        }
+        node++;
+    }
+
+    FSFAT_LOG("%c", '\n');
+    return CaseNext;
+}
+
+
+static const char fsfat_fopen_ascii_illegal_buf_g[] = "\"�'*+,./:;<=>?[\\]|";
+
+/** @brief  test to call fopen() with filename that in includes
+ *          illegal characters
+ *          - a max-length string of random illegal characters only
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_06(const size_t call_count)
+{
+    const char *mnt_pt = FSFAT_FOPEN_TEST_MOUNT_PT_PATH;
+    const char *extname = "txt";
+    const size_t filename_len = strlen(mnt_pt)+FSFAT_MAX_FILE_BASENAME+strlen(extname)+2;  /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */
+    char filename[FSFAT_BUF_MAX_LENGTH];
+    int32_t i = 0;
+    int32_t j = 0;
+    uint32_t pos = 0;
+    uint32_t len = 0;
+    int32_t ret = -1;
+    size_t buf_data_max = 0;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    memset(filename, 0, FSFAT_BUF_MAX_LENGTH);
+    /* create bad keyname strings with invalid character code at start of keyname */
+    buf_data_max = strlen(fsfat_fopen_ascii_illegal_buf_g);
+
+    /* generate a number of illegal filenames */
+    for (j = 0; i < FSFAT_MAX_FILE_BASENAME; j++) {
+        /* generate a kv name of illegal chars*/
+        len = snprintf(filename, filename_len+1, "%s/", mnt_pt);
+        for (i = 0; i < FSFAT_MAX_FILE_BASENAME; i++) {
+            pos = rand() % (buf_data_max+1);
+            len += snprintf(filename+len, filename_len+1, "%c", fsfat_fopen_ascii_illegal_buf_g[pos]);
+
+        }
+        len += snprintf(filename+len, filename_len+1, ".%s", extname);
+        ret = fsfat_test_create(filename, filename, len);
+        FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: created file when filename contains invalid characters (filename=%s, ret=%d).\n", __func__, filename, (int) ret);
+        TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g);
+    }
+    return CaseNext;
+}
+
+
+/** @brief  test for errno reporting on a failed fopen()call
+ *
+ *	This test does the following:
+ *	- tries to open a file that does not exist for reading, and checks that a NULL pointer is returned.
+ *	- checks that errno is not 0 as there is an error.
+ *	- checks that ferror() returns 1 indicating an error exists.
+ *
+ * Note: see NOTE_1 below.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_07(const size_t call_count)
+{
+	FILE *f = NULL;
+	int ret = -1;
+    int errno_val = 0;
+    const char *filename = sd_badfile_path;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    errno = 0;
+    /* this is expect to fail as the file doesnt exist */
+    f = fopen(filename,"r");
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: opened non-existent file for reading (filename=%s, f=%p).\n", __func__, filename, f);
+    TEST_ASSERT_MESSAGE(f == NULL, fsfat_fopen_utest_msg_g);
+
+    /* check errno is set correctly */
+#if ! defined(__ARMCC_VERSION) && defined(__GNUC__)
+    /* Store errno so the current value set  is not changed by new function call */
+    errno_val = errno;
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: errno has unexpected value (errno != 0 expected) (filename=%s, errno=%d).\n", __func__, filename, errno);
+    TEST_ASSERT_MESSAGE(errno_val != 0, fsfat_fopen_utest_msg_g);
+
+    /* check ferror() returns non-zero indicating there is an error
+     * Note ARMCC appears to fault when null FILE* is supplied to ferror() */
+    ret = ferror(f);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: ferror() did not return non-zero value when error exists (filename=%s, ret=%d).\n", __func__, filename, (int) ret);
+    TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g);
+#endif  /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */
+    return CaseNext;
+}
+
+
+/** @brief  test for operation of clearerr() and ferror()
+ *
+ *  The test does the following:
+ *  - opens and then closes a file, but keeps a copy of the FILE pointer fp.
+ *  - set errno to 0.
+ *  - write to the close file with fwrite(fp) which should return 0 (no writes) and set the errno.
+ *  - check the error condition is set with ferror().
+ *  - clear the error with clearerr().
+ *  - check the error condition is reset with ferror().
+ *
+ * NOTE_1: GCC/ARMCC support for setting errno
+ *  - Documentation (e.g. fwrite() man page) does not explicity say fwrite() sets errno
+ *    (e.g. for an fwrite() on a read-only file).
+ *  - GCC libc fwrite() appears to set errno as expected.
+ *  - ARMCC & IAR libc fwrite() appears not to set errno.
+ *
+ * The following ARMCC documents are silent on whether fwrite() sets errno:
+ * - "ARM C and C++ Libraries and Floating-Point Support".
+ * - "RL-ARM User Guide fwrite() section".
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_08(const size_t call_count)
+{
+    FILE *fp = NULL;
+    int ret = -1;
+    int ret_ferror = -1;
+    const char *filename = sd_testfile_path;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    errno = 0;
+    fp = fopen(filename,"w+");
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open file (filename=%s, f=%p).\n", __func__, filename, fp);
+    TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g);
+
+    /* close the fp but then try to read or write it */
+    ret = fclose(fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    /* open file  */
+    errno = 0;
+    fp = fopen(filename, "r");
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open file for reading (filename=\"%s\", ret=%d)\n", __func__, filename, (int) ret);
+    TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g);
+
+    /* Perform fwrite() operation that will fail. */
+    errno = 0;
+    ret = fwrite("42!", 4, 1, fp);
+
+    ret_ferror = ferror(fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: ferror() failed to report error (filename=%s, ret_ferror=%d).\n", __func__, filename, (int) ret_ferror);
+    TEST_ASSERT_MESSAGE(ret_ferror != 0, fsfat_fopen_utest_msg_g);
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fwrite successfully wrote to read-only file (filename=%s, ret=%d).\n", __func__, filename, (int) ret);
+    /* the fwrite() should fail and return 0. */
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+#if ! defined(__ARMCC_VERSION) && defined(__GNUC__)
+    /* check that errno is set. ARMCC appears not to set errno for fwrite() failure. */
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unexpected zero value for errno (filename=%s, ret=%d, errno=%d).\n", __func__, filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(errno != 0, fsfat_fopen_utest_msg_g);
+
+    /* check that errno is set to the expected value (this may change differ for different libc's) */
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: errno != EBADF (filename=%s, ret=%d, errno=%d).\n", __func__, filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(errno == EBADF, fsfat_fopen_utest_msg_g);
+#endif  /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */
+
+    /* check clearerr() return clears the error */
+    clearerr(fp);
+    ret = ferror(fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: ferror() did not return zero value when error has been cleared (filename=%s, ret=%d).\n", __func__, filename, (int) ret);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    fclose(fp);
+    return CaseNext;
+}
+
+
+/** @brief  test for operation of ftell()
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_09(const size_t call_count)
+{
+    FILE *fp = NULL;
+    int ret = -1;
+    int32_t len = 0;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    /* create a file of a certain length */
+    len = strlen(fsfat_fopen_test_02_data[0].value);
+    ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char*) fsfat_fopen_test_02_data[0].value, len);
+
+    errno = 0;
+    /* Open the file for reading so the file is not truncated to 0 length. */
+    fp = fopen(fsfat_fopen_test_02_data[0].filename, "r");
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open file (filename=%s, fp=%p, errno=%d).\n", __func__, fsfat_fopen_test_02_data[0].filename, fp, errno);
+    TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g);
+
+    errno = 0;
+    ret = fseek(fp, 0, SEEK_END);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fseek() failed to SEEK_END (filename=%s, ret=%d, errno=%d).\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    errno = 0;
+    ret = ftell(fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: ftell() failed to report correct offset value (filename=%s, ret=%d, errno=%d).\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == len, fsfat_fopen_utest_msg_g);
+
+    errno = 0;
+    ret = fclose(fp);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    return CaseNext;
+}
+
+
+/* file data for test_10 */
+static fsfat_kv_data_t fsfat_fopen_test_10_kv_data[] = {
+        { "/sd/test_10/testfile.txt", "test_data"},
+        { NULL, NULL},
+};
+
+/** @brief  test for operation of remove()
+ *
+ * Performs the following tests:
+ *  1. test remove() on a file that exists. This should succeed.
+ *  2. test remove() on a dir that exists. This should succeed.
+ *  3. test remove() on a file that doesnt exist. This should fail. check errno set.
+ *  4. test remove() on a dir that doesnt exist. This should fail. check errno set.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_10(const size_t call_count)
+{
+    char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1];
+    char *pos = NULL;
+    int32_t ret = -1;
+    size_t len = 0;
+    fsfat_kv_data_t *node = fsfat_fopen_test_10_kv_data;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1);
+
+    /* start from a known state i.e. directory to be created in not present */
+    fsfat_filepath_remove_all((char*) node->filename);
+
+    /* (1) */
+    errno = 0;
+    ret = fsfat_filepath_make_dirs((char*) node->filename, false);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    len = strlen(node->value);
+    ret = fsfat_test_create(node->filename, (char*) node->value, len);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    ret = remove(node->filename);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: delete file operation failed (filename=%s, ret=%d) .\n", __func__, node->filename, (int) ret);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    /* (3) */
+    ret = remove(node->filename);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: deleted a file that doesn't exist (filename=%s, ret=%d, errno=%d) .\n", __func__, node->filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g);
+
+    /* (2) */
+    memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1);
+    memcpy(buf, node->filename, strlen(node->filename));
+    pos = strrchr(buf, '/');
+    *pos = '\0';
+    ret = remove(buf);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: delete directory operation failed (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    /* (4) */
+    ret = remove(buf);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: deleted a directory that doesn't exist (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g);
+
+    return CaseNext;
+}
+
+
+/* file data for test_11 */
+static fsfat_kv_data_t fsfat_fopen_test_11_kv_data[] = {
+        { "/sd/test_11/step0.txt", "test_data"},
+        { "/sd/test_11/step1.txt", "test_data"},
+        { "/sd/test_11/subdir/step3.txt", "test_data"},
+        { NULL, NULL},
+};
+
+/** @brief  test for operation of rename()
+ *
+ * This test does the following:
+ *  1) test rename() on a file that exists to a new filename within the same directory.
+ *  2) test rename() on a file that exists to a new filename within a different directory.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_11(const size_t call_count)
+{
+    int32_t ret = -1;
+    size_t len = 0;
+    fsfat_kv_data_t *node = fsfat_fopen_test_11_kv_data;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1);
+
+    /* start from a known state i.e. directory to be created in not present, files not present */
+    while(node->filename != NULL) {
+        fsfat_filepath_remove_all((char*) node->filename);
+        node++;
+    }
+
+    /* create file and directories ready for rename() tests */
+    errno = 0;
+    node = fsfat_fopen_test_11_kv_data;
+    ret = fsfat_filepath_make_dirs((char*) node->filename, false);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    len = strlen(node->value);
+    ret = fsfat_test_create(node->filename, (char*) node->value, len);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    errno = 0;
+    node = &fsfat_fopen_test_11_kv_data[2];
+    ret = fsfat_filepath_make_dirs((char*) node->filename, false);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    /* (1) */
+    ret = rename(fsfat_fopen_test_11_kv_data[0].filename, fsfat_fopen_test_11_kv_data[1].filename);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unable to rename file from (%s) to (%s) (ret=%d, errno=%d).\n", __func__, fsfat_fopen_test_11_kv_data[0].filename, fsfat_fopen_test_11_kv_data[1].filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    /* (2) */
+    ret = rename(fsfat_fopen_test_11_kv_data[1].filename, fsfat_fopen_test_11_kv_data[2].filename);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unable to rename file from (%s) to (%s) (ret=%d, errno=%d).\n", __func__, fsfat_fopen_test_11_kv_data[1].filename, fsfat_fopen_test_11_kv_data[2].filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    return CaseNext;
+}
+
+
+/* file data for test_12 */
+static fsfat_kv_data_t fsfat_fopen_test_12_kv_data[] = {
+        { "/sd/test_12/subdir/testfil1.txt", "testfil1.txt"},
+        { "/sd/test_12/testfil2.txt", "testfil2.txt"},
+        { "/sd/test_12/testfil3.txt", "testfil3.txt"},
+        { "/sd/test_12/testfil4.txt", "testfil4.txt"},
+        { "/sd/test_12/testfil5.txt", "testfil5.txt"},
+        { NULL, NULL},
+};
+
+/** @brief  test for operation of readdir().
+ *
+ * Note, rewinddir(), telldir() and seekdir() dont appear to work reliably.
+ * opendir() not available on ARM/IAR toolchains.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_12(const size_t call_count)
+{
+    char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1];
+    char *pos = NULL;
+    int32_t count = 0;
+    int32_t ret = -1;
+    size_t len = 0;
+    DIR *dir;
+    struct dirent *dp;
+    fsfat_kv_data_t *node = fsfat_fopen_test_12_kv_data;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+#if ! defined(__ARMCC_VERSION) && defined(__GNUC__)
+
+    /* start from a known state i.e. directory to be created in not present */
+    while(node->filename != NULL) {
+        fsfat_filepath_remove_all((char*) node->filename);
+        node++;
+    }
+
+    /* create a file */
+    node = fsfat_fopen_test_12_kv_data;
+    errno = 0;
+    ret = fsfat_filepath_make_dirs((char*) node->filename, false);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    node = fsfat_fopen_test_12_kv_data;
+    while(node->filename != NULL) {
+        len = strlen(node->value);
+        ret = fsfat_test_create(node->filename, (char*) node->value, len);
+        FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret);
+        TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+        node++;
+    }
+
+    node = fsfat_fopen_test_12_kv_data;
+    memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1);
+    memcpy(buf, node->filename, strlen(node->filename));
+    pos = strrchr(buf, '/');
+    *pos = '\0';
+    dir = opendir(buf);
+    while ((dp = readdir(dir)) != NULL) {
+        FSFAT_DBGLOG("%s: filename: \"%s\"\n", __func__, dp->d_name);
+        TEST_ASSERT_MESSAGE(dp != 0, "Error: readdir() failed\n");
+        FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unexpected object name (name=%s, expected=%s).\n", __func__, dp->d_name, fsfat_fopen_test_12_kv_data[count].value);
+        TEST_ASSERT_MESSAGE(strncmp(dp->d_name, fsfat_fopen_test_12_kv_data[count].value, strlen(fsfat_fopen_test_12_kv_data[count].value)) == 0, fsfat_fopen_utest_msg_g);
+        count++;
+    }
+    closedir(dir);
+
+    /* cleanup */
+    node = fsfat_fopen_test_12_kv_data;
+    while(node->filename != NULL) {
+        fsfat_filepath_remove_all((char*) node->filename);
+        node++;
+    }
+#endif  /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */
+    return CaseNext;
+}
+
+
+/* file data for test_13 */
+static fsfat_kv_data_t fsfat_fopen_test_13_kv_data[] = {
+        /* a file is included in the filepath even though its not created by the test,
+         * as the fsfat_filepath_make_dirs() works with it present. */
+        { "/sd/test_13/dummy.txt", "testdir"},
+        { NULL, NULL},
+};
+/** @brief  test for operation of mkdir()/remove()
+ *
+ * This test checks that:
+ * - The mkdir() function successfully creates a directory that is not already present.
+ * - The mkdir() function returns EEXIST when trying to create a directory thats already present.
+ * - The remove() function successfully removes a directory that is present.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_13(const size_t call_count)
+{
+    int32_t ret = 0;
+
+    FSFAT_DBGLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    /* start from a known state i.e. directory to be created in not present */
+    fsfat_filepath_remove_all((char*) fsfat_fopen_test_13_kv_data[0].filename);
+
+    errno = 0;
+    ret = fsfat_filepath_make_dirs((char*) fsfat_fopen_test_13_kv_data[0].filename, false);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    /* check that get a suitable error when try to create it again.*/
+    errno = 0;
+    ret = fsfat_filepath_make_dirs((char*) fsfat_fopen_test_13_kv_data[0].filename, false);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: permitted to create directory when already exists (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g);
+
+    /* check errno is as expected */
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: errno != EEXIST (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(errno == EEXIST, fsfat_fopen_utest_msg_g);
+
+    ret = fsfat_filepath_remove_all((char*) fsfat_fopen_test_13_kv_data[0].filename);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to remove directory (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    return CaseNext;
+}
+
+/* file data for test_14 */
+static fsfat_kv_data_t fsfat_fopen_test_14_kv_data[] = {
+        /* a file is included in the filepath even though its not created by the test,
+         * as the fsfat_filepath_make_dirs() works with it present. */
+        { "/sd/test_14/testfile.txt", "testdata"},
+        { NULL, NULL},
+};
+
+/** @brief  test for operation of stat()
+ *
+ * stat() is currently no supported by ARMCC and IAR toolchains libc.
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_14(const size_t call_count)
+{
+#if ! defined(__ARMCC_VERSION) && defined(__GNUC__)
+
+	char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1];
+    char *pos = NULL;
+    int32_t ret = -1;
+    size_t len = 0;
+    struct stat file_stat;
+    fsfat_kv_data_t *node = fsfat_fopen_test_14_kv_data;
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1);
+
+    /* start from a known state i.e. directory to be created in not present */
+    fsfat_filepath_remove_all((char*) node->filename);
+
+    /* Create file in a directory. */
+    errno = 0;
+    ret = fsfat_filepath_make_dirs((char*) node->filename, false);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    len = strlen(node->value);
+    ret = fsfat_test_create(node->filename, (char*) node->value, len);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret);
+    TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g);
+
+    /* Test stat() on the file returns the correct attribute set */
+    memset(&file_stat, 0, sizeof(file_stat));
+    ret = stat(node->filename, &file_stat);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: stat() operation on file failed (filename=%s, ret=%d, errno=%d).\n", __func__, node->filename, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: expected st_mode S_IFREG flag not set (filename=%s).\n", __func__, node->filename);
+    TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFREG) == S_IFREG, fsfat_fopen_utest_msg_g);
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unexpected st_mode S_IFDIR flag set (filename=%s).\n", __func__, node->filename);
+    TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) != S_IFDIR, fsfat_fopen_utest_msg_g);
+
+    /* Test stat() on the directory returns the correct attribute set */
+    memset(&file_stat, 0, sizeof(file_stat));
+    memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1);
+    memcpy(buf, node->filename, strlen(node->filename));
+    pos = strrchr(buf, '/');
+    *pos = '\0';
+    ret = stat(buf, &file_stat);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: stat() operation on directory failed (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, errno);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: unexpected st_mode S_IFREG flag set (directory name=%s).\n", __func__, buf);
+    TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFREG) != S_IFREG, fsfat_fopen_utest_msg_g);
+
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: expected st_mode S_IFDIR flag not set (directory name=%s).\n", __func__, buf);
+    TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) == S_IFDIR, fsfat_fopen_utest_msg_g);
+
+    /* clean up after successful test */
+    fsfat_filepath_remove_all((char*) node->filename);
+
+#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */
+    return CaseNext;
+}
+
+/** @brief  test for operation of SDFileSystem::format()
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_15(const size_t call_count)
+{
+
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    (void) call_count;
+    int32_t ret = -1;
+
+    /* the allocation_unit of 0 means chanFS will use the default for the card (varies according to capacity). */
+    fs.unmount();
+    ret = fs.format(&sd);
+    FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to format sdcard (ret=%d)\n", __func__, (int) ret);
+    TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+    fs.mount(&sd);
+    return CaseNext;
+}
+
+
+/* @brief   test utility function to create a file of a given size.
+ *
+ * A reference data table is used of so that the data file can be later be
+ * checked with fsfat_test_check_data_file().
+ *
+ * @param   filename    name of the file including path
+ * @param   data        data to store in file
+ * @param   len         number of bytes of data present in the data buffer.
+ */
+int32_t fsfat_test_create_data_file(const char* filename, size_t len)
+{
+    int32_t ret = -1;
+    FILE *fp = NULL;
+    size_t write_len = 0;
+    size_t written_len = 0;
+    int32_t exp = 0;
+    const int32_t exp_max = 8;      /* so as not to exceed FSFAT_TEST_BYTE_DATA_TABLE_SIZE/2 */
+
+    FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len);
+    TEST_ASSERT(len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE == 0);
+    fp = fopen(filename, "a");
+    if(fp == NULL){
+        return ret;
+    }
+
+    while(written_len < len) {
+        /* write fsfat_test_byte_data_table or part thereof, in 9 writes of sizes
+         * 1, 2, 4, 8, 16, 32, 64, 128, 1, totalling 256 bytes len permitting. */
+        for(exp = 0; (exp <= exp_max) && (written_len < len); exp++){
+            write_len = 0x1 << (exp % exp_max);
+            write_len = len - written_len  > write_len ? write_len : len - written_len;
+            ret = fwrite((const void*) &fsfat_test_byte_data_table[written_len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE], write_len, 1, fp);
+            written_len += write_len;
+            if(ret != 1){
+                FSFAT_DBGLOG("%s:Error: fwrite() failed (ret=%d)\n", __func__, (int) ret);
+                ret = -1;
+                goto out0;
+            }
+        }
+    }
+    if(written_len == len) {
+        ret = 0;
+    } else {
+        ret = -1;
+    }
+out0:
+    fclose(fp);
+    return ret;
+}
+
+
+/* @brief   test utility function to check the data in the specified file is correct.
+ *
+ * The data read from the file is check that it agrees with the data written by
+ * fsfat_test_create_data_file().
+ *
+ * @param   filename    name of the file including path
+ * @param   data        data to store in file
+ * @param   len         number of bytes of data present in the data buffer.
+ */
+int32_t fsfat_test_check_data_file(const char* filename, size_t len)
+{
+    int32_t ret = -1;
+    FILE *fp = NULL;
+    size_t read_len = 0;
+    uint8_t buf[FSFAT_TEST_BYTE_DATA_TABLE_SIZE];
+
+    FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len);
+    TEST_ASSERT(len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE == 0);
+    fp = fopen(filename, "r");
+    if(fp == NULL){
+        return ret;
+    }
+
+    while(read_len < len) {
+        ret = fread((void*) buf, FSFAT_TEST_BYTE_DATA_TABLE_SIZE, 1, fp);
+        read_len += FSFAT_TEST_BYTE_DATA_TABLE_SIZE;
+        if(ret == 0){
+            /* end of read*/
+            FSFAT_DBGLOG("%s:unable to read data\n", __func__);
+            break;
+        }
+        if(memcmp(buf, fsfat_test_byte_data_table, FSFAT_TEST_BYTE_DATA_TABLE_SIZE) != 0) {
+            FSFAT_DBGLOG("%s:Error: read data not as expected (0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x\n", __func__,
+                    buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
+            ret = -1;
+            goto out0;
+        }
+    }
+    if(read_len == len) {
+        ret = 0;
+    }
+out0:
+    fclose(fp);
+    return ret;
+}
+
+/* file data for test_16 */
+static fsfat_kv_data_t fsfat_fopen_test_16_kv_data[] = {
+        { "/sd/tst16_0/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_1/subdir0/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_2/subdir0/subdir1/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_3/subdir0/subdir1/subdir2/subdir3/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_4/subdir0/subdir1/subdir2/subdir3/subdir4/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_5/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_6/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_7/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_8/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/testfil0.txt", "dummy_data"},
+        { "/sd/tst16_9/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/subdir9/testfil0.txt", "dummy_data"},
+        { NULL, NULL},
+};
+
+
+/** @brief  stress test to write data to fs
+ *
+ * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
+ */
+control_t fsfat_fopen_test_16(const size_t call_count)
+{
+    int32_t ret = 0;
+    fsfat_kv_data_t *node = fsfat_fopen_test_16_kv_data;
+    const int32_t num_blocks = 100; /* each file ~25kB */
+
+    FSFAT_DBGLOG("%s:entered\n", __func__);
+    (void) call_count;
+
+    /* remove file and directory from a previous failed test run, if present */
+    while(node->filename != NULL) {
+        fsfat_filepath_remove_all((char*) node->filename);
+        node++;
+    }
+
+    /* create dirs */
+    node = fsfat_fopen_test_16_kv_data;
+    while(node->filename != NULL) {
+        ret = fsfat_filepath_make_dirs((char*) node->filename, true);
+        FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret);
+        TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+        node++;
+    }
+
+    /* create the data files */
+    node = fsfat_fopen_test_16_kv_data;
+    while(node->filename != NULL) {
+        ret = fsfat_test_create_data_file(node->filename, num_blocks * FSFAT_TEST_BYTE_DATA_TABLE_SIZE);
+        FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret);
+        TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+        node++;
+    }
+
+    /* read the data back and check its as expected */
+    node = fsfat_fopen_test_16_kv_data;
+    while(node->filename != NULL) {
+        ret = fsfat_test_check_data_file(node->filename, num_blocks * FSFAT_TEST_BYTE_DATA_TABLE_SIZE);
+        FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to check data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret);
+        TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g);
+        node++;
+    }
+
+    /* clean up */
+    node = fsfat_fopen_test_16_kv_data;
+    while(node->filename != NULL) {
+        fsfat_filepath_remove_all((char*) node->filename);
+        node++;
+    }
+    return CaseNext;
+}
+
+
+#else
+
+
+#define FSFAT_FOPEN_TEST_01      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_02      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_03      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_04      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_05      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_06      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_07      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_08      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_09      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_10      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_11      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_12      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_13      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_14      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_15      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_16      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_17      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_18      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_19      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_20      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_21      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_22      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_23      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_24      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_25      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_26      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_27      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_28      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_29      fsfat_fopen_test_dummy
+#define FSFAT_FOPEN_TEST_30      fsfat_fopen_test_dummy
+
+/** @brief  fsfat_fopen_test_dummy    Dummy test case for testing when platform doesnt have an SDCard installed.
+ *
+ * @return success always
+ */
+static control_t fsfat_fopen_test_dummy()
+{
+    printf("Null test\n");
+    return CaseNext;
+}
+
+#endif  /* defined(DEVICE_SPI) && defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED) */
+
+
+/// @cond FSFAT_DOXYGEN_DISABLE
+utest::v1::status_t greentea_setup(const size_t number_of_cases)
+{
+    GREENTEA_SETUP(FSFAT_FOPEN_GREENTEA_TIMEOUT_S, "default_auto");
+    return greentea_test_setup_handler(number_of_cases);
+}
+
+Case cases[] = {
+           /*          1         2         3         4         5         6        7  */
+           /* 1234567890123456789012345678901234567890123456789012345678901234567890 */
+        Case("FSFAT_FOPEN_TEST_01: fopen()/fwrite()/fclose() directories/file in multi-dir filepath.", FSFAT_FOPEN_TEST_01),
+        Case("FSFAT_FOPEN_TEST_02: fopen(r) pre-existing file try to write it.", FSFAT_FOPEN_TEST_02),
+        Case("FSFAT_FOPEN_TEST_03: fopen(w+) pre-existing file try to write it.", FSFAT_FOPEN_TEST_03),
+        Case("FSFAT_FOPEN_TEST_04: fopen() with a filename exceeding the maximum length.", FSFAT_FOPEN_TEST_04),
+#ifdef FOPEN_EXTENDED_TESTING
+        Case("FSFAT_FOPEN_TEST_05: fopen() with bad filenames (extended).", FSFAT_FOPEN_TEST_05),
+#endif
+        Case("FSFAT_FOPEN_TEST_06: fopen() with bad filenames (minimal).", FSFAT_FOPEN_TEST_06),
+        Case("FSFAT_FOPEN_TEST_07: fopen()/errno handling.", FSFAT_FOPEN_TEST_07),
+        Case("FSFAT_FOPEN_TEST_08: ferror()/clearerr()/errno handling.", FSFAT_FOPEN_TEST_08),
+        Case("FSFAT_FOPEN_TEST_09: ftell() handling.", FSFAT_FOPEN_TEST_09),
+        Case("FSFAT_FOPEN_TEST_10: remove() test.", FSFAT_FOPEN_TEST_10),
+        Case("FSFAT_FOPEN_TEST_11: rename().", FSFAT_FOPEN_TEST_11),
+        Case("FSFAT_FOPEN_TEST_12: opendir(), readdir(), closedir() test.", FSFAT_FOPEN_TEST_12),
+        Case("FSFAT_FOPEN_TEST_13: mkdir() test.", FSFAT_FOPEN_TEST_13),
+        Case("FSFAT_FOPEN_TEST_14: stat() test.", FSFAT_FOPEN_TEST_14),
+        Case("FSFAT_FOPEN_TEST_15: format() test.", FSFAT_FOPEN_TEST_15),
+        Case("FSFAT_FOPEN_TEST_16: write/check n x 25kB data files.", FSFAT_FOPEN_TEST_16),
+};
+
+
+/* Declare your test specification with a custom setup handler */
+Specification specification(greentea_setup, cases);
+
+int main()
+{
+    return !Harness::run(specification);
+}
+/// @endcond
diff -r 000000000000 -r a1734fe1ec4b sd-driver/features/filesystem/sd/SDBlockDevice.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/features/filesystem/sd/SDBlockDevice.cpp	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,600 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2012 ARM Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/* Introduction
+ * ------------
+ * SD and MMC cards support a number of interfaces, but common to them all
+ * is one based on SPI. This is the one I'm implmenting because it means
+ * it is much more portable even though not so performant, and we already
+ * have the mbed SPI Interface!
+ *
+ * The main reference I'm using is Chapter 7, "SPI Mode" of:
+ *  http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
+ *
+ * SPI Startup
+ * -----------
+ * The SD card powers up in SD mode. The SPI interface mode is selected by
+ * asserting CS low and sending the reset command (CMD0). The card will
+ * respond with a (R1) response.
+ *
+ * CMD8 is optionally sent to determine the voltage range supported, and
+ * indirectly determine whether it is a version 1.x SD/non-SD card or
+ * version 2.x. I'll just ignore this for now.
+ *
+ * ACMD41 is repeatedly issued to initialise the card, until "in idle"
+ * (bit 0) of the R1 response goes to '0', indicating it is initialised.
+ *
+ * You should also indicate whether the host supports High Capicity cards,
+ * and check whether the card is high capacity - i'll also ignore this
+ *
+ * SPI Protocol
+ * ------------
+ * The SD SPI protocol is based on transactions made up of 8-bit words, with
+ * the host starting every bus transaction by asserting the CS signal low. The
+ * card always responds to commands, data blocks and errors.
+ *
+ * The protocol supports a CRC, but by default it is off (except for the
+ * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
+ * I'll leave the CRC off I think!
+ *
+ * Standard capacity cards have variable data block sizes, whereas High
+ * Capacity cards fix the size of data block to 512 bytes. I'll therefore
+ * just always use the Standard Capacity cards with a block size of 512 bytes.
+ * This is set with CMD16.
+ *
+ * You can read and write single blocks (CMD17, CMD25) or multiple blocks
+ * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
+ * the card gets a read command, it responds with a response token, and then
+ * a data token or an error.
+ *
+ * SPI Command Format
+ * ------------------
+ * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
+ *
+ * +---------------+------------+------------+-----------+----------+--------------+
+ * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
+ * +---------------+------------+------------+-----------+----------+--------------+
+ *
+ * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
+ *
+ * All Application Specific commands shall be preceded with APP_CMD (CMD55).
+ *
+ * SPI Response Format
+ * -------------------
+ * The main response format (R1) is a status byte (normally zero). Key flags:
+ *  idle - 1 if the card is in an idle state/initialising
+ *  cmd  - 1 if an illegal command code was detected
+ *
+ *    +-------------------------------------------------+
+ * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
+ *    +-------------------------------------------------+
+ *
+ * R1b is the same, except it is followed by a busy signal (zeros) until
+ * the first non-zero byte when it is ready again.
+ *
+ * Data Response Token
+ * -------------------
+ * Every data block written to the card is acknowledged by a byte
+ * response token
+ *
+ * +----------------------+
+ * | xxx | 0 | status | 1 |
+ * +----------------------+
+ *              010 - OK!
+ *              101 - CRC Error
+ *              110 - Write Error
+ *
+ * Single Block Read and Write
+ * ---------------------------
+ *
+ * Block transfers have a byte header, followed by the data, followed
+ * by a 16-bit CRC. In our case, the data will always be 512 bytes.
+ *
+ * +------+---------+---------+- -  - -+---------+-----------+----------+
+ * | 0xFE | data[0] | data[1] |        | data[n] | crc[15:8] | crc[7:0] |
+ * +------+---------+---------+- -  - -+---------+-----------+----------+
+ */
+
+/* If the target has no SPI support then SDCard is not supported */
+#ifdef DEVICE_SPI
+
+#include "SDBlockDevice.h"
+#include "mbed_debug.h"
+
+#define SD_COMMAND_TIMEOUT 5000
+
+#define SD_DBG             0
+
+#define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK        -5001	/*!< operation would block */
+#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED        -5002	/*!< unsupported operation */
+#define SD_BLOCK_DEVICE_ERROR_PARAMETER          -5003	/*!< invalid parameter */
+#define SD_BLOCK_DEVICE_ERROR_NO_INIT            -5004	/*!< uninitialized */
+#define SD_BLOCK_DEVICE_ERROR_NO_DEVICE          -5005	/*!< device is missing or not connected */
+#define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED    -5006	/*!< write protected */
+
+SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs)
+    : _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0)
+{
+    _cs = 1;
+
+    // Set default to 100kHz for initialisation and 1MHz for data transfer
+    _init_sck = 100000;
+    _transfer_sck = 1000000;
+}
+
+SDBlockDevice::~SDBlockDevice()
+{
+    if (_is_initialized) {
+        deinit();
+    }
+}
+
+#define R1_IDLE_STATE           (1 << 0)
+#define R1_ERASE_RESET          (1 << 1)
+#define R1_ILLEGAL_COMMAND      (1 << 2)
+#define R1_COM_CRC_ERROR        (1 << 3)
+#define R1_ERASE_SEQUENCE_ERROR (1 << 4)
+#define R1_ADDRESS_ERROR        (1 << 5)
+#define R1_PARAMETER_ERROR      (1 << 6)
+
+// Types
+//  - v1.x Standard Capacity
+//  - v2.x Standard Capacity
+//  - v2.x High Capacity
+//  - Not recognised as an SD Card
+#define SDCARD_FAIL 0
+#define SDCARD_V1   1
+#define SDCARD_V2   2
+#define SDCARD_V2HC 3
+
+int SDBlockDevice::_initialise_card()
+{
+    _dbg = SD_DBG;
+    // Set to SCK for initialisation, and clock card with cs = 1
+    _spi.lock();
+    _spi.frequency(_init_sck);
+    _cs = 1;
+    for (int i = 0; i < 16; i++) {
+        _spi.write(0xFF);
+    }
+    _spi.unlock();
+
+    // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
+    if (_cmd(0, 0) != R1_IDLE_STATE) {
+        debug_if(_dbg, "No disk, or could not put SD card in to SPI idle state\n");
+        return SD_BLOCK_DEVICE_ERROR_NO_DEVICE;
+    }
+
+    // send CMD8 to determine whther it is ver 2.x
+    int r = _cmd8();
+    if (r == R1_IDLE_STATE) {
+        return _initialise_card_v2();
+    } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
+        return _initialise_card_v1();
+    } else {
+        debug_if(_dbg, "Not in idle state after sending CMD8 (not an SD card?)\n");
+        return BD_ERROR_DEVICE_ERROR;
+    }
+}
+
+int SDBlockDevice::_initialise_card_v1()
+{
+    for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+        _cmd(55, 0);
+        if (_cmd(41, 0) == 0) {
+            _block_size = 512;
+            debug_if(_dbg, "\n\rInit: SEDCARD_V1\n\r");
+            return BD_ERROR_OK;
+        }
+    }
+
+    debug_if(_dbg, "Timeout waiting for v1.x card\n");
+    return BD_ERROR_DEVICE_ERROR;
+}
+
+int SDBlockDevice::_initialise_card_v2()
+{
+    for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+        wait_ms(50);
+        _cmd58();
+        _cmd(55, 0);
+        if (_cmd(41, 0x40000000) == 0) {
+            _cmd58();
+            debug_if(_dbg, "\n\rInit: SDCARD_V2\n\r");
+            _block_size = 1;
+            return BD_ERROR_OK;
+        }
+    }
+
+    debug_if(_dbg, "Timeout waiting for v2.x card\n");
+    return BD_ERROR_DEVICE_ERROR;
+}
+
+int SDBlockDevice::init()
+{
+    _lock.lock();
+    int err = _initialise_card();
+    _is_initialized = (err == BD_ERROR_OK);
+    if (!_is_initialized) {
+        debug_if(_dbg, "Fail to initialize card\n");
+        _lock.unlock();
+        return err;
+    }
+    debug_if(_dbg, "init card = %d\n", _is_initialized);
+    _sectors = _sd_sectors();
+
+    // Set block length to 512 (CMD16)
+    if (_cmd(16, 512) != 0) {
+        debug_if(_dbg, "Set 512-byte block timed out\n");
+        _lock.unlock();
+        return BD_ERROR_DEVICE_ERROR;
+    }
+
+    // Set SCK for data transfer
+    _spi.frequency(_transfer_sck);
+    _lock.unlock();
+    return BD_ERROR_OK;
+}
+
+int SDBlockDevice::deinit()
+{
+    return 0;
+}
+
+int SDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
+{
+    if (!is_valid_program(addr, size)) {
+        return SD_BLOCK_DEVICE_ERROR_PARAMETER;
+    }
+
+    _lock.lock();
+    if (!_is_initialized) {
+        _lock.unlock();
+        return SD_BLOCK_DEVICE_ERROR_NO_INIT;
+    }
+
+    const uint8_t *buffer = static_cast<const uint8_t*>(b);
+    while (size > 0) {
+        bd_addr_t block = addr / 512;
+        // set write address for single block (CMD24)
+        if (_cmd(24, block * _block_size) != 0) {
+            _lock.unlock();
+            return BD_ERROR_DEVICE_ERROR;
+        }
+
+        // send the data block
+        _write(buffer, 512);
+        buffer += 512;
+        addr += 512;
+        size -= 512;
+    }
+    _lock.unlock();
+    return 0;
+}
+
+int SDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
+{
+    if (!is_valid_read(addr, size)) {
+        return SD_BLOCK_DEVICE_ERROR_PARAMETER;
+    }
+
+    _lock.lock();
+    if (!_is_initialized) {
+        _lock.unlock();
+        return SD_BLOCK_DEVICE_ERROR_PARAMETER;
+    }
+    
+    uint8_t *buffer = static_cast<uint8_t *>(b);
+    while (size > 0) {
+        bd_addr_t block = addr / 512;
+        // set read address for single block (CMD17)
+        if (_cmd(17, block * _block_size) != 0) {
+            _lock.unlock();
+            return BD_ERROR_DEVICE_ERROR;
+        }
+        
+        // receive the data
+        _read(buffer, 512);
+        buffer += 512;
+        addr += 512;
+        size -= 512;
+    }
+    _lock.unlock();
+    return 0;
+}
+
+int SDBlockDevice::erase(bd_addr_t addr, bd_size_t size)
+{
+    return 0;
+}
+
+bd_size_t SDBlockDevice::get_read_size() const
+{
+    return 512;
+}
+
+bd_size_t SDBlockDevice::get_program_size() const
+{
+    return 512;
+}
+
+bd_size_t SDBlockDevice::get_erase_size() const
+{
+    return 512;
+}
+
+bd_size_t SDBlockDevice::size() const
+{
+    bd_size_t sectors = 0;
+    if(_is_initialized) {
+    	sectors = _sectors;
+    }
+    return 512*sectors;
+}
+
+void SDBlockDevice::debug(bool dbg)
+{
+    _dbg = dbg;
+}
+
+
+// PRIVATE FUNCTIONS
+int SDBlockDevice::_cmd(int cmd, int arg) {
+    _spi.lock();
+    _cs = 0;
+
+    // send a command
+    _spi.write(0x40 | cmd);
+    _spi.write(arg >> 24);
+    _spi.write(arg >> 16);
+    _spi.write(arg >> 8);
+    _spi.write(arg >> 0);
+    _spi.write(0x95);
+
+    // wait for the repsonse (response[7] == 0)
+    for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+        int response = _spi.write(0xFF);
+        if (!(response & 0x80)) {
+            _cs = 1;
+            _spi.write(0xFF);
+            _spi.unlock();
+            return response;
+        }
+    }
+    _cs = 1;
+    _spi.write(0xFF);
+    _spi.unlock();
+    return -1; // timeout
+}
+int SDBlockDevice::_cmdx(int cmd, int arg) {
+    _spi.lock();
+    _cs = 0;
+
+    // send a command
+    _spi.write(0x40 | cmd);
+    _spi.write(arg >> 24);
+    _spi.write(arg >> 16);
+    _spi.write(arg >> 8);
+    _spi.write(arg >> 0);
+    _spi.write(0x95);
+
+    // wait for the repsonse (response[7] == 0)
+    for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+        int response = _spi.write(0xFF);
+        if (!(response & 0x80)) {
+            _cs = 1;
+            _spi.unlock();
+            return response;
+        }
+    }
+    _cs = 1;
+    _spi.write(0xFF);
+    _spi.unlock();
+    return -1; // timeout
+}
+
+
+int SDBlockDevice::_cmd58() {
+    _spi.lock();
+    _cs = 0;
+    int arg = 0;
+
+    // send a command
+    _spi.write(0x40 | 58);
+    _spi.write(arg >> 24);
+    _spi.write(arg >> 16);
+    _spi.write(arg >> 8);
+    _spi.write(arg >> 0);
+    _spi.write(0x95);
+
+    // wait for the repsonse (response[7] == 0)
+    for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+        int response = _spi.write(0xFF);
+        if (!(response & 0x80)) {
+            int ocr = _spi.write(0xFF) << 24;
+            ocr |= _spi.write(0xFF) << 16;
+            ocr |= _spi.write(0xFF) << 8;
+            ocr |= _spi.write(0xFF) << 0;
+            _cs = 1;
+            _spi.write(0xFF);
+            _spi.unlock();
+            return response;
+        }
+    }
+    _cs = 1;
+    _spi.write(0xFF);
+    _spi.unlock();
+    return -1; // timeout
+}
+
+int SDBlockDevice::_cmd8() {
+    _spi.lock();
+    _cs = 0;
+
+    // send a command
+    _spi.write(0x40 | 8); // CMD8
+    _spi.write(0x00);     // reserved
+    _spi.write(0x00);     // reserved
+    _spi.write(0x01);     // 3.3v
+    _spi.write(0xAA);     // check pattern
+    _spi.write(0x87);     // crc
+
+    // wait for the repsonse (response[7] == 0)
+    for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) {
+        char response[5];
+        response[0] = _spi.write(0xFF);
+        if (!(response[0] & 0x80)) {
+            for (int j = 1; j < 5; j++) {
+                response[i] = _spi.write(0xFF);
+            }
+            _cs = 1;
+            _spi.write(0xFF);
+            _spi.unlock();
+            return response[0];
+        }
+    }
+    _cs = 1;
+    _spi.write(0xFF);
+    _spi.unlock();
+    return -1; // timeout
+}
+
+int SDBlockDevice::_read(uint8_t *buffer, uint32_t length) {
+    _spi.lock();
+    _cs = 0;
+
+    // read until start byte (0xFF)
+    while (_spi.write(0xFF) != 0xFE);
+
+    // read data
+    for (uint32_t i = 0; i < length; i++) {
+        buffer[i] = _spi.write(0xFF);
+    }
+    _spi.write(0xFF); // checksum
+    _spi.write(0xFF);
+
+    _cs = 1;
+    _spi.write(0xFF);
+    _spi.unlock();
+    return 0;
+}
+
+int SDBlockDevice::_write(const uint8_t*buffer, uint32_t length) {
+    _spi.lock();
+    _cs = 0;
+
+    // indicate start of block
+    _spi.write(0xFE);
+
+    // write the data
+    for (uint32_t i = 0; i < length; i++) {
+        _spi.write(buffer[i]);
+    }
+
+    // write the checksum
+    _spi.write(0xFF);
+    _spi.write(0xFF);
+
+    // check the response token
+    if ((_spi.write(0xFF) & 0x1F) != 0x05) {
+        _cs = 1;
+        _spi.write(0xFF);
+        _spi.unlock();
+        return 1;
+    }
+
+    // wait for write to finish
+    while (_spi.write(0xFF) == 0);
+
+    _cs = 1;
+    _spi.write(0xFF);
+    _spi.unlock();
+    return 0;
+}
+
+static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
+    uint32_t bits = 0;
+    uint32_t size = 1 + msb - lsb;
+    for (uint32_t i = 0; i < size; i++) {
+        uint32_t position = lsb + i;
+        uint32_t byte = 15 - (position >> 3);
+        uint32_t bit = position & 0x7;
+        uint32_t value = (data[byte] >> bit) & 1;
+        bits |= value << i;
+    }
+    return bits;
+}
+
+uint32_t SDBlockDevice::_sd_sectors() {
+    uint32_t c_size, c_size_mult, read_bl_len;
+    uint32_t block_len, mult, blocknr, capacity;
+    uint32_t hc_c_size;
+    uint32_t blocks;
+
+    // CMD9, Response R2 (R1 byte + 16-byte block read)
+    if (_cmdx(9, 0) != 0) {
+        debug_if(_dbg, "Didn't get a response from the disk\n");
+        return 0;
+    }
+
+    uint8_t csd[16];
+    if (_read(csd, 16) != 0) {
+        debug_if(_dbg, "Couldn't read csd response from disk\n");
+        return 0;
+    }
+
+    // csd_structure : csd[127:126]
+    // c_size        : csd[73:62]
+    // c_size_mult   : csd[49:47]
+    // read_bl_len   : csd[83:80] - the *maximum* read block length
+
+    int csd_structure = ext_bits(csd, 127, 126);
+
+    switch (csd_structure) {
+        case 0:
+            _block_size = 512;
+            c_size = ext_bits(csd, 73, 62);
+            c_size_mult = ext_bits(csd, 49, 47);
+            read_bl_len = ext_bits(csd, 83, 80);
+
+            block_len = 1 << read_bl_len;
+            mult = 1 << (c_size_mult + 2);
+            blocknr = (c_size + 1) * mult;
+            capacity = blocknr * block_len;
+            blocks = capacity / 512;
+            debug_if(_dbg, "\n\rSDBlockDevice\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks);
+            break;
+
+        case 1:
+            _block_size = 1;
+            hc_c_size = ext_bits(csd, 63, 48);
+            blocks = (hc_c_size+1)*1024;
+            debug_if(_dbg, "\n\rSDHC Card \n\rhc_c_size: %d\n\rcapacity: %lld \n\rsectors: %lld\n\r", hc_c_size, blocks*512, blocks);
+            break;
+
+        default:
+            debug_if(_dbg, "CSD struct unsupported\r\n");
+            return 0;
+    };
+    return blocks;
+}
+
+#endif  /* DEVICE_SPI */
diff -r 000000000000 -r a1734fe1ec4b sd-driver/features/filesystem/sd/SDBlockDevice.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/features/filesystem/sd/SDBlockDevice.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,158 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2012 ARM Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef MBED_SD_BLOCK_DEVICE_H
+#define MBED_SD_BLOCK_DEVICE_H
+
+/* If the target has no SPI support then SDCard is not supported */
+#ifdef DEVICE_SPI
+
+#include "BlockDevice.h"
+#include "mbed.h"
+
+
+/** Access an SD Card using SPI
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "SDBlockDevice.h"
+ *
+ * SDBlockDevice sd(p5, p6, p7, p12); // mosi, miso, sclk, cs
+ * uint8_t block[512] = "Hello World!\n";
+ *
+ * int main() {
+ *     sd.init();
+ *     sd.write(block, 0, 512);
+ *     sd.read(block, 0, 512);
+ *     printf("%s", block);
+ *     sd.deinit();
+ * }
+ */
+class SDBlockDevice : public BlockDevice {
+public:
+    /** Lifetime of an SD card
+     */
+    SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs);
+    virtual ~SDBlockDevice();
+
+    /** Initialize a block device
+     *
+     *  @return         0 on success or a negative error code on failure
+     */
+    virtual int init();
+
+    /** Deinitialize a block device
+     *
+     *  @return         0 on success or a negative error code on failure
+     */
+    virtual int deinit();
+
+    /** Read blocks from a block device
+     *
+     *  @param buffer   Buffer to write blocks to
+     *  @param addr     Address of block to begin reading from
+     *  @param size     Size to read in bytes, must be a multiple of read block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
+
+    /** Program blocks to a block device
+     *
+     *  The blocks must have been erased prior to being programmed
+     *
+     *  @param buffer   Buffer of data to write to blocks
+     *  @param addr     Address of block to begin writing to
+     *  @param size     Size to write in bytes, must be a multiple of program block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
+
+    /** Erase blocks on a block device
+     *
+     *  The state of an erased block is undefined until it has been programmed
+     *
+     *  @param addr     Address of block to begin erasing
+     *  @param size     Size to erase in bytes, must be a multiple of erase block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int erase(bd_addr_t addr, bd_size_t size);
+
+    /** Get the size of a readable block
+     *
+     *  @return         Size of a readable block in bytes
+     */
+    virtual bd_size_t get_read_size() const;
+
+    /** Get the size of a programable block
+     *
+     *  @return         Size of a programable block in bytes
+     *  @note Must be a multiple of the read size
+     */
+    virtual bd_size_t get_program_size() const;
+
+    /** Get the size of a eraseable block
+     *
+     *  @return         Size of a eraseable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size() const;
+
+    /** Get the total size of the underlying device
+     *
+     *  @return         Size of the underlying device in bytes
+     */
+    virtual bd_size_t size() const;
+
+    /** Enable or disable debugging
+     *
+     *  @param          State of debugging
+     */
+    virtual void debug(bool dbg);
+
+private:
+    int _cmd(int cmd, int arg);
+    int _cmdx(int cmd, int arg);
+    int _cmd8();
+    int _cmd58();
+    int _initialise_card();
+    int _initialise_card_v1();
+    int _initialise_card_v2();
+
+    int _read(uint8_t * buffer, uint32_t length);
+    int _write(const uint8_t *buffer, uint32_t length);
+    uint32_t _sd_sectors();
+    uint32_t _sectors;
+
+    uint32_t _init_sck;
+    uint32_t _transfer_sck;
+
+    SPI _spi;
+    DigitalOut _cs;
+    unsigned _block_size;
+    bool _is_initialized;
+    bool _dbg;
+    Mutex _lock;
+};
+
+
+#endif  /* DEVICE_SPI */
+
+#endif  /* MBED_SD_BLOCK_DEVICE_H */
diff -r 000000000000 -r a1734fe1ec4b sd-driver/features/filesystem/test/fsfat_debug.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/features/filesystem/test/fsfat_debug.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,88 @@
+/** @file fsfat_debug.h
+ *
+ * component debug header file.
+ */
+
+
+#ifndef __FSFAT_DEBUG
+#define __FSFAT_DEBUG
+
+#include <stdint.h>
+#include <assert.h>
+#include <stdio.h>
+
+
+/* Debug Support */
+
+#define FSFAT_LOG_NONE        0
+#define FSFAT_LOG_ERR         1
+#define FSFAT_LOG_WARN        2
+#define FSFAT_LOG_NOTICE      3
+#define FSFAT_LOG_INFO        4
+#define FSFAT_LOG_DEBUG       5
+#define FSFAT_LOG_FENTRY      6
+
+#define FSFAT_LOG(_fmt, ...)                          \
+  do                                                    \
+  {                                                     \
+        printf(_fmt, __VA_ARGS__);                      \
+  }while(0);
+
+#define noFSFAT_DEBUG
+#ifdef FSFAT_DEBUG
+
+extern uint32_t fsfat_optDebug_g;
+extern uint32_t fsfat_optLogLevel_g;
+
+
+/* uncomment for asserts to work */
+/* #undef NDEBUG */
+// todo: port to mbedOSV3++ #include <core-util/assert.h>
+
+#define FSFAT_INLINE
+// todo: port to mbedOSV3++ #define FSFAT_ASSERT  CORE_UTIL_ASSERT
+#define FSFAT_ASSERT(...)
+
+#define FSFAT_DBGLOG(_fmt, ...)                       \
+  do                                                    \
+  {                                                     \
+    if(fsfat_optDebug_g && (fsfat_optLogLevel_g >= FSFAT_LOG_DEBUG))  \
+    {                                                   \
+        printf(_fmt, __VA_ARGS__);                      \
+    }                                                   \
+  }while(0);
+
+
+#define FSFAT_ERRLOG(_fmt, ...)                       \
+  do                                                    \
+  {                                                     \
+    if(fsfat_optDebug_g && (fsfat_optLogLevel_g >= FSFAT_LOG_ERR))  \
+    {                                                   \
+        printf(_fmt, __VA_ARGS__);                      \
+    }                                                   \
+  }while(0);
+
+
+#define FSFAT_FENTRYLOG(_fmt, ...)                       \
+  do                                                    \
+  {                                                     \
+    if(fsfat_optDebug_g && (fsfat_optLogLevel_g >= FSFAT_LOG_FENTRY))  \
+    {                                                   \
+        printf(_fmt, __VA_ARGS__);                      \
+    }                                                   \
+  }while(0);
+
+
+
+
+
+#else
+#define FSFAT_ASSERT(_x)                   do { } while(0)
+#define FSFAT_INLINE                       inline
+#define FSFAT_DBGLOG(_fmt, ...)            do { } while(0)
+#define FSFAT_ERRLOG(_fmt, ...)            do { } while(0)
+#define FSFAT_FENTRYLOG(_fmt, ...)         do { } while(0)
+#endif /* FSFAT_DEBUG */
+
+
+#endif /*__FSFAT_DEBUG*/
diff -r 000000000000 -r a1734fe1ec4b sd-driver/features/filesystem/test/fsfat_test.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/features/filesystem/test/fsfat_test.c	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,117 @@
+/* @file fsfat_test.c
+ *
+ * mbed Microcontroller Library
+ * Copyright (c) 2006-2016 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * test support code implementation file.
+ */
+
+#include "fsfat_debug.h"
+#include "fsfat_test.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <ctype.h>
+
+
+#ifdef FSFAT_DEBUG
+uint32_t fsfat_optDebug_g = 1;
+uint32_t fsfat_optLogLevel_g = FSFAT_LOG_NONE; /*FSFAT_LOG_NONE|FSFAT_LOG_ERR|FSFAT_LOG_DEBUG|FSFAT_LOG_FENTRY; */
+#endif
+
+/* ruler for measuring text strings */
+/*                                                                                                    1         1         1         1         1         1         1         1         1         1         2         2         2 */
+/* 0        1         2         3         4         5         6         7         8         9         0         1         2         3         4         5         6         7         8         9         0         1         2 */
+/* 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 */
+
+const uint8_t fsfat_test_byte_data_table[FSFAT_TEST_BYTE_DATA_TABLE_SIZE] = {
+    0x2d, 0xf3, 0x31, 0x4c, 0x11, 0x4f, 0xde, 0x0d, 0xbd, 0xbc, 0xa6, 0x78, 0x36, 0x5c, 0x1d, 0x28,
+    0x5f, 0xa9, 0x10, 0x65, 0x54, 0x45, 0x21, 0x1a, 0x88, 0xfe, 0x76, 0x45, 0xb9, 0xac, 0x65, 0x9a,
+    0x34, 0x9d, 0x73, 0x10, 0xb4, 0xa9, 0x2e, 0x90, 0x95, 0x68, 0xac, 0xfe, 0xc5, 0x2d, 0x15, 0x03,
+    0x34, 0x70, 0xf1, 0x1d, 0x48, 0xa1, 0xa0, 0xed, 0x5c, 0x2f, 0xf5, 0x2b, 0xb9, 0x84, 0xbb, 0x45,
+    0x32, 0xdd, 0xb1, 0x33, 0x95, 0x2a, 0xbc, 0x26, 0xf0, 0x89, 0xba, 0xf4, 0xbd, 0xf9, 0x5d, 0x2e,
+    0x6e, 0x11, 0xc6, 0xa7, 0x78, 0xfc, 0xc9, 0x0e, 0x6b, 0x38, 0xba, 0x14, 0x1b, 0xab, 0x4c, 0x20,
+    0x91, 0xe4, 0xb0, 0xf1, 0x2b, 0x14, 0x07, 0x6b, 0xb5, 0xcd, 0xe3, 0x49, 0x75, 0xac, 0xe8, 0x98,
+    0xf1, 0x58, 0x8f, 0xd9, 0xc4, 0x8f, 0x00, 0x17, 0xb5, 0x06, 0x6a, 0x33, 0xbd, 0xa7, 0x40, 0x5a,
+    0xbf, 0x49, 0xf7, 0x27, 0x1b, 0x4c, 0x3e, 0x6f, 0xe3, 0x08, 0x1f, 0xfd, 0xa6, 0xd4, 0xc7, 0x5f,
+    0xa4, 0xa6, 0x82, 0xad, 0x19, 0xd5, 0x5c, 0xd8, 0x3a, 0x49, 0x85, 0xc9, 0x21, 0x83, 0xf6, 0xc6,
+    0x84, 0xf9, 0x76, 0x89, 0xf3, 0x2d, 0x17, 0x50, 0x97, 0x38, 0x48, 0x9a, 0xe1, 0x82, 0xcd, 0xac,
+    0xa8, 0x1d, 0xd7, 0x96, 0x5e, 0xb3, 0x08, 0xa8, 0x3a, 0xc7, 0x2b, 0x05, 0xaf, 0xdc, 0x16, 0xdf,
+    0x48, 0x0f, 0x2a, 0x7e, 0x3a, 0x82, 0xd7, 0x80, 0xd6, 0x49, 0x27, 0x5d, 0xe3, 0x07, 0x62, 0xb3,
+    0xc3, 0x6c, 0xba, 0xb2, 0xaa, 0x9f, 0xd9, 0x03, 0x0d, 0x27, 0xa8, 0xe0, 0xd6, 0xee, 0x79, 0x4b,
+    0xd6, 0x97, 0x99, 0xb7, 0x11, 0xd6, 0x0d, 0x34, 0xae, 0x99, 0x4a, 0x93, 0x95, 0xd0, 0x5a, 0x34,
+    0x19, 0xa2, 0x69, 0x57, 0xcf, 0x7c, 0x3d, 0x98, 0x88, 0x5d, 0x04, 0xf2, 0xd7, 0xac, 0xa5, 0x63
+};
+
+
+/* @brief  test utility function to delete the file identified by filename
+ */
+int32_t fsfat_test_delete(const char* filename)
+{
+    FSFAT_FENTRYLOG("%s:entered.\r\n", __func__);
+    return remove(filename);
+}
+
+
+/* @brief   test utility function to create a file
+ *
+ * @param   filename    name of the file including path
+ * @param   data        data to store in file
+ * @param   len         number of bytes of data present in the data buffer.
+ */
+int32_t fsfat_test_create(const char* filename, const char* data, size_t len)
+{
+    int32_t ret = -1;
+    FILE *fp = NULL;
+
+    FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len);
+    fp = fopen(filename, "w+");
+    if(fp == NULL){
+        return ret;
+    }
+    ret = fwrite((const void*) data, len, 1, fp);
+    if(ret < 0){
+        fclose(fp);
+        return ret;
+    }
+    fclose(fp);
+    return ret;
+}
+
+
+/* @brief   support function for generating a kv_name
+ * @param   name    buffer to hold kv name
+ * @param   len     length of kv name to generate
+ *
+ */
+int32_t fsfat_test_filename_gen(char* name, const size_t len)
+{
+    size_t i;
+    uint32_t pos = 0;
+
+    const char* buf = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!$-_@";
+    const int buf_len = strlen(buf);
+    FSFAT_FENTRYLOG("%s:entered\n", __func__);
+    for(i = 0; i < len; i++)
+    {
+        pos = rand() % (buf_len);
+        name[i] = buf[pos];
+    }
+    return 0;
+}
+
diff -r 000000000000 -r a1734fe1ec4b sd-driver/features/filesystem/test/fsfat_test.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sd-driver/features/filesystem/test/fsfat_test.h	Sat Apr 08 14:43:14 2017 +0000
@@ -0,0 +1,74 @@
+/** @file fsfat_test.h
+ *
+ * mbed Microcontroller Library
+ * Copyright (c) 2006-2016 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Header file for test support data structures and function API.
+ */
+#ifndef __FSFAT_TEST_H
+#define __FSFAT_TEST_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Defines */
+//#define FSFAT_INIT_1_TABLE_HEAD                 { "a", ""}
+#define FSFAT_INIT_1_TABLE_MID_NODE             { "/sd/01234567.txt", "abcdefghijklmnopqrstuvwxyz"}
+//#define FSFAT_INIT_1_TABLE_TAIL                 { "/sd/fopentst/hello/world/animal/wobbly/dog/foot/backrght.txt", "present"}
+#define FSFAT_TEST_RW_TABLE_SENTINEL            0xffffffff
+#define FSFAT_TEST_BYTE_DATA_TABLE_SIZE         256
+#define FSFAT_UTEST_MSG_BUF_SIZE                256
+#define FSFAT_UTEST_DEFAULT_TIMEOUT_MS          10000
+#define FSFAT_MBED_HOSTTEST_TIMEOUT             60
+#define FSFAT_MAX_FILE_BASENAME                 8
+#define FSFAT_MAX_FILE_EXTNAME                  3
+#define FSFAT_BUF_MAX_LENGTH                    64
+#define FSFAT_FILENAME_MAX_LENGTH               255
+
+
+/* support macro for make string for utest _MESSAGE macros, which dont support formatted output */
+#define FSFAT_TEST_UTEST_MESSAGE(_buf, _max_len, _fmt, ...)   \
+  do                                                            \
+  {                                                             \
+      snprintf((_buf), (_max_len), (_fmt), __VA_ARGS__);        \
+  }while(0);
+
+
+/*
+ * Structures
+ */
+
+/* kv data for test */
+typedef struct fsfat_kv_data_t {
+    const char* filename;
+    const char* value;
+} fsfat_kv_data_t;
+
+
+extern const uint8_t fsfat_test_byte_data_table[FSFAT_TEST_BYTE_DATA_TABLE_SIZE];
+
+int32_t fsfat_test_create(const char* filename, const char* data, size_t len);
+int32_t fsfat_test_delete(const char* key_name);
+int32_t fsfat_test_filename_gen(char* name, const size_t len);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FSFAT_TEST_H */