wifi test
Dependencies: X_NUCLEO_IKS01A2 mbed-http
Revision 0:24d3eb812fd4, committed 2018-09-05
- Comitter:
- JMF
- Date:
- Wed Sep 05 14:28:24 2018 +0000
- Commit message:
- Initial commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,483 @@ +These files allow you to build a simple HTTP/HTTPS application that will exchange data with httpbin.org and ensure the BG96 hardware/driver is working correctly. + +# Note + -The following firmware version was used in testing: + Modem SW Revision: BG96 Rev:BG96MAR02A04M1G + + + +# Required tools +1. mbed-cli (version 1.3.0 or later) +2. latest version of GNU ARM Embedded Toolchain: **https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads** + +# Create Project +1. Import the BG96_Example project: **mbed import http://github.com/Avnet/BG96_Example** + +2. Goto the BG96_Example folder, Then edit mbed_settings.py and add the path to your compiler using GCC_ARM_PATH + +# Build Application +1. Build the program by executing **'mbed compile -t GCC_ARM -m NUCLEO_L476RG'** + +2. When building the tests, it is possible to enable varying amounts of debug information to be output by the + Network driver. These settings are located in the 'mbed_app.json' file (the bg96_config.json file is used when + building for Green Tea). To enable or disable WNC Debug output, set the 'bg96_debug' flag to 'true' (or 1) or + to 'false' (or 0) to disable. + + The amount of debug information output is controlled by the 'bg96-debug-setting' flag in the 'mbed_app.json' file. + The values for this flag enabled debug output to trace various activities (see mbed_app.json for detailed settings). + +3. Verify operation of the basic application program by executing it on the target hardware. This is done by monitoring + the program operation using a teminal program (ex. minicom or hyperterm), with settings of 115200-N81. Program output + should resemble: + +``` +Test HTTP and HTTPS interface +[EasyConnect] Using BG96 +[EasyConnect] IPv4 mode +[EasyConnect] Connected to Network successfully +[EasyConnect] MAC address 37:67:61:79:08:72:30 +[EasyConnect] IP address 10.192.139.159 + +Modem SW Revision: BG96 Rev:BG96MAR02A04M1G + +>>>>>>>>>>>><<<<<<<<<<<< +>>> TEST HTTPClient <<< +>>>>>>>>>>>><<<<<<<<<<<< + +Connected over TCP to developer.mbed.org + + >>>First, lets get a page from http://developer.mbed.org + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Server: nginx/1.11.10 + Date: Wed, 28 Mar 2018 12:58:12 GMT + Content-Type: text/plain + Content-Length: 14 + Connection: keep-alive + Last-Modified: Fri, 27 Jul 2012 13:30:34 GMT + Accept-Ranges: bytes + Cache-Control: max-age=36000 + Expires: Wed, 28 Mar 2018 22:57:52 GMT + X-Upstream-L1-next-hop: 217.140.101.34:8080 + X-Upstream-L1: developer-sjc-indigo-border-nginx + +Body (14 bytes): + +Hello world! + +Connected over TCP to httpbin.org + + + + >>>Post data... ** + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Connection: keep-alive + Server: meinheld/0.6.1 + Date: Wed, 28 Mar 2018 12:58:04 GMT + Content-Type: application/json + Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true + X-Powered-By: Flask + X-Processed-Time: 0 + Content-Length: 335 + Via: 1.1 vegur + +Body (335 bytes): + +{ + "args": {}, + "data": "{\"hello\":\"world\"},{\"test\":\"1234\"}", + "files": {}, + "form": {}, + "headers": { + "Connection": "close", + "Content-Length": "33", + "Content-Type": "application/json", + "Host": "httpbin.org" + }, + "json": null, + "origin": "205.197.242.109", + "url": "http://httpbin.org/post" +} + + + + >>>Put data... + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Connection: keep-alive + Server: meinheld/0.6.1 + Date: Wed, 28 Mar 2018 12:58:03 GMT + Content-Type: application/json + Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true + X-Powered-By: Flask + X-Processed-Time: 0 + Content-Length: 312 + Via: 1.1 vegur + +Body (312 bytes): + +{ + "args": {}, + "data": "This is a PUT test!", + "files": {}, + "form": {}, + "headers": { + "Connection": "close", + "Content-Length": "19", + "Content-Type": "application/json", + "Host": "httpbin.org" + }, + "json": null, + "origin": "205.197.242.109", + "url": "http://httpbin.org/put" +} + + + + >>>Delete data... + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Connection: keep-alive + Server: meinheld/0.6.1 + Date: Wed, 28 Mar 2018 12:58:04 GMT + Content-Type: application/json + Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true + X-Powered-By: Flask + X-Processed-Time: 0 + Content-Length: 295 + Via: 1.1 vegur + +Body (295 bytes): + +{ + "args": {}, + "data": "", + "files": {}, + "form": {}, + "headers": { + "Connection": "close", + "Content-Length": "0", + "Content-Type": "application/json", + "Host": "httpbin.org" + }, + "json": null, + "origin": "205.197.242.109", + "url": "http://httpbin.org/delete" +} + + + + >>>HTTP:stream, send http://httpbin.org/stream/10... +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 0, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 1, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 2, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 3, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 4, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 5, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 6, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 7, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 8, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "http://httpbin.org/stream/10", "id": 9, "origin": "205.197.242.109"} + + + >>>HTTP:Status... + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Connection: keep-alive + Server: meinheld/0.6.1 + Date: Wed, 28 Mar 2018 12:58:05 GMT + Content-Type: application/json + Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true + X-Powered-By: Flask + X-Processed-Time: 0 + Content-Length: 485 + Via: 1.1 vegur + +Body (485 bytes): + +{ + "args": { + "show_env": "1" + }, + "headers": { + "Connect-Time": "0", + "Connection": "close", + "Host": "httpbin.org", + "Total-Route-Time": "0", + "Via": "1.1 vegur", + "X-Forwarded-For": "205.197.242.109", + "X-Forwarded-Port": "80", + "X-Forwarded-Proto": "http", + "X-Request-Id": "c0473d12-4062-4f12-88f2-7456d75de557", + "X-Request-Start": "1522241885624" + }, + "origin": "205.197.242.109", + "url": "http://httpbin.org/get?show_env=1" +} + +>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<< +>>> TEST HTTPS - set up TLS connection <<< +>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<< + +Connecting to httpbin.org:443 +Starting the TLS handshake... +TLS connection to httpbin.org:443 established +Server certificate: + cert. version : 3 + serial number : 03:55:B1:71:8C:8A:36:EC:AB:6C:1F:EA:C2:DD:D0:EC:F9:AD + issuer name : C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3 + subject name : CN=httpbin.org + issued on : 2018-03-13 01:23:44 + expires on : 2018-06-11 01:23:44 + signed using : RSA with SHA-256 + RSA key size : 2048 bits + basic constraints : CA=false + subject alt name : httpbin.org, www.httpbin.org + key usage : Digital Signature, Key Encipherment + ext key usage : TLS Web Server Authentication, TLS Web Client Authentication +Certificate verification passed + + + + >>>Post data... ** + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Connection: keep-alive + Server: meinheld/0.6.1 + Date: Wed, 28 Mar 2018 12:58:19 GMT + Content-Type: application/json + Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true + X-Powered-By: Flask + X-Processed-Time: 0 + Content-Length: 336 + Via: 1.1 vegur + +Body (336 bytes): + +{ + "args": {}, + "data": "{\"hello\":\"world\"},{\"test\":\"1234\"}", + "files": {}, + "form": {}, + "headers": { + "Connection": "close", + "Content-Length": "33", + "Content-Type": "application/json", + "Host": "httpbin.org" + }, + "json": null, + "origin": "205.197.242.109", + "url": "https://httpbin.org/post" +} + + + + >>>Put data... + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Connection: keep-alive + Server: meinheld/0.6.1 + Date: Wed, 28 Mar 2018 12:58:20 GMT + Content-Type: application/json + Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true + X-Powered-By: Flask + X-Processed-Time: 0 + Content-Length: 313 + Via: 1.1 vegur + +Body (313 bytes): + +{ + "args": {}, + "data": "This is a PUT test!", + "files": {}, + "form": {}, + "headers": { + "Connection": "close", + "Content-Length": "19", + "Content-Type": "application/json", + "Host": "httpbin.org" + }, + "json": null, + "origin": "205.197.242.109", + "url": "https://httpbin.org/put" +} + + + + >>>Delete data... + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Connection: keep-alive + Server: meinheld/0.6.1 + Date: Wed, 28 Mar 2018 12:58:20 GMT + Content-Type: application/json + Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true + X-Powered-By: Flask + X-Processed-Time: 0 + Content-Length: 296 + Via: 1.1 vegur + +Body (296 bytes): + +{ + "args": {}, + "data": "", + "files": {}, + "form": {}, + "headers": { + "Connection": "close", + "Content-Length": "0", + "Content-Type": "application/json", + "Host": "httpbin.org" + }, + "json": null, + "origin": "205.197.242.109", + "url": "https://httpbin.org/delete" +} + + + + >>>HTTP:stream, send http://httpbin.org/stream/10... +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 0, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 1, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 2, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 3, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 4, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 5, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 6, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 7, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 8, "origin": "205.197.242.109"} +Chunk Received: {"args": {}, "headers": {"Host": "httpbin.org", "Connection": "close"}, "url": "https://httpbin.org/stream/10", "id": 9, "origin": "205.197.242.109"} + + + >>>HTTP:Status... + +----- RESPONSE: ----- +Status: 200 - OK +Headers: + Connection: keep-alive + Server: meinheld/0.6.1 + Date: Wed, 28 Mar 2018 12:58:20 GMT + Content-Type: application/json + Access-Control-Allow-Origin: * + Access-Control-Allow-Credentials: true + X-Powered-By: Flask + X-Processed-Time: 0 + Content-Length: 488 + Via: 1.1 vegur + +Body (488 bytes): + +{ + "args": { + "show_env": "1" + }, + "headers": { + "Connect-Time": "0", + "Connection": "close", + "Host": "httpbin.org", + "Total-Route-Time": "0", + "Via": "1.1 vegur", + "X-Forwarded-For": "205.197.242.109", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https", + "X-Request-Id": "1a203766-8bdd-411b-89a4-25911114e72b", + "X-Request-Start": "1522241901714" + }, + "origin": "205.197.242.109", + "url": "https://httpbin.org/get?show_env=1" +} + + - - - - - - - ALL DONE - - - - - - - + +``` + +# Build for Greentea testing +You can test driver operation by building and running the MBed OS Greentea test suite: +1. There is a known issue when using Greentea (https://os.mbed.com/docs/v5.7/tools/testing-applications.html) + whereby there cannot be a main() function outside of a TESTS directory when building and running tests. This + is because all nontest code is compiled and linked with the test code and a linker error will occur due to + multiple main() functions defined. To eleminate this problem, rename the main application file in the 'source' + directory to build. NOTE: this only applies when using the Greentea test suite. + + In summary, rename the application source file 'source/main-x.cpp' to 'source/main-x.keepcpp'. + +2. Execute the command: **mbed test -m NUCLEO_L476RG -t GCC_ARM -c --test-config bg96_config.json -n mbed-os-tests-netsocket-\*** + When running the test suite, it programs different test files into the hardware to run so execution will take + some time to complete. When finished, you will get a summary report similar to: + +``` + mbedgt: test suite report: + ++-----------------------+---------------+-----------------------------------------+--------+--------------------+-------------+ +| target | platform_name | test suite | result | elapsed_time (sec) | copy_method | ++-----------------------+---------------+-----------------------------------------+--------+--------------------+-------------+ +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-connectivity | OK | 47.72 | default | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-gethostbyname | OK | 25.99 | default | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | OK | 11.83 | default | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-socket_sigio | OK | 36.46 | default | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-tcp_echo | OK | 37.9 | default | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-tcp_hello_world | OK | 28.42 | default | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-udp_echo | OK | 30.89 | default | ++-----------------------+---------------+-----------------------------------------+--------+--------------------+-------------+ +mbedgt: test suite results: 7 OK +mbedgt: test case report: ++-----------------------+---------------+-----------------------------------------+----------------------------------------+--------+--------+--------+--------------------+ +| target | platform_name | test suite | test case | passed | failed | result | elapsed_time (sec) | ++-----------------------+---------------+-----------------------------------------+----------------------------------------+--------+--------+--------+--------------------+ +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-connectivity | Bringing the network up and down | 1 | 0 | OK | 14.03 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-connectivity | Bringing the network up and down twice | 1 | 0 | OK | 21.89 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-gethostbyname | DNS literal | 1 | 0 | OK | 0.02 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-gethostbyname | DNS preference literal | 1 | 0 | OK | 0.02 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-gethostbyname | DNS preference query | 1 | 0 | OK | 0.02 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-gethostbyname | DNS query | 1 | 0 | OK | 0.14 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Hollowed IPv6 address | 1 | 0 | OK | 0.0 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Left-weighted IPv4 address | 1 | 0 | OK | 0.02 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Left-weighted IPv6 address | 1 | 0 | OK | 0.0 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Null IPv4 address | 1 | 0 | OK | 0.0 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Null IPv6 address | 1 | 0 | OK | 0.0 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Right-weighted IPv4 address | 1 | 0 | OK | 0.0 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Right-weighted IPv6 address | 1 | 0 | OK | 0.01 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Simple IPv4 address | 1 | 0 | OK | 0.0 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-ip_parsing | Simple IPv6 address | 1 | 0 | OK | 0.0 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-socket_sigio | Socket Attach Test | 1 | 0 | OK | 3.59 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-socket_sigio | Socket Detach Test | 1 | 0 | OK | 6.22 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-socket_sigio | Socket Reattach Test | 1 | 0 | OK | 0.53 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-tcp_echo | TCP echo | 1 | 0 | OK | 26.16 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-tcp_hello_world | TCP hello world | 1 | 0 | OK | 16.66 | +| NUCLEO_L476RG-GCC_ARM | NUCLEO_L476RG | mbed-os-tests-netsocket-udp_echo | UDP echo | 1 | 0 | OK | 19.2 | ++-----------------------+---------------+-----------------------------------------+----------------------------------------+--------+--------+--------+--------------------+ +mbedgt: test case results: 21 OK +mbedgt: completed in 219.44 sec + +``` + +NOTE: the "UDP DTLS handshake" test is a known failure and is expected. + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/X_NUCLEO_IKS01A2.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/teams/ST/code/X_NUCLEO_IKS01A2/#138a7a28bd21
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/easy-connect/#bf48f5b649eba3ed7b810c77c630b5eb51301311
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/COMMIT_EDITMSG Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +;.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/config Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/info/exclude Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,33 @@ +.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 +wifi-ism43362 +wifi-x-nucleo-idw01m1 +wizfi310-driver +wnc14a2a-driver \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 bf48f5b649eba3ed7b810c77c630b5eb51301311 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504010 +0000 clone: from https://github.com/ARMmbed/easy-connect/ +bf48f5b649eba3ed7b810c77c630b5eb51301311 173db6d6f5becb6d864e45f66b5f3a87d9909ae1 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1536157636 +0000 commit: ;.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 bf48f5b649eba3ed7b810c77c630b5eb51301311 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504010 +0000 clone: from https://github.com/ARMmbed/easy-connect/ +bf48f5b649eba3ed7b810c77c630b5eb51301311 173db6d6f5becb6d864e45f66b5f3a87d9909ae1 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1536157636 +0000 commit: ;.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 bf48f5b649eba3ed7b810c77c630b5eb51301311 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504010 +0000 clone: from https://github.com/ARMmbed/easy-connect/
Binary file easy-connect/.git/objects/05/307089d4ca8dd7e85178769b7ff2d8e1f7a357 has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/objects/17/3db6d6f5becb6d864e45f66b5f3a87d9909ae1 Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +xmÁjÃ0D{ÖWè^l´YK+ÓPrê¡Ð´«ÔÅ¢Ô¿_QèsyL*Û¶4}B|jUDyJÁ3xäÉÍr>±ÈÐÚC[Ó1O>Ûè¦Yb@aL"JM´- PáÑ>KÕïoúÜí²Eá1íUE:ýlºToû§&UÇ1phAÿÒ å[Ö²Kî_iXn¼\ËÐû²J×Â:þ²K½þÃV/£úpH« \ No newline at end of file
Binary file easy-connect/.git/objects/9b/c8ca119877d56e1bb60616d29163dbdda17b5d has changed
Binary file easy-connect/.git/objects/ad/401bf0743ba0119fdab3f3484cb54d279feaa1 has changed
Binary file easy-connect/.git/objects/be/e31d240073f2290632ddab8dfbe3857cd9540d has changed
Binary file easy-connect/.git/objects/bf/99e56a61aed71c2826a1048b13c94eacde004b has changed
Binary file easy-connect/.git/objects/pack/pack-bbb8831b7fdaee17dcab037594983b307f0875ee.idx has changed
Binary file easy-connect/.git/objects/pack/pack-bbb8831b7fdaee17dcab037594983b307f0875ee.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,29 @@ +# pack-refs with: peeled +c5ce3e9a02c7a707a2ce4eca11a880ddae0824dd refs/remotes/origin/China_Unicom_Demo +c447f41a97f22fc58da960fd7f936d049058df9a refs/remotes/origin/README-issues +60f6100d519763c2087a399071ab91c7ac5f79a9 refs/remotes/origin/WISE1530 +8910b5106ba424d300afb357b0d42b547bf28d6c refs/remotes/origin/early_mac +0e924fc9504c5fc4425adf30f7ad85a9fe0bf4fd refs/remotes/origin/esp8266-latest +fcb6b507d0eb336c66342492611550dc43338ce8 refs/remotes/origin/gitign +bf48f5b649eba3ed7b810c77c630b5eb51301311 refs/remotes/origin/master +e61ba698f31f71693451e91f68bb2035706695b7 refs/remotes/origin/mbedos5.3.4 +0c77697463c204aa53467a8b7c6286c31b973792 refs/remotes/origin/odin +bfed7888153a32712d1da875c09c3ab60ec3706c refs/remotes/origin/quectel_cellular +d3503403331d10000e1d061fe189c17f215d4e89 refs/remotes/origin/revert-mts +489b3343cb0d52d301752e085edb476efef38977 refs/remotes/origin/test-pin-mapping +2822a4f704b61664c38c119e4eea694b81ec91a6 refs/remotes/origin/ublox_cellular +522e43fa1bba9483f12284e2e80882f526ec2830 refs/tags/v1.0.0 +06594ba91bc141f08fe4024d0e9471605827cbd0 refs/tags/v1.0.1 +836c2959c669164f1effb243128ff5a9479d5812 refs/tags/v1.0.2 +4e608305251d18851afc500dbbe704cca51db624 refs/tags/v1.0.3 +559d00bf1580a5dbc423c37a06a84602b6aae90d refs/tags/v1.1.0 +48d7e16f0e965766787b7383fbf0cd1d00b1efb5 refs/tags/v1.2.0 +ce7059cc482a383640afe306f96333de49008086 refs/tags/v1.2.10 +5b52b5fa56c623d5853c5daf266b34986a0c20cc refs/tags/v1.2.11 +aaf89690919fc378799e680119a58a222402799f refs/tags/v1.2.12 +22bb2cbe9f29536a33fef90960719a512f11edea refs/tags/v1.2.13 +bf48f5b649eba3ed7b810c77c630b5eb51301311 refs/tags/v1.2.16 +6b2cce9f7cefd02e0503d6307ab5433b6197716d refs/tags/v1.2.2 +4aea66bdd42bad5a01b7c6afb195aaeead42f5ae refs/tags/v1.2.3 +7bc131ebae4a8bcfde095121e3f864407a158c82 refs/tags/v1.2.4 +21a78a40e94ba9298e05ce54738c6b42657ae010 refs/tags/v1.2.9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +173db6d6f5becb6d864e45f66b5f3a87d9909ae1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.gitignore Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,16 @@ +atmel-rf-driver/* +atmel-rf-driver +esp8266-driver/* +esp8266-driver +mcr20a-rf-driver/* +mcr20a-rf-driver +stm-spirit1-rf-driver +stm-spirit1-rf-driver/* +wifi-ism43362 +wifi-ism43362/* +wifi-x-nucleo-idw01m1 +wifi-x-nucleo-idw01m1/* +wizfi310-driver +wizfi310-driver/* +wnc14a2a-driver +wnc14a2a-driver/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<root> + <node _type="string" _key="repo_docs"></node> + <node _type="string" _key="repo_docs_id">https://github.com/ARMmbed/easy-connect/#bf48f5b649eba3ed7b810c77c630b5eb51301311</node> + <node _type="string" _key="repo_docs_ts"></node> + <node _type="NULL" _key="workspace_docs"></node> + <node _type="NULL" _key="workspace_docs_ts"></node> + <node _type="NULL" _key="workspace_docs_sync_id"></node> + <node _type="integer" _key="update">0</node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/.msub Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,8 @@ +atmel-rf-driver = https://github.com/ARMmbed/atmel-rf-driver/#118:96fdfc85a97bb4daefa5a88febe1299a28a1a292 +esp8266-driver = https://github.com/ARMmbed/esp8266-driver/#50:5a88ff9c75e34d65e359d7f239bacc456824ed0e +mcr20a-rf-driver = https://github.com/ARMmbed/mcr20a-rf-driver/#26:e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a +stm-spirit1-rf-driver = https://github.com/ARMmbed/stm-spirit1-rf-driver/#81:b8e3da9b2999d1aec1e500d0acf6e725060d3515 +wifi-ism43362 = https://github.com/ARMmbed/wifi-ism43362/#26:49d0f834dc420c98631fc33777aace9a31d8d584 +wifi-x-nucleo-idw01m1 = https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/#88:b28712c890b73be18884cd323aa884310cf85e3b +wizfi310-driver = https://github.com/ARMmbed/wizfi310-driver/#15:f00390eb6a3e6f003720ca1d589c150b92aa745c +wnc14a2a-driver = https://github.com/Avnet/wnc14a2a-driver/#20:889b7f130c4d714489d0f103b0183f15a7a41852
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/README.md Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,226 @@ +# Easy Connect - Easily add all supported connectivity methods to your mbed OS project + +You may want to give the users of your application the possibility to switch between connectivity methods. The `NetworkInterface` API makes this easy, but you still need a mechanism for the user to chooce the method, and perhaps throw in some `#define`'s. Easy Connect handles all of this for you. Just declare the desired connectivity method in your `mbed_app.json` file and call `easy_connect()` from your application. + +## Specifying the connectivity method + +Add the following to your `mbed_app.json` file: + +```json +{ + "config": { + "network-interface":{ + "help": "options are ETHERNET, WIFI_ESP8266, WIFI_IDW0XX1, WIFI_ODIN, WIFI_RTW, WIFI_WIZFI310, WIFI_ISM43362, MESH_LOWPAN_ND, MESH_THREAD, CELLULAR_ONBOARD", + "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 + } + } +} +``` + +### UBLOX ODIN/Ethernet + +#### Mbed OS 5.8 and older + +If you select `ETHERNET` with `UBLOX_ODIN_EVK_W2` you must add this to your `target-overrides` section in `mbed_app.json`: + +```json + "UBLOX_EVK_ODIN_W2": { + "target.device_has_remove": ["EMAC"] + } +``` + +#### Mbed OS 5.9 and newer + +With Mbed OS 5.9, the EMAC SW was refactored and a default network selector is used instead. You must add the following `target-overrides` section to `mbed_app.json`: + +```json + "UBLOX_EVK_ODIN_W2": { + "target.network-default-interface-type": "ETHERNET" + } +``` + +### Other WiFi stacks + +If you select `WIFI_ESP8266`, `WIFI_IDW0XX1`, `WIFI_ODIN` or `WIFI_RTW`, `WIFI_WIZFI310` you also need to add the WiFi SSID and password: + +```json + "config": { + "network-interface":{ + "help": "options are ETHERNET, WIFI_ESP8266, WIFI_IDW0XX1, WIFI_ODIN, WIFI_RTW, WIFI_WIZFI310, WIFI_ISM43362, MESH_LOWPAN_ND, MESH_THREAD, CELLULAR_ONBOARD", + "value": "WIFI_ESP8266" + }, + "wifi-ssid": { + "value": "\"SSID\"" + }, + "wifi-password": { + "value": "\"Password\"" + } + } +``` + +If you use `MESH_LOWPAN_ND` or `MESH_THREAD` you need to specify your radio module: + +```json + "config": { + "network-interface":{ + "help": "options are ETHERNET, WIFI_ESP8266, WIFI_IDW0XX1, WIFI_ODIN, WIFI_RTW, WIFI_WIZFI310, MESH_LOWPAN_ND, MESH_THREAD, CELLULAR_ONBOARD", + "value": "MESH_LOWPAN_ND" + }, + "mesh_radio_type": { + "help": "options are ATMEL, MCR20, SPIRIT1, EFR32", + "value": "ATMEL" + } + } +``` + +### CELLULAR_ONBOARD + +If you use [`CELLULAR_ONBOARD`](https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/communication/cellular/) you must specify the following: + +```json + "target_overrides": { + "*": { + "ppp-cell-iface.apn-lookup": true + } + } +``` +...and you may also need to specify one or more of the following: + +```json + "config": { + "cellular-apn": { + "help": "Please provide the APN string for your SIM if it is not already included in APN_db.h.", + "value": "\"my_sims_apn\"" + }, + "cellular-username": { + "help": "May or may not be required for your APN, please consult your SIM provider.", + "value": "\"my_sim_apns_username\"" + }, + "cellular-password": { + "help": "May or may not be required for your APN, please consult your SIM provider.", + "value": "\"my_sim_apns_password\"" + }, + "cellular-sim-pin": { + "help": "Please provide the PIN for your SIM (as a four digit string) if your SIM is normally locked", + "value": "\"1234\"" + } + } +``` + +None of the optional settings need to be specified for the `UBLOX_C030_U201` cellular target, for which the APN settings are in `APN_db.h`. + +## Using Easy Connect from your application + +Easy Connect has just one function that returns either 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 +} +``` + +## Using Easy connect with WiFi + +The easy-connect `easy_connect()` is overloaded now for WiFi so that you can submit your WiFi SSID and password programmatically in you want +the user to be able to supply them via some means. + +```cpp +#include "easy-connect.h" + +int main(int, char**) { + char* wifi_SSID = "SSID"; + char* wifi_password = "password"; + + NetworkInterface* network = easy_connect(true, wifi_SSID, wifi_password); + if (!network) { + printf("Connecting to the network failed... See serial output.\r\n"); + return 1; + } + + // Rest of your program +} +``` + +## Overriding settings + +Easy-connect was changed recently with [PR #59](https://github.com/ARMmbed/easy-connect/pull/59) - where some of the defines expected via `mbed_app.json` were +moved to the [`mbed_lib.json`](https://github.com/ARMmbed/easy-connect/blob/master/mbed_lib.json). +This minimises the amount of lines needed (in typical cases) in the applications `mbed_app.json`. However, due to this the overrides +need to be done slightly differently, as you need to override the `easy-connect` defines. + +So, for example changing the ESP8266 TX/RX pins and enable debugs - you would now have modify as below. + +```json + "target_overrides": { + "*": { + "easy-connect.wifi-esp8266-tx": "A1", + "easy-connect.wifi-esp8266-rx": "A2", + "easy-connect.wifi-esp8266-debug: true + } + } +``` + + +## Configuration examples + +There are many things that you have to modify for all of the combinations. Examples for configurations are available for example in the [mbed-os-example-client](https://github.com/ARMmbed/mbed-os-example-client/tree/master/configs) repository. + +## Linking error with UBLOX_EVK_ODIN_W2 + +If you get a linking error such as below, you are compiling the `WIFI_ODIN` with the `EMAC override` section in `mbed_app.json`. Remove the `EMAC override` from your `mbed_app.json`. + +``` +Link: tls-client +./mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_UBLOX_EVK_ODIN_W2/sdk/TOOLCHAIN_GCC_ARM/libublox-odin-w2-driver.a(OdinWiFiInterface.o): In function `OdinWiFiInterface::handle_wlan_status_started(wlan_status_started_s*)': +OdinWiFiInterface.cpp:(.text._ZN17OdinWiFiInterface26handle_wlan_status_startedEP21wlan_status_started_s+0x46): undefined reference to `wifi_emac_get_interface()' +OdinWiFiInterface.cpp:(.text._ZN17OdinWiFiInterface26handle_wlan_status_startedEP21wlan_status_started_s+0x4c): undefined reference to `wifi_emac_init_mem()' +collect2: error: ld returned 1 exit status +[ERROR] ./mbed-os/targets/TARGET_STM/TARGET_STM32F4/TARGET_UBLOX_EVK_ODIN_W2/sdk/TOOLCHAIN_GCC_ARM/libublox-odin-w2-driver.a(OdinWiFiInterface.o): In function `OdinWiFiInterface::handle_wlan_status_started(wlan_status_started_s*)': +OdinWiFiInterface.cpp:(.text._ZN17OdinWiFiInterface26handle_wlan_status_startedEP21wlan_status_started_s+0x46): undefined reference to `wifi_emac_get_interface()' +OdinWiFiInterface.cpp:(.text._ZN17OdinWiFiInterface26handle_wlan_status_startedEP21wlan_status_started_s+0x4c): undefined reference to `wifi_emac_init_mem()' +collect2: error: ld returned 1 exit status + +[mbed] ERROR: "/usr/bin/python" returned error code 1. +``` + +## Network errors + +If Easy Connect cannot connect to the network, it returns a network error with an error code. To see what the error code means, see the [mbed OS Communication API](https://os.mbed.com/docs/latest/reference/network-socket.html). + +## 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 + } + } +``` + +## For network stack developers + +Please try out the reliability of your networking stack using +[stress-test](https://github.com/ARMmbed/mbed-stress-test) to ensure +your stack is performing as expected. + +## 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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/atmel-rf-driver/#96fdfc85a97bb4daefa5a88febe1299a28a1a292
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/FETCH_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,21 @@ +96fdfc85a97bb4daefa5a88febe1299a28a1a292 branch 'master' of https://github.com/ARMmbed/atmel-rf-driver +a2d72a667b7ed3ac4e70ae743fd3c02a6e02afda not-for-merge branch 'alpha2-release' of https://github.com/ARMmbed/atmel-rf-driver +d11d8a2564ef5f946c99f8003533caea13599d7b not-for-merge branch 'alpha3-release' of https://github.com/ARMmbed/atmel-rf-driver +6a5156bea2dc8981a7efd86bcdf341dc398307e3 not-for-merge branch 'dep_update' of https://github.com/ARMmbed/atmel-rf-driver +dc0c089e6782d66f3ef379736f3062afae708ef2 not-for-merge branch 'eui_chip_check' of https://github.com/ARMmbed/atmel-rf-driver +1bf67eedce0f85a16376876670d525144d887892 not-for-merge branch 'eui_mac_chip_check' of https://github.com/ARMmbed/atmel-rf-driver +1816200dbd1b336403525a9757a5d495cc7933e8 not-for-merge branch 'eventqueue' of https://github.com/ARMmbed/atmel-rf-driver +f29a7aaefdba350fee57572a7d56bba66a87464e not-for-merge branch 'fhss_dev' of https://github.com/ARMmbed/atmel-rf-driver +06296efdcc38e2719895af98e1f5ec911a1f00f8 not-for-merge branch 'mac_class_update' of https://github.com/ARMmbed/atmel-rf-driver +a41e721bbb81e4e15b812909cd36005a000b03f9 not-for-merge branch 'maint_merge' of https://github.com/ARMmbed/atmel-rf-driver +b73c78b4f8ccbfa3295fd419173ce576ff9ddcf6 not-for-merge branch 'morpheus_dependency' of https://github.com/ARMmbed/atmel-rf-driver +248d04582db6ba2db423cf8eb4e3535d5ef4cb72 not-for-merge branch 'ns_minar_take2' of https://github.com/ARMmbed/atmel-rf-driver +03f33d5a0fc026529fbf10943ba7a7de0fc64c62 not-for-merge branch 'perf_test' of https://github.com/ARMmbed/atmel-rf-driver +e89312f0278b8174e0159ec035cb49f639da6a45 not-for-merge branch 'pll_on_fail_fix' of https://github.com/ARMmbed/atmel-rf-driver +a36e17a728732268b404fc727940257830e208ac not-for-merge branch 'retries' of https://github.com/ARMmbed/atmel-rf-driver +a729202ba68a7537e4bdbea5f6d91d1522280ccd not-for-merge branch 'spi_timing_fix' of https://github.com/ARMmbed/atmel-rf-driver +a82eda14afc4bd57c0574d0d58443d4aa4dddf31 not-for-merge branch 'thread_start_cond' of https://github.com/ARMmbed/atmel-rf-driver +6666cb4f0f131803e315a5869be68dfbd911829b not-for-merge branch 'ublox_fixes' of https://github.com/ARMmbed/atmel-rf-driver +37e636728520d0d6d4e6caafff5e36962e5ceec0 not-for-merge branch 'update_mbed_dep' of https://github.com/ARMmbed/atmel-rf-driver +0f7255a79b69c09469f4b3377513a39a9e6b25f5 not-for-merge branch 'v1.0-maint' of https://github.com/ARMmbed/atmel-rf-driver +a7ff1a1ea2b3060139a345a09b72bdbf244cf4dc not-for-merge branch 'v2.1-maint' of https://github.com/ARMmbed/atmel-rf-driver
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/ORIG_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +96fdfc85a97bb4daefa5a88febe1299a28a1a292
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/config Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/atmel-rf-driver/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/info/exclude Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 96fdfc85a97bb4daefa5a88febe1299a28a1a292 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504012 +0000 clone: from https://github.com/ARMmbed/atmel-rf-driver/ +96fdfc85a97bb4daefa5a88febe1299a28a1a292 ca9782e68f5f47680b7ec82c3dcb60a98dd8e361 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504012 +0000 checkout: moving from master to ca9782e68f5f47680b7ec82c3dcb60a98dd8e361 +ca9782e68f5f47680b7ec82c3dcb60a98dd8e361 96fdfc85a97bb4daefa5a88febe1299a28a1a292 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504038 +0000 checkout: moving from ca9782e68f5f47680b7ec82c3dcb60a98dd8e361 to master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 96fdfc85a97bb4daefa5a88febe1299a28a1a292 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504012 +0000 clone: from https://github.com/ARMmbed/atmel-rf-driver/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 96fdfc85a97bb4daefa5a88febe1299a28a1a292 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504012 +0000 clone: from https://github.com/ARMmbed/atmel-rf-driver/
Binary file easy-connect/atmel-rf-driver/.git/objects/pack/pack-d2a3404c26773e709e80052ff34ef4ccb3da41ba.idx has changed
Binary file easy-connect/atmel-rf-driver/.git/objects/pack/pack-d2a3404c26773e709e80052ff34ef4ccb3da41ba.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,89 @@ +# 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 +1816200dbd1b336403525a9757a5d495cc7933e8 refs/remotes/origin/eventqueue +f29a7aaefdba350fee57572a7d56bba66a87464e refs/remotes/origin/fhss_dev +06296efdcc38e2719895af98e1f5ec911a1f00f8 refs/remotes/origin/mac_class_update +a41e721bbb81e4e15b812909cd36005a000b03f9 refs/remotes/origin/maint_merge +96fdfc85a97bb4daefa5a88febe1299a28a1a292 refs/remotes/origin/master +b73c78b4f8ccbfa3295fd419173ce576ff9ddcf6 refs/remotes/origin/morpheus_dependency +248d04582db6ba2db423cf8eb4e3535d5ef4cb72 refs/remotes/origin/ns_minar_take2 +03f33d5a0fc026529fbf10943ba7a7de0fc64c62 refs/remotes/origin/perf_test +e89312f0278b8174e0159ec035cb49f639da6a45 refs/remotes/origin/pll_on_fail_fix +a36e17a728732268b404fc727940257830e208ac refs/remotes/origin/retries +a729202ba68a7537e4bdbea5f6d91d1522280ccd refs/remotes/origin/spi_timing_fix +a82eda14afc4bd57c0574d0d58443d4aa4dddf31 refs/remotes/origin/thread_start_cond +6666cb4f0f131803e315a5869be68dfbd911829b refs/remotes/origin/ublox_fixes +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 +52e7eda33249e3b6adbcb792250a48ac60fb8c7d refs/tags/v3.0.4 +^96fdfc85a97bb4daefa5a88febe1299a28a1a292
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +96fdfc85a97bb4daefa5a88febe1299a28a1a292
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.gitignore Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,6 @@ +*~ +*.swo +*.swp +build +yotta_modules +yotta_targets
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<root> + <node _type="integer" _key="update">0</node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/LICENSE Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/README.md Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/apache-2.0.txt Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,85 @@ +/* + * 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 "at24mac.h" +#include "PinNames.h" + +#ifdef MBED_CONF_NANOSTACK_CONFIGURATION + +#include "NanostackRfPhy.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); + virtual ~NanostackRfPhyAtmel(); + virtual int8_t rf_register(); + virtual void rf_unregister(); + virtual void get_mac_address(uint8_t *mac); + virtual 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 /* MBED_CONF_NANOSTACK_CONFIGURATION */ +#endif /* NANOSTACK_RF_PHY_ATMEL_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/mbed_lib.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,34 @@ +{ + "name": "atmel-rf", + "config": { + "full-spi-speed": { + "help": "Maximum SPI clock speed (Hz), as long as sufficient inter-byte spacing", + "value": 7500000 + }, + "full-spi-speed-byte-spacing": { + "help": "Required byte spacing in nanoseconds if full SPI speed is in use", + "value": 250 + }, + "low-spi-speed": { + "help": "Maximum SPI clock speed (Hz) if no inter-byte spacing", + "value": 3750000 + }, + "use-spi-spacing-api": { + "help": "Use SPI spacing API proposed in https://github.com/ARMmbed/mbed-os/pull/5353 to ensure spacing between bytes - either run at full speed with spacing, or low with no spacing", + "value": false + }, + "assume-spaced-spi": { + "help": "If not using SPI spacing API, assume platform has widely-spaced bytes in bursts, so use full clock speed rather than low.", + "value": false + }, + "provide-default": { + "help": "Provide default NanostackRfpy. [true/false]", + "value": false + } + }, + "target_overrides": { + "STM": { + "assume-spaced-spi": true + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/module.json Wed Sep 05 14:28:24 2018 +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": {} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/source/AT86RFReg.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,172 @@ +/* + * 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_3A 0x00 +#define CCA_MODE_1 0x20 +#define CCA_MODE_2 0x40 +#define CCA_MODE_3B 0x60 +#define CCA_MODE_MASK 0x60 +#define CCA_CHANNEL_MASK 0x1F + +/*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 +#define TX_AUTO_CRC_ON 0x20 +#define SPI_CMD_MODE_TRX_STATUS 0x04 +#define SPI_CMD_MODE_PHY_RSSI 0x08 +#define SPI_CMD_MODE_IRQ_STATUS 0x0C + +/*TRX_CTRL_2 bits*/ +#define RX_SAFE_MODE 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_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,2405 @@ +/* + * 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> + +#ifdef MBED_CONF_NANOSTACK_CONFIGURATION + +#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 "mbed_trace.h" +#include "mbed_toolchain.h" + +#define TRACE_GROUP "AtRF" + +/*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 + +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, + BUSY_TX = 0x02, + 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, + STATE_TRANSITION_IN_PROGRESS = 0x1F +}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; +static uint8_t xah_ctrl_1; + +/* 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 rf_trx_part_e rf_radio_type_read(void); +static void rf_ack_wait_timer_start(uint16_t slots); +static void rf_handle_cca_ed_done(uint8_t full_trx_status); +static void rf_handle_tx_end(rf_trx_states_t trx_status); +static void rf_handle_rx_end(rf_trx_states_t trx_status); +static void rf_on(void); +static void rf_give_up_on_ack(void); +static void rf_receive(rf_trx_states_t trx_status = STATE_TRANSITION_IN_PROGRESS); +static rf_trx_states_t 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 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 rf_trx_states_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 rf_trx_states_t rf_if_change_trx_state(rf_trx_states_t trx_state); +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); +static void rf_if_spi_exchange_n(const void *tx, size_t tx_len, void *rx, size_t rx_len); + +static inline rf_trx_states_t rf_if_trx_status_from_full(uint8_t full_trx_status) +{ + return (rf_trx_states_t) (full_trx_status & 0x1F); +} + +#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 + +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 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 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) +{ + const uint8_t tx[2] = { static_cast<uint8_t>(0xC0 | addr), data }; + uint8_t rx[2]; + CS_SELECT(); + rf_if_spi_exchange_n(tx, 2, rx, 2); + CS_RELEASE(); +} + +/* + * \brief Function reads RF register, and also outputs PHY_STATUS + * + * \param addr Address on the RF + * \param[out] status_out Pointer to store PHY_STATUS + * + * \return Read register data + */ +static uint8_t rf_if_read_register_with_status(uint8_t addr, uint8_t *status_out) +{ + const uint8_t tx[1] = { static_cast<uint8_t>(0x80 | addr) }; + uint8_t rx[2]; + CS_SELECT(); + rf_if_spi_exchange_n(tx, 1, rx, 2); + CS_RELEASE(); + if (status_out) { + *status_out = rx[0]; + } + return rx[1]; +} + +/* + * \brief Function reads RF register. + * + * \param addr Address on the RF + * + * \return Read register data + */ +static uint8_t rf_if_read_register(uint8_t addr) +{ + return rf_if_read_register_with_status(addr, NULL); +} + +/* + * \brief Function resets the RF. + * + * \param none + * + * \return none + */ +static void rf_if_reset_radio(void) +{ +#if MBED_CONF_ATMEL_RF_USE_SPI_SPACING_API + rf->spi.frequency(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED); + int spacing = rf->spi.write_spacing(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING); + if (spacing < MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING) { + rf->spi.frequency(MBED_CONF_ATMEL_RF_LOW_SPI_SPEED); + rf->spi.write_spacing(0); + } +#elif MBED_CONF_ATMEL_RF_ASSUME_SPACED_SPI + rf->spi.frequency(MBED_CONF_ATMEL_RF_FULL_SPI_SPEED); +#else + rf->spi.frequency(MBED_CONF_ATMEL_RF_LOW_SPI_SPEED); +#endif + 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) +{ + if (!(xah_ctrl_1 & AACK_PROM_MODE)) { + /*Set AACK_PROM_MODE to enable the promiscuous mode*/ + rf_if_write_register(XAH_CTRL_1, xah_ctrl_1 |= AACK_PROM_MODE); + } +} + +/* + * \brief Function disable the promiscuous mode. + * + * \param none + * + * \return none + */ +static void rf_if_disable_promiscuous_mode(void) +{ + if (xah_ctrl_1 & AACK_PROM_MODE) { + /*Clear AACK_PROM_MODE to disable the promiscuous mode*/ + rf_if_write_register(XAH_CTRL_1, 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); + + /* Auto CRC on, IRQ status shows unmasked only, TRX_STATUS output on all accesses */ + rf_if_write_register(TRX_CTRL_1, TX_AUTO_CRC_ON | SPI_CMD_MODE_TRX_STATUS); + + rf_if_write_register(IRQ_MASK, CCA_ED_DONE | TRX_END | TRX_UR); + + xah_ctrl_1 = rf_if_read_register(XAH_CTRL_1); + + /*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, RX_SAFE_MODE | 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, RX_SAFE_MODE); + rf_rssi_base_val = -91; + } +} + +/* + * \brief Function returns the RF state + * + * \param none + * + * \return RF state + */ +static rf_trx_states_t rf_if_read_trx_state(void) +{ + return rf_if_trx_status_from_full(rf_if_read_register(TRX_STATUS)); +} + +/* + * \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(); + const uint8_t tx[1] = { 0x20 }; + uint8_t rx[3]; + rf_if_spi_exchange_n(tx, 1, rx, 2); + uint8_t len = rx[1] & 0x7F; + rf_if_spi_exchange_n(NULL, 0, data_out, len); + rf_if_spi_exchange_n(NULL, 0, rx, 3); + *lqi_out = rx[0]; + *ed_out = rx[1]; + *crc_good = rx[2] & 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) & (1 << AACK_SET_PD)) + 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) +{ + const uint8_t cmd[2] = { 0x60, static_cast<uint8_t>(length + 2) }; + + CS_SELECT(); + rf_if_spi_exchange_n(cmd, 2, NULL, 0); + rf_if_spi_exchange_n(ptr, length, NULL, 0); + 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 rf_trx_states_t rf_if_change_trx_state(rf_trx_states_t trx_state) +{ + rf_if_write_register(TRX_STATE, trx_state); + /*Wait while not in desired state*/ + return rf_poll_trx_state_change(trx_state); +} + +/* + * \brief Function starts the CCA process + * + * \param none + * + * \return none + */ +static void rf_if_start_cca_process(void) +{ + rf_if_write_register(PHY_CC_CCA, CCA_REQUEST | CCA_MODE_3A | rf_phy_channel); +} + +/* + * \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, CCA_CHANNEL_MASK); +} + +/* + * \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 +{ + static uint8_t last_is, last_ts; + uint8_t irq_status, full_trx_status; + uint8_t orig_xah_ctrl_1 = xah_ctrl_1; + + /*Read and clear interrupt flag, and pick up trx_status*/ + irq_status = rf_if_read_register_with_status(IRQ_STATUS, &full_trx_status); + uint8_t orig_flags = rf_flags; + + /*Frame end interrupt (RX and TX)*/ + if(irq_status & TRX_END) + { + /*TX done interrupt*/ + rf_trx_states_t trx_status = rf_if_trx_status_from_full(full_trx_status); + if(trx_status == PLL_ON || trx_status == TX_ARET_ON) + { + rf_handle_tx_end(trx_status); + } + /*Frame received interrupt*/ + else + { + rf_handle_rx_end(trx_status); + } + } + if(irq_status & CCA_ED_DONE) + { + rf_handle_cca_ed_done(full_trx_status); + } + if (irq_status & TRX_UR) + { + tr_error("Radio underrun is %x->%x ts %x->%x fl %x->%x x1 %x", last_is, irq_status, last_ts, full_trx_status, orig_flags, rf_flags, orig_xah_ctrl_1); + } + last_is = irq_status; + last_ts = full_trx_status; +} + +/* + * \brief Function writes/read data in SPI interface + */ +static void rf_if_spi_exchange_n(const void *tx, size_t tx_len, void *rx, size_t rx_len) +{ +#if 1 + rf->spi.write(static_cast<const char *>(tx), tx_len, + static_cast<char *>(rx), rx_len); +#else + const uint8_t *txb = static_cast<const uint8_t *>(tx); + uint8_t *rxb = static_cast<uint8_t *>(rx); + while (tx_len > 0 || rx_len > 0) { + uint8_t b; + if (tx_len) { + tx_len--; + b = *txb++; + } else { + b = 0xFF; + } + b = rf->spi.write(b); + if (rx_len) { + rx_len--; + *rxb++ = b; + } + } +#endif +} + +/* + * \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); + } else { + rf_if_disable_irq(); + } + 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 Function is a call back for ACK wait timeout. + * + * \param none + * + * \return none + */ +static void rf_ack_wait_timer_interrupt(void) +{ + rf_if_lock(); + rf_give_up_on_ack(); + 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) +{ + rf_flags_set(RFF_CCA); + /*Start CCA process*/ + 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 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) +{ + 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_trx_states_t trx_status = rf_if_change_trx_state(PLL_ON); + /*Start receiver*/ + rf_receive(trx_status); + /*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 rf_trx_states_t rf_poll_trx_state_change(rf_trx_states_t trx_state) +{ + uint16_t while_counter = 0; + + if(trx_state == FORCE_PLL_ON) + trx_state = PLL_ON; + else if(trx_state == FORCE_TRX_OFF) + trx_state = TRX_OFF; + + rf_trx_states_t state_out; + while((state_out = rf_if_read_trx_state()) != trx_state) + { + while_counter++; + if(while_counter == 0x1ff) + break; + } + + return state_out; +} + +/* + * \brief Function polls the RF state until it is no longer transitioning. + * + * \param trx_state RF state + * + * \return none + */ +static rf_trx_states_t rf_poll_for_state(void) +{ + rf_trx_states_t state_out; + while((state_out = rf_if_read_trx_state()) == STATE_TRANSITION_IN_PROGRESS) + { + } + + return state_out; +} + +/* + * \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*/ + rf_trx_states_t trx_state = rf_if_read_trx_state(); + if(trx_state == BUSY_RX || trx_state == BUSY_RX_AACK || data_length > RF_MTU - 2) + { + rf_if_unlock(); + /*Return busy*/ + return -1; + } + else + { + rf_give_up_on_ack(); + + /*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); +} + +/* + * \brief Function starts the transmission of the frame. + * + * \param none + * + * \return none + */ +static bool rf_start_tx() +{ + /* Attempt change to PLL_ON */ + rf_if_write_register(TRX_STATE, PLL_ON); + + // It appears that if radio is busy, rather than ignoring the state change, + // the state change happens when it stops being busy - eg + // after address match fail or finishing reception. If this happens, we do + // not want to transmit - our channel clear check is stale (either someone is + // still transmitting, or it's a long time since we checked). So wait for the + // PLL_ON change and then go to receive mode without trying to transmit. + rf_trx_states_t state = rf_poll_for_state(); + int poll_count = 0; + while (state != PLL_ON) { + /* Change didn't work (yet) - must be busy - assume it will eventually change */ + state = rf_poll_for_state(); + poll_count++; + } + + rf_flags_clear(RFF_RX); + // Check whether we saw any delay in the PLL_ON transition. + if (poll_count > 0) { + tr_warning("PLL_ON delayed, retry count: %d", poll_count); + // let's get back to the receiving state. + rf_receive(state); + return false; + } + + rf_flags_set(RFF_TX); + /*RF state change: SLP_TR pulse triggers PLL_ON->BUSY_TX*/ + rf_if_enable_slptr(); + /*Chip permits us to write frame buffer while it is transmitting*/ + /*As long as first byte of data is in within 176us of TX start, we're good */ + rf_if_write_frame_buffer(rf_tx_data, rf_tx_length); + rf_if_disable_slptr(); + return true; +} + +/* + * \brief Function sets the RF in RX state. + * + * \param none + * + * \return none + */ +static void rf_receive(rf_trx_states_t trx_status) +{ + uint16_t while_counter = 0; + if(rf_flags_check(RFF_ON) == 0) + { + rf_on(); + rf_channel_set(rf_phy_channel); + trx_status = TRX_OFF; + } + /*If not yet in RX state set it*/ + if(rf_flags_check(RFF_RX) == 0) + { + /*Wait while receiving data. Just making sure, usually this shouldn't happen. */ + while(trx_status == BUSY_RX || trx_status == BUSY_RX_AACK || trx_status == STATE_TRANSITION_IN_PROGRESS) + { + while_counter++; + if(while_counter == 0xffff) + { + break; + } + trx_status = rf_if_read_trx_state(); + } + + if((rf_mode == RF_MODE_SNIFFER) || (rf_mode == RF_MODE_ED)) + { + if (trx_status != RX_ON) { + trx_status = 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(); + } + if (trx_status != RX_AACK_ON) { + trx_status = 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_flags_set(RFF_RX); + } +} + +/* + * \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_trx_states_t trx_status = 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(trx_status); + 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 Abandon waiting for an ack frame + + * \return none + */ +static void rf_give_up_on_ack(void) +{ + if (expected_ack_sequence == -1) { + return; + } + + rf_if_disable_promiscuous_mode(); + rf_if_ack_wait_timer_stop(); + expected_ack_sequence = -1; + + if(device_driver.phy_tx_done_cb){ + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_TX_FAIL, 0, 0); + } +} + +/* + * \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; + /*Received ACK sequence must be equal with transmitted packet sequence*/ + if(expected_ack_sequence == seq_number) + { + rf_if_disable_promiscuous_mode(); + rf_if_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); + } + } else { + rf_give_up_on_ack(); + } +} + +/* + * \brief Function is a call back for RX end interrupt. + * + * \param none + * + * \return none + */ +static void rf_handle_rx_end(rf_trx_states_t trx_status) +{ + /*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) { + rf_give_up_on_ack(); + 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 { + rf_give_up_on_ack(); + 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(rf_trx_states_t trx_status) +{ + 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_TX); + /*Start receiver*/ + rf_receive(trx_status); + + /*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(uint8_t full_trx_status) +{ + if (!rf_flags_check(RFF_CCA)) { + return; + } + rf_flags_clear(RFF_CCA); + + bool success = false; + + /*Check the result of CCA process*/ + if((full_trx_status & CCA_STATUS) && rf_if_trx_status_from_full(full_trx_status) == RX_AACK_ON) + { + success = rf_start_tx(); + } + + if (!success) + { + /*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 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_if_lock(); + rf_mode = RF_MODE_NORMAL; + rf_channel_set(rf_channel); + rf_receive(); + rf_if_enable_irq(); + rf_if_unlock(); + 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); + // 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(); +} + +#if MBED_CONF_ATMEL_RF_PROVIDE_DEFAULT + +NanostackRfPhy &NanostackRfPhy::get_default_instance() +{ + static 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); + return rf_phy; +} + +#endif // MBED_CONF_ATMEL_RF_PROVIDE_DEFAULT + +#endif // MBED_CONF_NANOSTACK_CONFIGURATION
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/source/at24mac.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,82 @@ +/* + * 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::I2CReset::I2CReset(PinName sda, PinName scl) +{ + mbed::DigitalInOut SDA(sda, PIN_OUTPUT, PullUp, 1); + mbed::DigitalInOut SCL(scl, PIN_OUTPUT, PullUp, 0); + //generate 9 clocks for worst-case scenario + for (int i = 0; i < 10; ++i) { + SCL = 1; + wait_us(5); + SCL = 0; + wait_us(5); + } + //generate a STOP condition + SDA = 0; + wait_us(5); + SCL = 1; + wait_us(5); + SDA = 1; + wait_us(5); +} + +/*I2C needs to be reset before constructing the I2C object (in case I2C is stuck) + because they use the same pins, therefore i2c_reset has to be before _i2c + in the initializer list*/ +AT24Mac::AT24Mac(PinName sda, PinName scl) : i2c_reset(sda, 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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/atmel-rf-driver/source/at24mac.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,74 @@ +/* + * 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" +#include "drivers/DigitalInOut.h" +#include "platform/mbed_wait_api.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: + /* + * Dummy class to allow us to reset I2C before the I2C constructor is called in + * the initializer list of AT24Mac's constructor + */ + class I2CReset { + public: + I2CReset(PinName sda, PinName scl); + }; + I2CReset i2c_reset; + mbed::I2C _i2c; +}; + +#endif /* AT24MAC_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/easy-connect.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,440 @@ +/* + * FILE: easy-connect.cpp + * + * Copyright (c) 2015 - 2017 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 "mbed.h" +#include "easy-connect.h" + +/* + * Instantiate the configured network interface + */ +#if MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ESP8266 +#include "ESP8266Interface.h" +#define EASY_CONNECT_WIFI_TYPE "ESP8266" + +#ifdef MBED_CONF_APP_ESP8266_DEBUG +ESP8266Interface wifi(MBED_CONF_EASY_CONNECT_WIFI_ESP8266_TX, MBED_CONF_EASY_CONNECT_WIFI_ESP8266_RX, MBED_CONF_EASY_CONNECT_WIFI_ESP8266_DEBUG); +#else +ESP8266Interface wifi(MBED_CONF_EASY_CONNECT_WIFI_ESP8266_TX, MBED_CONF_EASY_CONNECT_WIFI_ESP8266_RX); +#endif + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ODIN +#define EASY_CONNECT_WIFI_TYPE "Odin" +#include "OdinWiFiInterface.h" +OdinWiFiInterface wifi; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_RTW +#define EASY_CONNECT_WIFI_TYPE "RTW" +#include "RTWInterface.h" +RTWInterface wifi; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_IDW0XX1 +#include "SpwfSAInterface.h" + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW01M1 +#define EASY_CONNECT_WIFI_TYPE "IDW01M1" +SpwfSAInterface wifi(MBED_CONF_EASY_CONNECT_WIFI_IDW01M1_TX, MBED_CONF_EASY_CONNECT_WIFI_IDW01M1_RX); +#endif // MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW01M1 + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 +#define EASY_CONNECT_WIFI_TYPE "IDW04A1" +SpwfSAInterface wifi(MBED_CONF_EASY_CONNECT_WIFI_IDW04A1_TX, MBED_CONF_EASY_CONNECT_WIFI_IDW04A1_RX); +#endif // MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ISM43362 +#include "ISM43362Interface.h" +#define EASY_CONNECT_WIFI_TYPE "ISM43362" + +#ifdef MBED_CONF_APP_ISM43362_DEBUG +ISM43362Interface wifi(true); +#else +ISM43362Interface wifi; +#endif + +#elif MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET +#include "EthernetInterface.h" +EthernetInterface eth; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_LOWPAN_ND +#define EASY_CONNECT_MESH +#include "NanostackInterface.h" +LoWPANNDInterface mesh; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_THREAD +#define EASY_CONNECT_MESH +#include "NanostackInterface.h" +ThreadInterface mesh; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR_ONBOARD +#include "OnboardCellularInterface.h" +OnboardCellularInterface cellular; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR +#include "EasyCellularConnection.h" +EasyCellularConnection cellular; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_WIZFI310 +#include "WizFi310Interface.h" +#define EASY_CONNECT_WIFI_TYPE "WizFi310" + +#ifdef MBED_CONF_APP_WIZFI310_DEBUG + WizFi310Interface wifi(MBED_CONF_EASY_CONNECT_WIFI_WIZFI310_TX, MBED_CONF_EASY_CONNECT_WIFI_WIZFI310_RX, MBED_CONF_EASY_CONNECT_WIFI_WIZFI310_DEBUG); +#else + WizFi310Interface wifi(MBED_CONF_EASY_CONNECT_WIFI_WIZFI310_TX, MBED_CONF_EASY_CONNECT_WIFI_WIZFI310_RX); +#endif + +#elif MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR_WNC14A2A +#include "WNC14A2AInterface.h" + +#if MBED_CONF_APP_WNC_DEBUG == true +#include "WNCDebug.h" +WNCDebug dbgout(stderr); +WNC14A2AInterface wnc(&dbgout); +#else +WNC14A2AInterface wnc; +#endif + + +#else +#error "No connectivity method chosen. Please add 'config.network-interfaces.value' to your mbed_app.json (see README.md for more information)." +#endif // MBED_CONF_APP_NETWORK_INTERFACE + +/* + * In case of Mesh, instantiate the configured RF PHY. + */ +#if defined (EASY_CONNECT_MESH) +#if MBED_CONF_APP_MESH_RADIO_TYPE == ATMEL +#include "NanostackRfPhyAtmel.h" +#define EASY_CONNECT_MESH_TYPE "Atmel" +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" +#define EASY_CONNECT_MESH_TYPE "Mcr20A" +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" +#define EASY_CONNECT_MESH_TYPE "Spirit1" +NanostackRfPhySpirit1 rf_phy(SPIRIT1_SPI_MOSI, SPIRIT1_SPI_MISO, SPIRIT1_SPI_SCLK, + SPIRIT1_DEV_IRQ, SPIRIT1_DEV_CS, SPIRIT1_DEV_SDN, SPIRIT1_BRD_LED); + +#elif MBED_CONF_APP_MESH_RADIO_TYPE == EFR32 +#include "NanostackRfPhyEfr32.h" +#define EASY_CONNECT_MESH_TYPE "EFR32" +NanostackRfPhyEfr32 rf_phy; + +#endif // MBED_CONF_APP_RADIO_TYPE +#endif // EASY_CONNECT_MESH + +#if defined (EASY_CONNECT_WIFI) +#define WIFI_SSID_MAX_LEN 32 // As per IEEE 802.11 chapter 7.3.2.1 (SSID element) +#define WIFI_PASSWORD_MAX_LEN 64 // + +char* _ssid = NULL; +char* _password = NULL; +#endif // EASY_CONNECT_WIFI + +/* \brief print_MAC - print_MAC - helper function to print out MAC address + * in: network_interface - pointer to network i/f + * bool log-messages print out logs or not + * MAC address is printed, if it can be acquired & log_messages is true. + * + */ +void print_MAC(NetworkInterface* network_interface, bool log_messages) { +#if MBED_CONF_APP_NETWORK_INTERFACE != CELLULAR_ONBOARD && MBED_CONF_APP_NETWORK_INTERFACE != CELLULAR + const char *mac_addr = network_interface->get_mac_address(); + if (mac_addr == NULL) { + if (log_messages) { + printf("[EasyConnect] ERROR - No MAC address\n"); + } + return; + } + if (log_messages) { + printf("[EasyConnect] MAC address %s\n", mac_addr); + } +#endif +} + + + +/* \brief easy_connect easy_connect() function to connect the pre-defined network bearer, + * config done via mbed_app.json (see README.md for details). + * + * IN: bool log_messages print out diagnostics or not. + */ +NetworkInterface* easy_connect(bool log_messages) { + NetworkInterface* network_interface = NULL; + int connect_success = -1; + +#if defined (EASY_CONNECT_WIFI) + // We check if the _ssid and _password have already been set (via the easy_connect() + // that takes thoses parameters or not. + // If they have not been set, use the ones we can gain from mbed_app.json. + if (_ssid == NULL) { + if(strlen(MBED_CONF_APP_WIFI_SSID) > WIFI_SSID_MAX_LEN) { + printf("ERROR - MBED_CONF_APP_WIFI_SSID is too long %d vs. %d\n", + strlen(MBED_CONF_APP_WIFI_SSID), + WIFI_SSID_MAX_LEN); + return NULL; + } + } + + if (_password == NULL) { + if(strlen(MBED_CONF_APP_WIFI_PASSWORD) > WIFI_PASSWORD_MAX_LEN) { + printf("ERROR - MBED_CONF_APP_WIFI_PASSWORD is too long %d vs. %d\n", + strlen(MBED_CONF_APP_WIFI_PASSWORD), + WIFI_PASSWORD_MAX_LEN); + return NULL; + } + } +#endif // EASY_CONNECT_WIFI + + /// This should be removed once mbedOS supports proper dual-stack + if (log_messages) { +#if defined (EASY_CONNECT_MESH) || (MBED_CONF_LWIP_IPV6_ENABLED==true) + printf("[EasyConnect] IPv6 mode\n"); +#else + printf("[EasyConnect] IPv4 mode\n"); +#endif + } + +#if defined (EASY_CONNECT_WIFI) + if (log_messages) { + printf("[EasyConnect] Using WiFi (%s) \n", EASY_CONNECT_WIFI_TYPE); + printf("[EasyConnect] Connecting to WiFi %s\n", + ((_ssid == NULL) ? MBED_CONF_APP_WIFI_SSID : _ssid) ); + } + network_interface = &wifi; + if (_ssid == NULL) { + connect_success = wifi.connect(MBED_CONF_APP_WIFI_SSID, MBED_CONF_APP_WIFI_PASSWORD, + (strlen(MBED_CONF_APP_WIFI_PASSWORD) > 1) ? NSAPI_SECURITY_WPA_WPA2 : NSAPI_SECURITY_NONE); + } + else { + connect_success = wifi.connect(_ssid, _password, (strlen(_password) > 1) ? NSAPI_SECURITY_WPA_WPA2 : NSAPI_SECURITY_NONE); + } +#elif MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR_ONBOARD || MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR +# ifdef MBED_CONF_APP_CELLULAR_SIM_PIN + cellular.set_sim_pin(MBED_CONF_APP_CELLULAR_SIM_PIN); +# endif +# ifdef MBED_CONF_APP_CELLULAR_APN +# ifndef MBED_CONF_APP_CELLULAR_USERNAME +# define MBED_CONF_APP_CELLULAR_USERNAME 0 +# endif +# ifndef MBED_CONF_APP_CELLULAR_PASSWORD +# define MBED_CONF_APP_CELLULAR_PASSWORD 0 +# endif + cellular.set_credentials(MBED_CONF_APP_CELLULAR_APN, MBED_CONF_APP_CELLULAR_USERNAME, MBED_CONF_APP_CELLULAR_PASSWORD); + if (log_messages) { + printf("[EasyConnect] Connecting using Cellular interface and APN %s\n", MBED_CONF_APP_CELLULAR_APN); + } +# else + if (log_messages) { + printf("[EasyConnect] Connecting using Cellular interface and default APN\n"); + } +# endif + connect_success = cellular.connect(); + network_interface = &cellular; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR_WNC14A2A + if (log_messages) { + printf("[EasyConnect] Using WNC14A2A\n"); + } +# if MBED_CONF_APP_WNC_DEBUG == true + printf("[EasyConnect] With WNC14A2A debug output set to 0x%02X\n",MBED_CONF_APP_WNC_DEBUG_SETTING); + wnc.doDebug(MBED_CONF_APP_WNC_DEBUG_SETTING); +# endif + network_interface = &wnc; + connect_success = wnc.connect(); + +#elif MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET + if (log_messages) { + printf("[EasyConnect] Using Ethernet\n"); + } + network_interface = ð +#if MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION + eth.set_blocking(false); +#endif + connect_success = eth.connect(); +#endif + +#ifdef EASY_CONNECT_MESH + if (log_messages) { + printf("[EasyConnect] Using Mesh (%s)\n", EASY_CONNECT_MESH_TYPE); + printf("[EasyConnect] Connecting to Mesh...\n"); + } + network_interface = &mesh; +#if MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION + mesh.set_blocking(false); +#endif + mesh.initialize(&rf_phy); + connect_success = mesh.connect(); +#endif + if(connect_success == 0 +#if (MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION && (MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET || defined(EASY_CONNECT_MESH))) + || connect_success == NSAPI_ERROR_IS_CONNECTED || connect_success == NSAPI_ERROR_ALREADY +#endif + ) { +#if (MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION && (MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET || defined(EASY_CONNECT_MESH))) + nsapi_connection_status_t connection_status; + + for (;;) { + + // Check current connection status. + connection_status = network_interface->get_connection_status(); + + if (connection_status == NSAPI_STATUS_GLOBAL_UP) { + + // Connection ready. + break; + + } else if (connection_status == NSAPI_STATUS_ERROR_UNSUPPORTED) { + + if (log_messages) { + print_MAC(network_interface, log_messages); + printf("[EasyConnect] Connection to Network Failed %d!\n", connection_status); + } + return NULL; + + } + + // Not ready yet, give some runtime to the network stack. + mbed::mbed_event_queue()->dispatch(100); + + } +#endif + + if (log_messages) { + printf("[EasyConnect] Connected to Network successfully\n"); + print_MAC(network_interface, log_messages); + } + } else { + if (log_messages) { + print_MAC(network_interface, log_messages); + printf("[EasyConnect] Connection to Network Failed %d!\n", connect_success); + } + return NULL; + } + const char *ip_addr = network_interface->get_ip_address(); + if (ip_addr == NULL) { + if (log_messages) { + printf("[EasyConnect] ERROR - No IP address\n"); + } + return NULL; + } + + if (log_messages) { + printf("[EasyConnect] IP address %s\n", ip_addr); + } + return network_interface; +} + +/* \brief easy_connect - easy_connect function to connect the pre-defined network bearer, + * config done via mbed_app.json (see README.md for details). + * This version is just a helper version and uses the easy_connect() with + * one parameters to do it's job. + * IN: bool log_messages print out diagnostics or not. + * char* WiFiSSID WiFi SSID - pointer to WiFi SSID, but if it is NULL + * then MBED_CONF_APP_WIFI_SSID will be used + * char* WiFiPassword WiFi Password - pointer to WiFI password, but if it's NULL + * then MBED_CONF_APP_WIFI_PASSWORD will be used + */ + +NetworkInterface* easy_connect(bool log_messages, + char* WiFiSSID, + char* WiFiPassword ) { + +// This functionality only makes sense when using WiFi +#if defined (EASY_CONNECT_WIFI) + // We essentially want to populate the _ssid and _password and then call easy_connect() again. + if (WiFiSSID != NULL) { + if(strlen(WiFiSSID) > WIFI_SSID_MAX_LEN) { + printf("ERROR - WiFi SSID is too long - %d vs %d.\n", strlen(WiFiSSID), WIFI_SSID_MAX_LEN); + return NULL; + } + _ssid = WiFiSSID; + } + + if (WiFiPassword != NULL) { + if(strlen(WiFiPassword) > WIFI_PASSWORD_MAX_LEN) { + printf("ERROR - WiFi Password is too long - %d vs %d\n", strlen(WiFiPassword), WIFI_PASSWORD_MAX_LEN); + return NULL; + } + _password = WiFiPassword; + } +#endif // EASY_CONNECT_WIFI + return easy_connect(log_messages); +} + +/* \brief easy_get_netif - easy_connect function to get pointer to network interface + * without connecting to it. + * + * IN: bool log_messages print out diagnostics or not. + */ +NetworkInterface* easy_get_netif(bool log_messages) { +#if defined (EASY_CONNECT_WIFI) + if (log_messages) { + printf("[EasyConnect] WiFi: %s\n", EASY_CONNECT_WIFI_TYPE); + } + return &wifi; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == ETHERNET + if (log_messages) { + printf("[EasyConnect] Ethernet\n"); + } + return ð + +#elif defined (EASY_CONNECT_MESH) + if (log_messages) { + printf("[EasyConnect] Mesh : %s\n", EASY_CONNECT_MESH_TYPE); + } + return &mesh; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR_ONBOARD || MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR + if (log_messages) { + printf("[EasyConnect] Cellular\n"); + } + return &cellular; + +#elif MBED_CONF_APP_NETWORK_INTERFACE == CELLULAR_WNC14A2A + if (log_messages) { + printf("[EasyConnect] WNC14A2A\n"); + } + return &wnc; +#endif +} + +/* \brief easy_get_wifi - easy_connect function to get pointer to Wifi interface + * without connecting to it. You would want this 1st so that + * you can scan the APNs, choose the right one and then connect. + * + * IN: bool log_messages print out diagnostics or not. + */ +WiFiInterface* easy_get_wifi(bool log_messages) { +#if defined (EASY_CONNECT_WIFI) + if (log_messages) { + printf("[EasyConnect] WiFi: %s\n", EASY_CONNECT_WIFI_TYPE); + } + return &wifi; +#else + if (log_messages) { + printf("[EasyConnect] ERROR - Wifi not in use, can not return WifiInterface.\n"); + } + return NULL; +#endif +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/easy-connect.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,122 @@ +/* + * FILE: easy-connect.h + * + * Copyright (c) 2015 - 2017 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 __EASY_CONNECT_H__ +#define __EASY_CONNECT_H__ + +#include "mbed.h" + +#define ETHERNET 1 +#define WIFI_ESP8266 11 +#define WIFI_ODIN 12 +#define WIFI_RTW 13 +#define WIFI_IDW0XX1 14 +#define WIFI_WIZFI310 15 +#define WIFI_ISM43362 16 +#define MESH_LOWPAN_ND 101 +#define MESH_THREAD 102 +#define CELLULAR_ONBOARD 201 +#define CELLULAR 202 +#define CELLULAR_WNC14A2A 203 + +/* Define supersets for WiFi and Mesh */ + +#if MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ESP8266 +#define EASY_CONNECT_WIFI + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ODIN +#define EASY_CONNECT_WIFI + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_RTW +#define EASY_CONNECT_WIFI + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_IDW0XX1 +#define EASY_CONNECT_WIFI + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_WIZFI310 +#define EASY_CONNECT_WIFI + +#elif MBED_CONF_APP_NETWORK_INTERFACE == WIFI_ISM43362 +#define EASY_CONNECT_WIFI + +#elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_LOWPAN_ND +#define EASY_CONNECT_MESH + +#elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_THREAD +#define EASY_CONNECT_MESH +#endif // MBED_CONF_APP_NETWORK_INTERFACE + +#if defined(EASY_CONNECT_MESH) + +// Define macros for radio type +#define ATMEL 1 +#define MCR20 2 +#define SPIRIT1 3 +#define EFR32 4 + +// This is address to mbed Device Connector (hard-coded IP due to DNS might not be there) +#define MBED_SERVER_ADDRESS "coaps://[2607:f0d0:2601:52::20]:5684" + +#else +// This is address to mbed Device Connector +#define MBED_SERVER_ADDRESS "coap://api.connector.mbed.com:5684" + +#endif // (EASY_CONNECT_MESH) + +/* \brief print_MAC - print_MAC - helper function to print out MAC address + * in: network_interface - pointer to network i/f + * bool log-messages print out logs or not + * MAC address is print, if it can be acquired & log_messages is true. + * + */ +void print_MAC(NetworkInterface* network_interface, bool log_messages); + + +/* \brief easy_connect - easy_connect function to connect the pre-defined network bearer, + * config done via mbed_app.json (see README.md for details). + * IN: bool log_messages print out diagnostics or not. + */ +NetworkInterface* easy_connect(bool log_messages = false); + +/* \brief easy_connect - easy_connect function to connect the pre-defined network bearer, + * config done via mbed_app.json (see README.md for details). + * IN: bool log_messages print out diagnostics or not. + * char* WiFiSSID WiFi SSID - by default NULL, but if it's NULL + * then MBED_CONF_APP_WIFI_SSID will be used + * char* WiFiPassword WiFi Password - by default NULL, but if it's NULL + * then MBED_CONF_APP_WIFI_PASSWORD will be used + */ +NetworkInterface* easy_connect(bool log_messages, + char* WiFiSSID, + char* WiFiPassword); + +/* \brief easy_get_netif - easy_connect function to get pointer to network interface w/o connect it. + You might need this for example getting the WiFi interface, then doing a scan + and then connecting to one of the SSIDs found with a password end user supplies. + * IN: bool log_messages print out diagnostics or not. + */ + +NetworkInterface* easy_get_netif(bool log_messages); +/* \brief easy_get_wifi - easy_connect function to get pointer to Wifi interface + * without connecting to it. You would want this 1st so that + * you can scan the APNs, choose the right one and then connect. + * + * IN: bool log_messages print out diagnostics or not. + */ +WiFiInterface* easy_get_wifi(bool log_messages); + +#endif // __EASY_CONNECT_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/esp8266-driver/#5a88ff9c75e34d65e359d7f239bacc456824ed0e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/FETCH_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +59b5304361b43a8fcea7c9637f82e1321446c9d5 tag 'v1.5' of https://github.com/ARMmbed/esp8266-driver
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +5a88ff9c75e34d65e359d7f239bacc456824ed0e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/ORIG_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +5a88ff9c75e34d65e359d7f239bacc456824ed0e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/config Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/esp8266-driver/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/info/exclude Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 7bb1d8e27be54f9f92805a38176478d795aa9dfb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504015 +0000 clone: from https://github.com/ARMmbed/esp8266-driver/ +7bb1d8e27be54f9f92805a38176478d795aa9dfb 5a88ff9c75e34d65e359d7f239bacc456824ed0e www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504016 +0000 checkout: moving from master to 5a88ff9c75e34d65e359d7f239bacc456824ed0e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 7bb1d8e27be54f9f92805a38176478d795aa9dfb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504015 +0000 clone: from https://github.com/ARMmbed/esp8266-driver/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 7bb1d8e27be54f9f92805a38176478d795aa9dfb www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504015 +0000 clone: from https://github.com/ARMmbed/esp8266-driver/
Binary file easy-connect/esp8266-driver/.git/objects/pack/pack-e82aebf5d4cf9434779e8a42d9bccadbe217a9c3.idx has changed
Binary file easy-connect/esp8266-driver/.git/objects/pack/pack-e82aebf5d4cf9434779e8a42d9bccadbe217a9c3.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,17 @@ +# pack-refs with: peeled +4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb refs/remotes/origin/firmware-0.2 +e47620ee6560c710adba1067e8e52937c4eacf3c refs/remotes/origin/firmware-2.0 +11a1703cacd094f24aba878778b886cf1c3648ae refs/remotes/origin/fix_compilation_error +1ae21460e1c87bef97246f6221c104cf663c38d9 refs/remotes/origin/g-connect-retries +e69ab5198be50d2dd7b094119f5267afbbff57ba refs/remotes/origin/g-custom-baud-rate +63cefc73abddc2637cafb0b5785bc2ef4b8ac280 refs/remotes/origin/imsherlock +7bb1d8e27be54f9f92805a38176478d795aa9dfb refs/remotes/origin/master +450cc128865ffb90b5cbfe5af193621644024fa7 refs/tags/v1.0 +29d63ae2ee0a233e2fbd9577cdddc7661bb783d1 refs/tags/v1.1 +4ed87bf7fe37d5ba0de6c4e78868f604a82f8ecb refs/tags/v1.2 +cac4d0d8f97745fe9a613b705b406646aeacc3e2 refs/tags/v1.3 +44fb447c72a37fb397a413467e02208ffeddb88e refs/tags/v1.4 +59b5304361b43a8fcea7c9637f82e1321446c9d5 refs/tags/v1.5 +^5a88ff9c75e34d65e359d7f239bacc456824ed0e +731b75573b0c4738a6cd0f43c598c575e27ac5e8 refs/tags/v1.6 +^e81625ee4d5f715e5414b1c8c52c4299e8373186
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +7bb1d8e27be54f9f92805a38176478d795aa9dfb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<root> + <node _type="integer" _key="update">0</node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/ESP8266/ESP8266.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,670 @@ +/* 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" +#include "mbed_debug.h" +#include "nsapi_types.h" + +#include <cstring> + +#define ESP8266_DEFAULT_BAUD_RATE 115200 +#define ESP8266_ALL_SOCKET_IDS -1 + +ESP8266::ESP8266(PinName tx, PinName rx, bool debug) + : _serial(tx, rx, ESP8266_DEFAULT_BAUD_RATE), + _parser(&_serial), + _packets(0), + _packets_end(&_packets), + _connect_error(0), + _fail(false), + _closed(false), + _socket_open(), + _connection_status(NSAPI_STATUS_DISCONNECTED) +{ + _serial.set_baud( ESP8266_DEFAULT_BAUD_RATE ); + _parser.debug_on(debug); + _parser.set_delimiter("\r\n"); + _parser.oob("+IPD", callback(this, &ESP8266::_packet_handler)); + //Note: espressif at command document says that this should be +CWJAP_CUR:<error code> + //but seems that at least current version is not sending it + //https://www.espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf + //Also seems that ERROR is not sent, but FAIL instead + _parser.oob("+CWJAP:", callback(this, &ESP8266::_connect_error_handler)); + _parser.oob("0,CLOSED", callback(this, &ESP8266::_oob_socket0_closed_handler)); + _parser.oob("1,CLOSED", callback(this, &ESP8266::_oob_socket1_closed_handler)); + _parser.oob("2,CLOSED", callback(this, &ESP8266::_oob_socket2_closed_handler)); + _parser.oob("3,CLOSED", callback(this, &ESP8266::_oob_socket3_closed_handler)); + _parser.oob("4,CLOSED", callback(this, &ESP8266::_oob_socket4_closed_handler)); + _parser.oob("WIFI ", callback(this, &ESP8266::_connection_status_handler)); + _parser.oob("UNLINK", callback(this, &ESP8266::_oob_socket_close_error)); +} + +int ESP8266::get_firmware_version() +{ + int version; + + _smutex.lock(); + bool done = _parser.send("AT+GMR") + && _parser.recv("SDK version:%d", &version) + && _parser.recv("OK\n"); + _smutex.unlock(); + + if(done) { + return version; + } else { + // Older firmware versions do not prefix the version with "SDK version: " + return -1; + } +} + +bool ESP8266::startup(int mode) +{ + if (!(mode == WIFIMODE_STATION || mode == WIFIMODE_SOFTAP + || mode == WIFIMODE_STATION_SOFTAP)) { + return false; + } + + _smutex.lock(); + setTimeout(ESP8266_CONNECT_TIMEOUT); + bool done = _parser.send("AT+CWMODE_CUR=%d", mode) + && _parser.recv("OK\n") + &&_parser.send("AT+CIPMUX=1") + && _parser.recv("OK\n"); + setTimeout(); //Restore default + _smutex.unlock(); + + return done; +} + +bool ESP8266::reset(void) +{ + _smutex.lock(); + setTimeout(ESP8266_CONNECT_TIMEOUT); + + for (int i = 0; i < 2; i++) { + if (_parser.send("AT+RST") + && _parser.recv("OK\n") + && _parser.recv("ready")) { + _clear_socket_packets(ESP8266_ALL_SOCKET_IDS); + _smutex.unlock(); + return true; + } + } + setTimeout(); + _smutex.unlock(); + + return false; +} + +bool ESP8266::dhcp(bool enabled, int mode) +{ + //only 3 valid modes + if (mode < 0 || mode > 2) { + return false; + } + + _smutex.lock(); + bool done = _parser.send("AT+CWDHCP_CUR=%d,%d", mode, enabled?1:0) + && _parser.recv("OK\n"); + _smutex.unlock(); + + return done; +} + +nsapi_error_t ESP8266::connect(const char *ap, const char *passPhrase) +{ + _smutex.lock(); + setTimeout(ESP8266_CONNECT_TIMEOUT); + _connection_status = NSAPI_STATUS_CONNECTING; + if(_connection_status_cb) + _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connection_status); + + _parser.send("AT+CWJAP_CUR=\"%s\",\"%s\"", ap, passPhrase); + if (!_parser.recv("OK\n")) { + if (_fail) { + _smutex.unlock(); + nsapi_error_t ret; + if (_connect_error == 1) + ret = NSAPI_ERROR_CONNECTION_TIMEOUT; + else if (_connect_error == 2) + ret = NSAPI_ERROR_AUTH_FAILURE; + else if (_connect_error == 3) + ret = NSAPI_ERROR_NO_SSID; + else + ret = NSAPI_ERROR_NO_CONNECTION; + + _fail = false; + _connect_error = 0; + return ret; + } + } + setTimeout(); + _smutex.unlock(); + + return NSAPI_ERROR_OK; +} + +bool ESP8266::disconnect(void) +{ + _smutex.lock(); + bool done = _parser.send("AT+CWQAP") && _parser.recv("OK\n"); + _smutex.unlock(); + + return done; +} + +const char *ESP8266::getIPAddress(void) +{ + _smutex.lock(); + setTimeout(ESP8266_CONNECT_TIMEOUT); + if (!(_parser.send("AT+CIFSR") + && _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer) + && _parser.recv("OK\n"))) { + _smutex.unlock(); + return 0; + } + setTimeout(); + _smutex.unlock(); + + return _ip_buffer; +} + +const char *ESP8266::getMACAddress(void) +{ + _smutex.lock(); + if (!(_parser.send("AT+CIFSR") + && _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer) + && _parser.recv("OK\n"))) { + _smutex.unlock(); + return 0; + } + _smutex.unlock(); + + return _mac_buffer; +} + +const char *ESP8266::getGateway() +{ + _smutex.lock(); + if (!(_parser.send("AT+CIPSTA_CUR?") + && _parser.recv("+CIPSTA_CUR:gateway:\"%15[^\"]\"", _gateway_buffer) + && _parser.recv("OK\n"))) { + _smutex.unlock(); + return 0; + } + _smutex.unlock(); + + return _gateway_buffer; +} + +const char *ESP8266::getNetmask() +{ + _smutex.lock(); + if (!(_parser.send("AT+CIPSTA_CUR?") + && _parser.recv("+CIPSTA_CUR:netmask:\"%15[^\"]\"", _netmask_buffer) + && _parser.recv("OK\n"))) { + _smutex.unlock(); + return 0; + } + _smutex.unlock(); + + return _netmask_buffer; +} + +int8_t ESP8266::getRSSI() +{ + int8_t rssi; + char bssid[18]; + + _smutex.lock(); + setTimeout(ESP8266_CONNECT_TIMEOUT); + if (!(_parser.send("AT+CWJAP_CUR?") + && _parser.recv("+CWJAP_CUR:\"%*[^\"]\",\"%17[^\"]\"", bssid) + && _parser.recv("OK\n"))) { + _smutex.unlock(); + return 0; + } + setTimeout(); + _smutex.unlock(); + + _smutex.lock(); + setTimeout(ESP8266_CONNECT_TIMEOUT); + if (!(_parser.send("AT+CWLAP=\"\",\"%s\",", bssid) + && _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi) + && _parser.recv("OK\n"))) { + _smutex.unlock(); + return 0; + } + setTimeout(); + _smutex.unlock(); + + return rssi; +} + +int ESP8266::scan(WiFiAccessPoint *res, unsigned limit) +{ + unsigned cnt = 0; + nsapi_wifi_ap_t ap; + + _smutex.lock(); + setTimeout(ESP8266_CONNECT_TIMEOUT); + + if (!_parser.send("AT+CWLAP")) { + _smutex.unlock(); + return NSAPI_ERROR_DEVICE_ERROR; + } + + while (recv_ap(&ap)) { + if (cnt < limit) { + res[cnt] = WiFiAccessPoint(ap); + } + + cnt++; + if (limit != 0 && cnt >= limit) { + break; + } + } + setTimeout(); + _smutex.unlock(); + + return cnt; +} + +nsapi_error_t ESP8266::open_udp(int id, const char* addr, int port, int local_port) +{ + static const char *type = "UDP"; + bool done = false; + + if (id >= SOCKET_COUNT) { + return NSAPI_ERROR_PARAMETER; + } else if (_socket_open[id]) { + return NSAPI_ERROR_IS_CONNECTED; + } + + _smutex.lock(); + if(local_port) { + done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d,%d", id, type, addr, port, local_port) + && _parser.recv("OK\n"); + } else { + done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port) + && _parser.recv("OK\n"); + } + + if (done) { + _socket_open[id] = 1; + } + + _clear_socket_packets(id); + + _smutex.unlock(); + + return done ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR; +} + +bool ESP8266::open_tcp(int id, const char* addr, int port, int keepalive) +{ + static const char *type = "TCP"; + bool done = false; + + if (id >= SOCKET_COUNT || _socket_open[id]) { + return false; + } + + _smutex.lock(); + if(keepalive) { + done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d,%d", id, type, addr, port, keepalive) + && _parser.recv("OK\n"); + } else { + done = _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port) + && _parser.recv("OK\n"); + } + + if (done) { + _socket_open[id] = 1; + } + + _clear_socket_packets(id); + + _smutex.unlock(); + + return done; +} + +bool ESP8266::dns_lookup(const char* name, char* ip) +{ + _smutex.lock(); + bool done = _parser.send("AT+CIPDOMAIN=\"%s\"", name) && _parser.recv("+CIPDOMAIN:%s%*[\r]%*[\n]", ip); + _smutex.unlock(); + + return done; +} + +nsapi_error_t 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++) { + _smutex.lock(); + setTimeout(ESP8266_SEND_TIMEOUT); + if (_parser.send("AT+CIPSEND=%d,%lu", id, amount) + && _parser.recv(">") + && _parser.write((char*)data, (int)amount) >= 0) { + while (_parser.process_oob()); // multiple sends in a row require this + _smutex.unlock(); + return NSAPI_ERROR_OK; + } + setTimeout(); + _smutex.unlock(); + } + + return NSAPI_ERROR_DEVICE_ERROR; +} + +void ESP8266::_packet_handler() +{ + int id; + int 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) { + debug("ESP8266: could not allocate memory for RX data\n"); + return; + } + + packet->id = id; + packet->len = amount; + packet->next = 0; + + if (_parser.read((char*)(packet + 1), amount) < amount) { + free(packet); + return; + } + + // append to packet list + *_packets_end = packet; + _packets_end = &packet->next; +} + +int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout) +{ + _smutex.lock(); + setTimeout(timeout); + + // Poll for inbound packets + while (_parser.process_oob()) { + } + + setTimeout(); + + // 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; + _smutex.unlock(); + + 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); + + _smutex.unlock(); + return amount; + } + } + } + if(!_socket_open[id]) { + _smutex.unlock(); + return 0; + } + _smutex.unlock(); + + return NSAPI_ERROR_WOULD_BLOCK; +} + +int32_t ESP8266::recv_udp(int id, void *data, uint32_t amount, uint32_t timeout) +{ + _smutex.lock(); + setTimeout(timeout); + + // Poll for inbound packets + while (_parser.process_oob()) { + } + + setTimeout(); + + // 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; + + // Return and remove packet (truncated if necessary) + uint32_t len = q->len < amount ? q->len : amount; + memcpy(data, q+1, len); + + if (_packets_end == &(*p)->next) { + _packets_end = p; + } + *p = (*p)->next; + _smutex.unlock(); + + free(q); + return len; + } + } + _smutex.unlock(); + + return NSAPI_ERROR_WOULD_BLOCK; +} + +void ESP8266::_clear_socket_packets(int id) +{ + struct packet **p = &_packets; + + while (*p) { + if ((*p)->id == id || id == ESP8266_ALL_SOCKET_IDS) { + struct packet *q = *p; + + if (_packets_end == &(*p)->next) { + _packets_end = p; // Set last packet next field/_packets + } + *p = (*p)->next; + + free(q); + } else { + // Point to last packet next field + p = &(*p)->next; + } + } +} + +bool ESP8266::close(int id) +{ + //May take a second try if device is busy + for (unsigned i = 0; i < 2; i++) { + _smutex.lock(); + if (_parser.send("AT+CIPCLOSE=%d", id)) { + if (!_parser.recv("OK\n")) { + if (_closed) { // UNLINK ERROR + _closed = false; + _socket_open[id] = 0; + _clear_socket_packets(id); + _smutex.unlock(); + // ESP8266 has a habit that it might close a socket on its own. + //debug("ESP8266: socket %d already closed when calling close\n", id); + return true; + } + } else { + _clear_socket_packets(id); + _smutex.unlock(); + return true; + } + } + _smutex.unlock(); + } + + return false; +} + +void ESP8266::setTimeout(uint32_t timeout_ms) +{ + _parser.set_timeout(timeout_ms); +} + +bool ESP8266::readable() +{ + return _serial.FileHandle::readable(); +} + +bool ESP8266::writeable() +{ + return _serial.FileHandle::writable(); +} + +void ESP8266::sigio(Callback<void()> func) +{ + _serial.sigio(func); +} + +void ESP8266::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) +{ + _connection_status_cb = status_cb; +} + +bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap) +{ + int sec; + int dummy; + bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%hhu,%d,%d)\n", + &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, + &dummy, + &dummy); + + ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN; + + return ret; +} + +void ESP8266::_connect_error_handler() +{ + _fail = false; + _connect_error = 0; + + if (_parser.recv("%d", &_connect_error) && _parser.recv("FAIL")) { + _fail = true; + _parser.abort(); + } +} + +void ESP8266::_oob_socket_close_error() +{ + if (_parser.recv("ERROR\n")) { + _closed = true; // Not possible to pinpoint to a certain socket + _parser.abort(); + } +} + +void ESP8266::_oob_socket0_closed_handler() +{ + _socket_open[0] = 0; +} + +void ESP8266::_oob_socket1_closed_handler() +{ + _socket_open[1] = 0; +} + +void ESP8266::_oob_socket2_closed_handler() +{ + _socket_open[2] = 0; +} + +void ESP8266::_oob_socket3_closed_handler() +{ + _socket_open[3] = 0; +} + +void ESP8266::_oob_socket4_closed_handler() +{ + _socket_open[4] = 0; +} + +void ESP8266::_connection_status_handler() +{ + char status[13]; + if (_parser.recv("%12[^\"]\n", status)) { + if (strcmp(status, "GOT IP\n") == 0) + _connection_status = NSAPI_STATUS_GLOBAL_UP; + else if (strcmp(status, "DISCONNECT\n") == 0) + _connection_status = NSAPI_STATUS_DISCONNECTED; + else + return; + + if(_connection_status_cb) + _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connection_status); + } +} + +int8_t ESP8266::get_default_wifi_mode() +{ + int8_t mode; + + _smutex.lock(); + if (_parser.send("AT+CWMODE_DEF?") + && _parser.recv("+CWMODE_DEF:%hhd", &mode) + && _parser.recv("OK\n")) { + _smutex.unlock(); + return mode; + } + _smutex.unlock(); + + return 0; +} + +bool ESP8266::set_default_wifi_mode(const int8_t mode) +{ + _smutex.lock(); + bool done = _parser.send("AT+CWMODE_DEF=%hhd", mode) + && _parser.recv("OK\n"); + _smutex.unlock(); + + return done; +} + +nsapi_connection_status_t ESP8266::get_connection_status() const +{ + return _connection_status; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/ESP8266/ESP8266.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,309 @@ +/* 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 "ATCmdParser.h" +#include "nsapi_types.h" +#include "rtos.h" + +// Various timeouts for different ESP8266 operations +#ifndef ESP8266_CONNECT_TIMEOUT +#define ESP8266_CONNECT_TIMEOUT 15000 +#endif +#ifndef ESP8266_SEND_TIMEOUT +#define ESP8266_SEND_TIMEOUT 2000 +#endif +#ifndef ESP8266_RECV_TIMEOUT +#define ESP8266_RECV_TIMEOUT 2000 +#endif +#ifndef ESP8266_MISC_TIMEOUT +#define ESP8266_MISC_TIMEOUT 2000 +#endif + +/** ESP8266Interface class. + This is an interface to a ESP8266 radio. + */ +class ESP8266 +{ +public: + ESP8266(PinName tx, PinName rx, bool debug=false); + + /** + * Check firmware version of ESP8266 + * + * @return integer firmware version or -1 if firmware query command gives outdated response + */ + int get_firmware_version(void); + + /** + * 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 NSAPI_ERROR_OK only if ESP8266 is connected successfully + */ + nsapi_error_t 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(); + + /** 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); + + /**Perform a dns query + * + * @param name Hostname to resolve + * @param ip Buffer to store IP address + * @return 0 true on success, false on failure + */ + bool dns_lookup(const char *name, char *ip); + + /** + * 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 + * @param port the port on the destination + * @param local_port UDP socket's local port, zero means any + * @return true only if socket opened successfully + */ + nsapi_error_t open_udp(int id, const char* addr, int port, int local_port = 0); + + /** + * 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 + * @param port the port on the destination + * @param tcp_keepalive TCP connection's keep alive time, zero means disabled + * @return true only if socket opened successfully + */ + bool open_tcp(int id, const char* addr, int port, int keepalive = 0); + + /** + * 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 NSAPI_ERROR_OK in success, negative error code in failure + */ + nsapi_error_t send(int id, const void *data, uint32_t amount); + + /** + * Receives datagram from an open UDP 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_udp(int id, void *data, uint32_t amount, uint32_t timeout=ESP8266_RECV_TIMEOUT); + + /** + * Receives stream data from an open TCP 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_tcp(int id, void *data, uint32_t amount, uint32_t timeout=ESP8266_RECV_TIMEOUT); + + /** + * 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=ESP8266_MISC_TIMEOUT); + + /** + * Checks if data is available + */ + bool readable(); + + /** + * Checks if data can be written + */ + bool writeable(); + + /** + * Attach a function to call whenever sigio happens in the serial + * + * @param func A pointer to a void function, or 0 to set as none + */ + void sigio(Callback<void()> func); + + /** + * Attach a function to call whenever sigio happens in the serial + * + * @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 sigio(T *obj, M method) { + sigio(Callback<void()>(obj, method)); + } + + /** + * 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(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb); + + /** + * Read default Wifi mode from flash + * + * return Station, SoftAP or SoftAP+Station - 0 on failure + */ + int8_t get_default_wifi_mode(); + + /** + * Write default Wifi mode to flash + */ + bool set_default_wifi_mode(const int8_t mode); + + /** Get the connection status + * + * @return The connection status according to ConnectionStatusType + */ + nsapi_connection_status_t get_connection_status() const; + + static const int8_t WIFIMODE_STATION = 1; + static const int8_t WIFIMODE_SOFTAP = 2; + static const int8_t WIFIMODE_STATION_SOFTAP = 3; + static const int8_t SOCKET_COUNT = 5; + +private: + UARTSerial _serial; + ATCmdParser _parser; + Mutex _smutex; // Protect serial port access + + struct packet { + struct packet *next; + int id; + uint32_t len; + // data follows + } *_packets, **_packets_end; + void _packet_handler(); + void _connect_error_handler(); + bool recv_ap(nsapi_wifi_ap_t *ap); + void _oob_socket0_closed_handler(); + void _oob_socket1_closed_handler(); + void _oob_socket2_closed_handler(); + void _oob_socket3_closed_handler(); + void _oob_socket4_closed_handler(); + void _connection_status_handler(); + void _oob_socket_close_error(); + void _clear_socket_packets(int id); + + char _ip_buffer[16]; + char _gateway_buffer[16]; + char _netmask_buffer[16]; + char _mac_buffer[18]; + + int _connect_error; + bool _fail; + bool _closed; + int _socket_open[SOCKET_COUNT]; + nsapi_connection_status_t _connection_status; + Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/ESP8266Interface.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,577 @@ +/* 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 <cstring> +#include "ESP8266.h" +#include "ESP8266Interface.h" +#include "mbed_debug.h" +#include "nsapi_types.h" + + +#ifndef MBED_CONF_ESP8266_TX +#ifdef TARGET_FF_ARDUINO +#define MBED_CONF_ESP8266_TX D1 +#else +#define MBED_CONF_ESP8266_TX NC +#endif +#endif + +#ifndef MBED_CONF_ESP8266_RX +#ifdef TARGET_FF_ARDUINO +#define MBED_CONF_ESP8266_RX D0 +#else +#define MBED_CONF_ESP8266_RX NC +#endif +#endif + +// Firmware version +#define ESP8266_VERSION 2 + +ESP8266Interface::ESP8266Interface() + : _esp(MBED_CONF_ESP8266_TX, MBED_CONF_ESP8266_RX, MBED_CONF_ESP8266_DEBUG), + _initialized(false), + _started(false) +{ + memset(_ids, 0, sizeof(_ids)); + memset(_cbs, 0, sizeof(_cbs)); + memset(ap_ssid, 0, sizeof(ap_ssid)); + memset(ap_pass, 0, sizeof(ap_pass)); + memset(_local_ports, 0, sizeof(_local_ports)); + ap_sec = NSAPI_SECURITY_UNKNOWN; + + _esp.sigio(this, &ESP8266Interface::event); + _esp.setTimeout(); +} + +// ESP8266Interface implementation +ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug) + : _esp(tx, rx, debug), + _initialized(false), + _started(false) +{ + memset(_ids, 0, sizeof(_ids)); + memset(_cbs, 0, sizeof(_cbs)); + memset(ap_ssid, 0, sizeof(ap_ssid)); + memset(ap_pass, 0, sizeof(ap_pass)); + memset(_local_ports, 0, sizeof(_local_ports)); + ap_sec = NSAPI_SECURITY_UNKNOWN; + + _esp.sigio(this, &ESP8266Interface::event); + _esp.setTimeout(); +} + +int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security_t security, + uint8_t channel) +{ + if (channel != 0) { + return NSAPI_ERROR_UNSUPPORTED; + } + + int err = set_credentials(ssid, pass, security); + if(err) { + return err; + } + + return connect(); +} + +int ESP8266Interface::connect() +{ + nsapi_error_t status; + + if (strlen(ap_ssid) == 0) { + return NSAPI_ERROR_NO_SSID; + } + + if (ap_sec != NSAPI_SECURITY_NONE) { + if (strlen(ap_pass) < ESP8266_PASSPHRASE_MIN_LENGTH) { + return NSAPI_ERROR_PARAMETER; + } + } + + status = _init(); + if(status != NSAPI_ERROR_OK) { + return status; + } + + if(get_ip_address()) { + return NSAPI_ERROR_IS_CONNECTED; + } + + status = _startup(ESP8266::WIFIMODE_STATION); + if(status != NSAPI_ERROR_OK) { + return status; + } + _started = true; + + if (!_esp.dhcp(true, 1)) { + return NSAPI_ERROR_DHCP_FAILURE; + } + + int connect_error = _esp.connect(ap_ssid, ap_pass); + if (connect_error) { + return connect_error; + } + + if (!get_ip_address()) { + return NSAPI_ERROR_DHCP_FAILURE; + } + + return NSAPI_ERROR_OK; +} + +int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) +{ + ap_sec = security; + + if (!ssid) { + return NSAPI_ERROR_PARAMETER; + } + + int ssid_length = strlen(ssid); + + if (ssid_length > 0 + && ssid_length <= ESP8266_SSID_MAX_LENGTH) { + memset(ap_ssid, 0, sizeof(ap_ssid)); + strncpy(ap_ssid, ssid, sizeof(ap_ssid)); + } else { + return NSAPI_ERROR_PARAMETER; + } + + if (ap_sec != NSAPI_SECURITY_NONE) { + + if (!pass) { + return NSAPI_ERROR_PARAMETER; + } + + int pass_length = strlen(pass); + if (pass_length >= ESP8266_PASSPHRASE_MIN_LENGTH + && pass_length <= ESP8266_PASSPHRASE_MAX_LENGTH ) { + memset(ap_pass, 0, sizeof(ap_pass)); + strncpy(ap_pass, pass, sizeof(ap_pass)); + } else { + return NSAPI_ERROR_PARAMETER; + } + } else { + memset(ap_pass, 0, sizeof(ap_pass)); + } + + return NSAPI_ERROR_OK; +} + +int ESP8266Interface::set_channel(uint8_t channel) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + + +int ESP8266Interface::disconnect() +{ + _started = false; + _initialized = false; + + return _esp.disconnect() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR; +} + +const char *ESP8266Interface::get_ip_address() +{ + if(!_started) { + return NULL; + } + + const char *ip_buff = _esp.getIPAddress(); + if(!ip_buff || std::strcmp(ip_buff, "0.0.0.0") == 0) { + return NULL; + } + + return ip_buff; +} + +const char *ESP8266Interface::get_mac_address() +{ + return _esp.getMACAddress(); +} + +const char *ESP8266Interface::get_gateway() +{ + return _started ? _esp.getGateway() : NULL; +} + +const char *ESP8266Interface::get_netmask() +{ + return _started ? _esp.getNetmask() : NULL; +} + +int8_t ESP8266Interface::get_rssi() +{ + return _started ? _esp.getRSSI() : 0; +} + +int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count) +{ + nsapi_error_t status; + + status = _init(); + if(status != NSAPI_ERROR_OK) { + return status; + } + + status = _startup(ESP8266::WIFIMODE_STATION); + if(status != NSAPI_ERROR_OK) { + return status; + } + + return _esp.scan(res, count); +} + +bool ESP8266Interface::_get_firmware_ok() +{ + if (_esp.get_firmware_version() != ESP8266_VERSION) { + debug("ESP8266: ERROR: Firmware incompatible with this driver.\ + \r\nUpdate to v%d - https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update\r\n",ESP8266_VERSION); + return false; + } + + return true; +} + +bool ESP8266Interface::_disable_default_softap() +{ + static int disabled = false; + + if (disabled || _esp.get_default_wifi_mode() == ESP8266::WIFIMODE_STATION) { + disabled = true; + return true; + } + if (_esp.set_default_wifi_mode(ESP8266::WIFIMODE_STATION)) { + disabled = true; + return true; + } + + return false; +} + +nsapi_error_t ESP8266Interface::_init(void) +{ + if (!_initialized) { + if (!_esp.reset()) { + return NSAPI_ERROR_DEVICE_ERROR; + } + if (!_get_firmware_ok()) { + return NSAPI_ERROR_DEVICE_ERROR; + } + if (_disable_default_softap() == false) { + return NSAPI_ERROR_DEVICE_ERROR; + } + _initialized = true; + } + return NSAPI_ERROR_OK; +} + +nsapi_error_t ESP8266Interface::_startup(const int8_t wifi_mode) +{ + if (!_started) { + if (!_esp.startup(wifi_mode)) { + return NSAPI_ERROR_DEVICE_ERROR; + } + } + return NSAPI_ERROR_OK; +} + +struct esp8266_socket { + int id; + nsapi_protocol_t proto; + bool connected; + SocketAddress addr; + int keepalive; // TCP +}; + +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; + socket->keepalive = 0; + *handle = socket; + return 0; +} + +int ESP8266Interface::socket_close(void *handle) +{ + struct esp8266_socket *socket = (struct esp8266_socket *)handle; + int err = 0; + + if (!socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + if (socket->connected && !_esp.close(socket->id)) { + err = NSAPI_ERROR_DEVICE_ERROR; + } + + socket->connected = false; + _ids[socket->id] = false; + _local_ports[socket->id] = 0; + delete socket; + return err; +} + +int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address) +{ + struct esp8266_socket *socket = (struct esp8266_socket *)handle; + + if (!socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + if (socket->proto == NSAPI_UDP) { + if(address.get_addr().version != NSAPI_UNSPEC) { + return NSAPI_ERROR_UNSUPPORTED; + } + + for(int id = 0; id < ESP8266_SOCKET_COUNT; id++) { + if(_local_ports[id] == address.get_port() && id != socket->id) { // Port already reserved by another socket + return NSAPI_ERROR_PARAMETER; + } else if (id == socket->id && socket->connected) { + return NSAPI_ERROR_PARAMETER; + } + } + _local_ports[socket->id] = address.get_port(); + return 0; + } + + 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; + nsapi_error_t ret; + + if (!socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + if (socket->proto == NSAPI_UDP) { + ret = _esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id]); + if (ret != NSAPI_ERROR_OK) { + return ret; + } + } else { + if (!_esp.open_tcp(socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive)) { + 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) +{ + nsapi_error_t status; + struct esp8266_socket *socket = (struct esp8266_socket *)handle; + + if (!socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + status = _esp.send(socket->id, data, size); + + return status != NSAPI_ERROR_OK ? status : size; +} + +int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size) +{ + struct esp8266_socket *socket = (struct esp8266_socket *)handle; + + if (!socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + int32_t recv; + if (socket->proto == NSAPI_TCP) { + recv = _esp.recv_tcp(socket->id, data, size); + if (recv <= 0 && recv != NSAPI_ERROR_WOULD_BLOCK) { + socket->connected = false; + } + } else { + recv = _esp.recv_udp(socket->id, data, size); + } + + 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) { + return NSAPI_ERROR_NO_SOCKET; + } + + if((strcmp(addr.get_ip_address(), "0.0.0.0") == 0) || !addr.get_port()) { + return NSAPI_ERROR_DNS_FAILURE; + } + + if (socket->connected && socket->addr != addr) { + 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; + + if (!socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + 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; +} + +nsapi_error_t ESP8266Interface::setsockopt(nsapi_socket_t handle, int level, + int optname, const void *optval, unsigned optlen) +{ + struct esp8266_socket *socket = (struct esp8266_socket *)handle; + + if (!optlen) { + return NSAPI_ERROR_PARAMETER; + } else if (!socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) { + switch (optname) { + case NSAPI_KEEPALIVE: { + if(socket->connected) {// ESP8266 limitation, keepalive needs to be given before connecting + return NSAPI_ERROR_UNSUPPORTED; + } + + if (optlen == sizeof(int)) { + int secs = *(int *)optval; + if (secs >= 0 && secs <= 7200) { + socket->keepalive = secs; + return NSAPI_ERROR_OK; + } + } + return NSAPI_ERROR_PARAMETER; + } + } + } + + return NSAPI_ERROR_UNSUPPORTED; +} + +nsapi_error_t ESP8266Interface::getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen) +{ + struct esp8266_socket *socket = (struct esp8266_socket *)handle; + + if (!optval || !optlen) { + return NSAPI_ERROR_PARAMETER; + } else if (!socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) { + switch (optname) { + case NSAPI_KEEPALIVE: { + if(*optlen > sizeof(int)) { + *optlen = sizeof(int); + } + memcpy(optval, &(socket->keepalive), *optlen); + return NSAPI_ERROR_OK; + } + } + } + + return NSAPI_ERROR_UNSUPPORTED; +} + + +void ESP8266Interface::event() +{ + for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) { + if (_cbs[i].callback) { + _cbs[i].callback(_cbs[i].data); + } + } +} + +void ESP8266Interface::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) +{ + _esp.attach(status_cb); +} + +nsapi_connection_status_t ESP8266Interface::get_connection_status() const +{ + return _esp.get_connection_status(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/ESP8266Interface.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,346 @@ +/* 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: + /** + * @brief ESP8266Interface default constructor + * Will use values defined in mbed_lib.json + */ + ESP8266Interface(); + + /** 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; + + /** Set socket options + * + * The setsockopt allow an application to pass stack-specific hints + * to the underlying stack. For unsupported options, + * NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified. + * + * @param handle Socket handle + * @param level Stack-specific protocol level + * @param optname Stack-specific option identifier + * @param optval Option value + * @param optlen Length of the option value + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t setsockopt(nsapi_socket_t handle, int level, + int optname, const void *optval, unsigned optlen); + + /** Get socket options + * + * getsockopt allows an application to retrieve stack-specific options + * from the underlying stack using stack-specific level and option names, + * or to request generic options using levels from nsapi_socket_level_t. + * + * For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned + * and the socket is unmodified. + * + * @param level Stack-specific protocol level or nsapi_socket_level_t + * @param optname Level-specific option name + * @param optval Destination for option value + * @param optlen Length of the option value + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t getsockopt(nsapi_socket_t handle, int level, int optname, + void *optval, unsigned *optlen); + + /** Register callback for status reporting + * + * The specified status callback function will be called on status changes + * on the network. The parameters on the callback are the event type and + * event-type dependent reason parameter. + * + * In ESP8266 the callback will be called when processing OOB-messages via + * AT-parser. Do NOT call any ESP8266Interface -functions or do extensive + * processing in the callback. + * + * @param status_cb The callback for status changes + */ + virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb); + + /** Get the connection status + * + * @return The connection status according to ConnectionStatusType + */ + virtual nsapi_connection_status_t get_connection_status() const; + +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: + static const int ESP8266_SSID_MAX_LENGTH = 32; /* 32 is what 802.11 defines as longest possible name */ + static const int ESP8266_PASSPHRASE_MAX_LENGTH = 63; /* The longest allowed passphrase */ + static const int ESP8266_PASSPHRASE_MIN_LENGTH = 8; /* The shortest allowed passphrase */ + + ESP8266 _esp; + bool _ids[ESP8266_SOCKET_COUNT]; + int _initialized; + int _started; + + char ap_ssid[ESP8266_SSID_MAX_LENGTH + 1]; /* 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[ESP8266_PASSPHRASE_MAX_LENGTH + 1]; + uint16_t _local_ports[ESP8266_SOCKET_COUNT]; + + bool _disable_default_softap(); + void event(); + bool _get_firmware_ok(); + nsapi_error_t _init(void); + nsapi_error_t _startup(const int8_t wifi_mode); + + struct { + void (*callback)(void *); + void *data; + } _cbs[ESP8266_SOCKET_COUNT]; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/README.md Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,13 @@ +# ESP8266 WiFi driver for Mbed OS + +The Mbed OS driver for the ESP8266 WiFi module. + +## Firmware version + +ESP8266 modules come in different shapes and formats, but the most important factor is the firmware version in it. To make sure that the firmware in your module is compatible with Mbed OS, follow the [Update guide](https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update). + +## Restrictions + +- The ESP8266 WiFi module does not allow the TCP client to bind on a specific port. +- Setting up a UDP server is not possible. +- The serial port does not have hardware flow control enabled. The AT command set does not either have a way to limit the download rate. Therefore, downloading anything larger than the serial port input buffer is unreliable. An application should be able to read fast enough to stay ahead of the network. This affects mostly the TCP protocol where data would be lost with no notification. On UDP, this would lead to only packet losses which the higher layer protocol should recover from.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/.mbedignore Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +host_tests/* \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/connectivity/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,76 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" + +#include "ESP8266Interface.h" + +using namespace utest::v1; + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Bringing the network up and down +template <int COUNT> +void test_bring_up_down() { + ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); + net.set_credentials(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + + for (int i = 0; i < COUNT; i++) { + int err = net.connect(); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: IP Address %s\r\n", net.get_ip_address()); + printf("MBED: Netmask %s\r\n", net.get_netmask()); + printf("MBED: Gateway %s\r\n", net.get_gateway()); + TEST_ASSERT(net.get_ip_address()); + TEST_ASSERT(net.get_netmask()); + TEST_ASSERT(net.get_gateway()); + + UDPSocket udp; + err = udp.open(&net); + TEST_ASSERT_EQUAL(0, err); + err = udp.close(); + TEST_ASSERT_EQUAL(0, err); + + TCPSocket tcp; + err = tcp.open(&net); + TEST_ASSERT_EQUAL(0, err); + err = tcp.close(); + TEST_ASSERT_EQUAL(0, err); + + err = net.disconnect(); + TEST_ASSERT_EQUAL(0, err); + } +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Bringing the network up and down", test_bring_up_down<1>), + Case("Bringing the network up and down twice", test_bring_up_down<2>), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/gethostbyname/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,118 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "ESP8266Interface.h" + +using namespace utest::v1; + +// Hostname for testing against +// Must have A and AAAA records +#ifndef MBED_DNS_TEST_HOST +#define MBED_DNS_TEST_HOST "connector.mbed.com" +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + +// Address info from stack +const char *ip_literal; +nsapi_version_t ip_pref; +const char *ip_pref_repr; + +// Network setup +ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); +void net_bringup() { + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + printf("MBED: Connected to network\n"); + printf("MBED: IP Address: %s\n", net.get_ip_address()); + + ip_literal = net.get_ip_address(); + ip_pref = SocketAddress(ip_literal).get_ip_version(); + ip_pref_repr = (ip_pref == NSAPI_IPv4) ? "ipv4" : + (ip_pref == NSAPI_IPv6) ? "ipv6" : "unspec"; +} + + +// DNS tests +void test_dns_query() { + SocketAddress addr; + int err = net.gethostbyname(MBED_DNS_TEST_HOST, &addr); + printf("DNS: query \"%s\" => \"%s\"\n", + MBED_DNS_TEST_HOST, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); +} + +void test_dns_query_pref() { + SocketAddress addr; + int err = net.gethostbyname(MBED_DNS_TEST_HOST, &addr, ip_pref); + printf("DNS: query %s \"%s\" => \"%s\"\n", + ip_pref_repr, MBED_DNS_TEST_HOST, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT_EQUAL(ip_pref, addr.get_ip_version()); +} + +void test_dns_literal() { + SocketAddress addr; + int err = net.gethostbyname(ip_literal, &addr); + printf("DNS: literal \"%s\" => \"%s\"\n", + ip_literal, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT(strcmp(ip_literal, addr.get_ip_address()) == 0); +} + +void test_dns_literal_pref() { + SocketAddress addr; + int err = net.gethostbyname(ip_literal, &addr, ip_pref); + printf("DNS: literal %s \"%s\" => \"%s\"\n", + ip_pref_repr, ip_literal, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT_EQUAL(ip_pref, addr.get_ip_version()); + TEST_ASSERT(strcmp(ip_literal, addr.get_ip_address()) == 0); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + net_bringup(); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("DNS query", test_dns_query), + Case("DNS preference query", test_dns_query_pref), + Case("DNS literal", test_dns_literal), + Case("DNS preference literal", test_dns_literal_pref), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/host_tests/tcp_echo.py Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,195 @@ +# Copyright 2015 ARM Limited, All rights reserved +# +# 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. + +import sys +import select +import socket +import logging +from threading import Thread +from sys import stdout +from SocketServer import BaseRequestHandler, TCPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class TCPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ + Handles a connection. Test starts by client(i.e. mbed) connecting to server. + This connection handler receives data and echoes back to the client util + {{end}} is received. Then it sits on recv() for client to terminate the + connection. + + Note: reason for not echoing data back after receiving {{end}} is that send + fails raising a SocketError as client closes connection. + """ + while self.server.isrunning(): + try: + data = self.recv() + if not data: break + except Exception as e: + break + + try: + # echo data back to the client + self.send(data) + except Exception as e: + break + + def recv(self): + """ + Try to receive until server is shutdown + """ + while self.server.isrunning(): + rl, wl, xl = select.select([self.request], [], [], 1) + if len(rl): + return self.request.recv(1024) + + def send(self, data): + """ + Try to send until server is shutdown + """ + while self.server.isrunning(): + rl, wl, xl = select.select([], [self.request], [], 1) + if len(wl): + self.request.sendall(data) + break + + +class TCPServerWrapper(TCPServer): + """ + Wrapper over TCP server to implement server initiated shutdown. + Adds a flag:= running that a request handler can check and come out of + recv loop when shutdown is called. + """ + + def __init__(self, addr, request_handler): + # hmm, TCPServer is not sub-classed from object! + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).__init__(addr, request_handler) + else: + TCPServer.__init__(self, addr, request_handler) + self.running = False + + def serve_forever(self): + self.running = True + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).serve_forever() + else: + TCPServer.serve_forever(self) + + def shutdown(self): + self.running = False + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).shutdown() + else: + TCPServer.shutdown(self) + + def isrunning(self): + return self.running + + +class TCPEchoClientTest(BaseHostTest): + + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_tcp_server(self): + """ + sets up a TCP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_tcp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = TCPServerWrapper((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for TCP connections: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=TCPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_tcp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/host_tests/udp_echo.py Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,127 @@ +""" +mbed SDK +Copyright (c) 2011-2013 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. +""" + +import sys +import socket +from sys import stdout +from threading import Thread +from SocketServer import BaseRequestHandler, UDPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class UDPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ UDP packet handler. Echoes data back to sender's address. + """ + data, sock = self.request + sock.sendto(data, self.client_address) + + +class UDPEchoClientTest(BaseHostTest): + + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_udp_server(self): + """ + sets up a UDP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_udp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_udp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/host_tests/udp_shotgun.py Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,142 @@ +""" +mbed SDK +Copyright (c) 2011-2013 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. +""" + +import sys +import socket +import json +import random +import itertools +import time +from sys import stdout +from threading import Thread +from SocketServer import BaseRequestHandler, UDPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class UDPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ UDP packet handler. Responds with multiple simultaneous packets + """ + data, sock = self.request + pattern = [ord(d) << 4 for d in data] + + # Each byte in request indicates size of packet to recieve + # Each packet size is shifted over by 4 to fit in a byte, which + # avoids any issues with endianess or decoding + for packet in pattern: + data = [random.randint(0, 255) for _ in range(packet-1)] + data.append(reduce(lambda a,b: a^b, data)) + data = ''.join(map(chr, data)) + sock.sendto(data, self.client_address) + + # Sleep a tiny bit to compensate for local network + time.sleep(0.01) + + +class UDPEchoClientTest(BaseHostTest): + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_udp_server(self): + """ + sets up a UDP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_udp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_udp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/tcp_echo/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,112 @@ +#include "mbed.h" +#include "ESP8266Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 256 +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + +namespace { + char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + const char ASCII_MAX = '~' - ' '; +} + +void prep_buffer(char *tx_buffer, size_t tx_size) { + for (size_t i=0; i<tx_size; ++i) { + tx_buffer[i] = (rand() % 10) + '0'; + } +} + +void test_tcp_echo() { + ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + + if (err) { + printf("MBED: failed to connect with an error of %d\r\n", err); + TEST_ASSERT_EQUAL(0, err); + } + + printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + bool result = false; + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + + TCPSocket sock(&net); + SocketAddress tcp_addr(ipbuf, port); + if (sock.connect(tcp_addr) == 0) { + printf("HTTP: Connected to %s:%d\r\n", ipbuf, port); + printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer)); + printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer)); + + prep_buffer(tx_buffer, sizeof(tx_buffer)); + sock.send(tx_buffer, sizeof(tx_buffer)); + printf("MBED: Finished sending\r\n"); + // Server will respond with HTTP GET's success code + const int ret = sock.recv(rx_buffer, sizeof(rx_buffer)); + printf("MBED: Finished receiving\r\n"); + + result = !memcmp(tx_buffer, rx_buffer, sizeof(tx_buffer)); + TEST_ASSERT_EQUAL(ret, sizeof(rx_buffer)); + TEST_ASSERT_EQUAL(true, result); + } + + sock.close(); + net.disconnect(); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP echo", test_tcp_echo), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/tcp_echo_parallel/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,159 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_THREADS +#define MBED_CFG_TCP_CLIENT_ECHO_THREADS 3 +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); +SocketAddress tcp_addr; +Mutex iomutex; + +void prep_buffer(char *tx_buffer, size_t tx_size) { + for (size_t i=0; i<tx_size; ++i) { + tx_buffer[i] = (rand() % 10) + '0'; + } +} + + +// Each echo class is in charge of one parallel transaction +class Echo { +private: + char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE]; + char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE]; + + TCPSocket sock; + Thread thread; + +public: + // Limiting stack size to 1k + Echo(): thread(osPriorityNormal, 1024) { + } + + void start() { + osStatus status = thread.start(callback(this, &Echo::echo)); + TEST_ASSERT_EQUAL(osOK, status); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void echo() { + int err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + + iomutex.lock(); + printf("HTTP: Connected to %s:%d\r\n", + tcp_addr.get_ip_address(), tcp_addr.get_port()); + printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer)); + printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer)); + iomutex.unlock(); + + prep_buffer(tx_buffer, sizeof(tx_buffer)); + sock.send(tx_buffer, sizeof(tx_buffer)); + + // Server will respond with HTTP GET's success code + const int ret = sock.recv(rx_buffer, sizeof(rx_buffer)); + bool result = !memcmp(tx_buffer, rx_buffer, sizeof(tx_buffer)); + TEST_ASSERT_EQUAL(ret, sizeof(rx_buffer)); + TEST_ASSERT_EQUAL(true, result); + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } +}; + +Echo *echoers[MBED_CFG_TCP_CLIENT_ECHO_THREADS]; + + +void test_tcp_echo_parallel() { + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + tcp_addr.set_ip_address(ipbuf); + tcp_addr.set_port(port); + + // Startup echo threads in parallel + for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { + echoers[i] = new Echo; + echoers[i]->start(); + } + + for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { + echoers[i]->join(); + delete echoers[i]; + } + + net.disconnect(); +} + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP echo parallel", test_tcp_echo_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/tcp_hello_world/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,115 @@ +#include <algorithm> +#include "mbed.h" +#include "ESP8266Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +namespace { + // Test connection information + const char *HTTP_SERVER_NAME = "os.mbed.com"; + const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt"; + const int HTTP_SERVER_PORT = 80; +#if defined(TARGET_VK_RZ_A1H) + const int RECV_BUFFER_SIZE = 300; +#else + const int RECV_BUFFER_SIZE = 512; +#endif + // Test related data + const char *HTTP_OK_STR = "200 OK"; + const char *HTTP_HELLO_STR = "Hello world!"; + + // Test buffers + char buffer[RECV_BUFFER_SIZE] = {0}; +} + +bool find_substring(const char *first, const char *last, const char *s_first, const char *s_last) { + const char *f = std::search(first, last, s_first, s_last); + return (f != last); +} + +void test_tcp_hello_world() { + bool result = false; + ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); + net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + printf("TCP client IP Address is %s\r\n", net.get_ip_address()); + + TCPSocket sock(&net); + printf("HTTP: Connection to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT); + if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) { + printf("HTTP: OK\r\n"); + + // We are constructing GET command like this: + // GET http://os.mbed.com/media/uploads/mbed_official/hello.txt HTTP/1.0\n\n + strcpy(buffer, "GET http://"); + strcat(buffer, HTTP_SERVER_NAME); + strcat(buffer, HTTP_SERVER_FILE_PATH); + strcat(buffer, " HTTP/1.0\n\n"); + // Send GET command + sock.send(buffer, strlen(buffer)); + + // Server will respond with HTTP GET's success code + const int ret = sock.recv(buffer, sizeof(buffer) - 1); + buffer[ret] = '\0'; + + // Find 200 OK HTTP status in reply + bool found_200_ok = find_substring(buffer, buffer + ret, HTTP_OK_STR, HTTP_OK_STR + strlen(HTTP_OK_STR)); + // Find "Hello World!" string in reply + bool found_hello = find_substring(buffer, buffer + ret, HTTP_HELLO_STR, HTTP_HELLO_STR + strlen(HTTP_HELLO_STR)); + + TEST_ASSERT_TRUE(found_200_ok); + TEST_ASSERT_TRUE(found_hello); + + if (found_200_ok && found_hello) result = true; + + printf("HTTP: Received %d chars from server\r\n", ret); + printf("HTTP: Received 200 OK status ... %s\r\n", found_200_ok ? "[OK]" : "[FAIL]"); + printf("HTTP: Received '%s' status ... %s\r\n", HTTP_HELLO_STR, found_hello ? "[OK]" : "[FAIL]"); + printf("HTTP: Received message:\r\n"); + printf("%s", buffer); + sock.close(); + } else { + printf("HTTP: ERROR\r\n"); + } + + net.disconnect(); + printf("Network disconnected\r\n"); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP hello world", test_tcp_hello_world), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/tcp_packet_pressure/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,253 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Pressure tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Shared buffer for network transactions +uint8_t *buffer; +size_t buffer_size; + +// Tries to get the biggest buffer possible on the device. Exponentially +// grows a buffer until heap runs out of space, and uses half to leave +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +void test_tcp_packet_pressure() { + generate_buffer(&buffer, &buffer_size, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); + printf("MBED: Generated buffer %d\r\n", buffer_size); + + ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + + TCPSocket sock; + SocketAddress tcp_addr(ipbuf, port); + + Timer timer; + timer.start(); + + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + printf("TCP: %s:%d streaming %d bytes\r\n", ipbuf, port, size); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out data + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.send(buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: tx -> %d\r\n", td); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, + // cut buffer in half + if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: Not sent (%d), window = %d\r\n", td, window); + } + } + } + + // Verify recieved data + while (rx_count < size) { + int rd = sock.recv(buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + if (rd > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: rx <- %d\r\n", rd); + } + int diff = rx_seq.cmp(buffer, rd); + TEST_ASSERT_EQUAL(0, diff); + rx_seq.skip(rd); + rx_count += rd; + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net.disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP packet pressure", test_tcp_packet_pressure), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/tcp_packet_pressure_parallel/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,315 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS 3 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + + +// Tries to get the biggest buffer possible on the device. Exponentially +// grows a buffer until heap runs out of space, and uses half to leave +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +// Global variables shared between pressure tests +ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); +SocketAddress tcp_addr; +Timer timer; +Mutex iomutex; + +// Single instance of a pressure test +class PressureTest { +private: + uint8_t *buffer; + size_t buffer_size; + + TCPSocket sock; + Thread thread; + +public: + PressureTest(uint8_t *buffer, size_t buffer_size) + : buffer(buffer), buffer_size(buffer_size) { + } + + void start() { + osStatus status = thread.start(callback(this, &PressureTest::run)); + TEST_ASSERT_EQUAL(osOK, status); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void run() { + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + int err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + iomutex.lock(); + printf("TCP: %s:%d streaming %d bytes\r\n", + tcp_addr.get_ip_address(), tcp_addr.get_port(), size); + iomutex.unlock(); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out data + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.send(buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: tx -> %d\r\n", td); + iomutex.unlock(); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, + // cut buffer in half + if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: Not sent (%d), window = %d\r\n", td, window); + iomutex.unlock(); + } + } + } + + // Verify recieved data + while (rx_count < size) { + int rd = sock.recv(buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + if (rd > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: rx <- %d\r\n", rd); + iomutex.unlock(); + } + int diff = rx_seq.cmp(buffer, rd); + TEST_ASSERT_EQUAL(0, diff); + rx_seq.skip(rd); + rx_count += rd; + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + } +}; + +PressureTest *pressure_tests[MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS]; + + +void test_tcp_packet_pressure_parallel() { + uint8_t *buffer; + size_t buffer_size; + generate_buffer(&buffer, &buffer_size, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); + + size_t buffer_subsize = buffer_size / MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; + printf("MBED: Generated buffer %d\r\n", buffer_size); + printf("MBED: Split into %d buffers %d\r\n", + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS, + buffer_subsize); + + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + tcp_addr.set_ip_address(ipbuf); + tcp_addr.set_port(port); + + timer.start(); + + // Startup pressure tests in parallel + for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); + pressure_tests[i]->start(); + } + + for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i]->join(); + delete pressure_tests[i]; + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS* + 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net.disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP packet pressure parallel", test_tcp_packet_pressure_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/udp_dtls_handshake/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,159 @@ +#include "mbed.h" +#include "ESP8266Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE +#define MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE 512 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES +#define MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES 16 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN +#define MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN 112, 384, 200, 219, 25 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT +#define MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT 1500 +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + +uint8_t buffer[MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE] = {0}; +int udp_dtls_handshake_pattern[] = {MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN}; +const int udp_dtls_handshake_count = sizeof(udp_dtls_handshake_pattern) / sizeof(int); + +void test_udp_dtls_handshake() { + ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: UDPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + bool result = false; + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); + + // align each size to 4-bits + for (int i = 0; i < udp_dtls_handshake_count; i++) { + udp_dtls_handshake_pattern[i] = (~0xf & udp_dtls_handshake_pattern[i]) + 0x10; + } + + printf("MBED: DTLS pattern ["); + for (int i = 0; i < udp_dtls_handshake_count; i++) { + printf("%d", udp_dtls_handshake_pattern[i]); + if (i != udp_dtls_handshake_count-1) { + printf(", "); + } + } + printf("]\r\n"); + + UDPSocket sock; + SocketAddress udp_addr(ipbuf, port); + sock.set_timeout(MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT); + + for (int attempt = 0; attempt < MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES; attempt++) { + err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + + for (int i = 0; i < udp_dtls_handshake_count; i++) { + buffer[i] = udp_dtls_handshake_pattern[i] >> 4; + } + + err = sock.sendto(udp_addr, buffer, udp_dtls_handshake_count); + printf("UDP: tx -> %d\r\n", err); + TEST_ASSERT_EQUAL(udp_dtls_handshake_count, err); + + int step = 0; + while (step < udp_dtls_handshake_count) { + err = sock.recvfrom(NULL, buffer, sizeof(buffer)); + printf("UDP: rx <- %d ", err); + + // check length + if (err != udp_dtls_handshake_pattern[step]) { + printf("x (expected %d)\r\n", udp_dtls_handshake_pattern[step]); + break; + } + + // check quick xor of packet + uint8_t check = 0; + for (int j = 0; j < udp_dtls_handshake_pattern[step]; j++) { + check ^= buffer[j]; + } + + if (check != 0) { + printf("x (checksum 0x%02x)\r\n", check); + break; + } + + // successfully got a packet + printf("\r\n"); + step += 1; + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + + // got through all steps, test passed + if (step == udp_dtls_handshake_count) { + result = true; + break; + } + } + + net.disconnect(); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_shotgun"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP DTLS handshake", test_udp_dtls_handshake), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/udp_echo/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,151 @@ +#include "mbed.h" +#include "ESP8266Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT +#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +namespace { + char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + const char ASCII_MAX = '~' - ' '; + const int ECHO_LOOPS = 16; + char uuid[48] = {0}; +} + +void prep_buffer(char *uuid, char *tx_buffer, size_t tx_size) { + size_t i = 0; + + memcpy(tx_buffer, uuid, strlen(uuid)); + i += strlen(uuid); + + tx_buffer[i++] = ' '; + + for (; i<tx_size; ++i) { + tx_buffer[i] = (rand() % 10) + '0'; + } +} + +void test_udp_echo() { + ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); + + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + if (err) { + printf("MBED: failed to connect with an error of %d\r\n", err); + TEST_ASSERT_EQUAL(0, err); + } + + printf("UDP client IP Address is %s\n", net.get_ip_address()); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + UDPSocket sock; + sock.open(&net); + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); + SocketAddress udp_addr(ipbuf, port); + + int success = 0; + for (int i = 0; success < ECHO_LOOPS; i++) { + prep_buffer(uuid, tx_buffer, sizeof(tx_buffer)); + const int ret = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer)); + if (ret >= 0) { + printf("[%02d] sent %d bytes - %.*s \n", i, ret, ret, tx_buffer); + } else { + printf("[%02d] Network error %d\n", i, ret); + continue; + } + + SocketAddress temp_addr; + const int n = sock.recvfrom(&temp_addr, rx_buffer, sizeof(rx_buffer)); + if (n >= 0) { + printf("[%02d] recv %d bytes - %.*s \n", i, n, n, tx_buffer); + } else { + printf("[%02d] Network error %d\n", i, n); + continue; + } + + if ((temp_addr == udp_addr && + n == sizeof(tx_buffer) && + memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { + success += 1; + + printf("[%02d] success #%d\n", i, success); + continue; + } + + // failed, clean out any remaining bad packets + sock.set_timeout(0); + while (true) { + err = sock.recvfrom(NULL, NULL, 0); + if (err == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + } + + sock.close(); + net.disconnect(); + TEST_ASSERT_EQUAL(ECHO_LOOPS, success); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP echo", test_udp_echo), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/udp_echo_parallel/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,231 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT +#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_THREADS +#define MBED_CFG_UDP_CLIENT_ECHO_THREADS 3 +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +const int ECHO_LOOPS = 16; +ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); +SocketAddress udp_addr; +Mutex iomutex; +char uuid[48] = {0}; + +// NOTE: assuming that "id" stays in the single digits +void prep_buffer(int id, char *uuid, char *tx_buffer, size_t tx_size) { + size_t i = 0; + + tx_buffer[i++] = '0' + id; + tx_buffer[i++] = ' '; + + memcpy(tx_buffer+i, uuid, strlen(uuid)); + i += strlen(uuid); + + tx_buffer[i++] = ' '; + + for (; i<tx_size; ++i) { + tx_buffer[i] = (rand() % 10) + '0'; + } +} + + +// Each echo class is in charge of one parallel transaction +class Echo { +private: + char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE]; + char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE]; + + UDPSocket sock; + Thread thread; + bool result; + int id; + char *uuid; + +public: + // Limiting stack size to 1k + Echo(): thread(osPriorityNormal, 1024), result(false) { + } + + void start(int id, char *uuid) { + this->id = id; + this->uuid = uuid; + osStatus status = thread.start(callback(this, &Echo::echo)); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void echo() { + int success = 0; + + int err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + + for (int i = 0; success < ECHO_LOOPS; i++) { + prep_buffer(id, uuid, tx_buffer, sizeof(tx_buffer)); + const int ret = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer)); + if (ret >= 0) { + iomutex.lock(); + printf("[ID:%01d][%02d] sent %d bytes - %.*s \n", id, i, ret, ret, tx_buffer); + iomutex.unlock(); + } else { + iomutex.lock(); + printf("[ID:%01d][%02d] Network error %d\n", id, i, ret); + iomutex.unlock(); + continue; + } + + SocketAddress temp_addr; + const int n = sock.recvfrom(&temp_addr, rx_buffer, sizeof(rx_buffer)); + if (n >= 0) { + iomutex.lock(); + printf("[ID:%01d][%02d] recv %d bytes - %.*s \n", id, i, n, n, tx_buffer); + iomutex.unlock(); + } else { + iomutex.lock(); + printf("[ID:%01d][%02d] Network error %d\n", id, i, n); + iomutex.unlock(); + continue; + } + + if ((temp_addr == udp_addr && + n == sizeof(tx_buffer) && + memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { + success += 1; + iomutex.lock(); + printf("[ID:%01d][%02d] success #%d\n", id, i, success); + iomutex.unlock(); + continue; + } + + // failed, clean out any remaining bad packets + sock.set_timeout(0); + while (true) { + err = sock.recvfrom(NULL, NULL, 0); + if (err == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + } + + result = success == ECHO_LOOPS; + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + if (err) { + result = false; + } + } + + bool get_result() { + return result; + } +}; + +Echo *echoers[MBED_CFG_UDP_CLIENT_ECHO_THREADS]; + + +void test_udp_echo_parallel() { + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + if (err) { + printf("MBED: failed to connect with an error of %d\r\n", err); + GREENTEA_TESTSUITE_RESULT(false); + } else { + printf("UDP client IP Address is %s\n", net.get_ip_address()); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); + udp_addr.set_ip_address(ipbuf); + udp_addr.set_port(port); + + // Startup echo threads in parallel + for (int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { + echoers[i] = new Echo; + echoers[i]->start(i, uuid); + } + + bool result = true; + + for (int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { + echoers[i]->join(); + result = result && echoers[i]->get_result(); + delete echoers[i]; + } + + net.disconnect(); + TEST_ASSERT_EQUAL(true, result); + } +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP echo parallel", test_udp_echo_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/udp_packet_pressure/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,276 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Pressure tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Shared buffer for network transactions +uint8_t *buffer; +size_t buffer_size; + +// Tries to get the biggest buffer possible on the device. Exponentially +// grows a buffer until heap runs out of space, and uses half to leave +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + +void test_udp_packet_pressure() { + generate_buffer(&buffer, &buffer_size, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); + printf("MBED: Generated buffer %d\r\n", buffer_size); + + ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: UDPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + + UDPSocket sock; + SocketAddress udp_addr(ipbuf, port); + + Timer timer; + timer.start(); + + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + printf("UDP: %s:%d streaming %d bytes\r\n", ipbuf, port, size); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + int known_time = timer.read_ms(); + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out packets + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.sendto(udp_addr, buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: tx -> %d\r\n", td); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, revert to + // last good sequence and cut buffer in half + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: Not sent (%d), window = %d\r\n", td, window); + } + } + } + + // Prioritize recieving over sending packets to avoid flooding + // the network while handling erronous packets + while (rx_count < size) { + int rd = sock.recvfrom(NULL, buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + + if (rd > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: rx <- %d\r\n", rd); + } + + if (rx_seq.cmp(buffer, rd) == 0) { + rx_seq.skip(rd); + rx_count += rd; + known_time = timer.read_ms(); + if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { + window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + } + } + } else if (timer.read_ms() - known_time > + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { + // Dropped packet or out of order, revert to last good sequence + // and cut buffer in half + tx_seq = rx_seq; + tx_count = rx_count; + known_time = timer.read_ms(); + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: Dropped, window = %d\r\n", window); + } + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net.disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP packet pressure", test_udp_packet_pressure), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/TESTS/net/udp_packet_pressure_parallel/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,341 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS 3 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Tries to get the biggest buffer possible on the device. Exponentially +// grows a buffer until heap runs out of space, and uses half to leave +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 8; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +// Global variables shared between pressure tests +ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); +SocketAddress udp_addr; +Timer timer; +Mutex iomutex; + +// Single instance of a pressure test +class PressureTest { +private: + uint8_t *buffer; + size_t buffer_size; + + UDPSocket sock; + Thread thread; + +public: + PressureTest(uint8_t *buffer, size_t buffer_size) + : buffer(buffer), buffer_size(buffer_size) { + } + + void start() { + osStatus status = thread.start(callback(this, &PressureTest::run)); + TEST_ASSERT_EQUAL(osOK, status); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void run() { + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + int err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + iomutex.lock(); + printf("UDP: %s:%d streaming %d bytes\r\n", + udp_addr.get_ip_address(), udp_addr.get_port(), size); + iomutex.unlock(); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + int known_time = timer.read_ms(); + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out packets + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.sendto(udp_addr, buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: tx -> %d\r\n", td); + iomutex.unlock(); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, revert to + // last good sequence and cut buffer in half + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: Not sent (%d), window = %d\r\n", td, window); + iomutex.unlock(); + } + } + } + + // Prioritize recieving over sending packets to avoid flooding + // the network while handling erronous packets + while (rx_count < size) { + int rd = sock.recvfrom(NULL, buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + + if (rd > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: rx <- %d\r\n", rd); + iomutex.unlock(); + } + + if (rx_seq.cmp(buffer, rd) == 0) { + rx_seq.skip(rd); + rx_count += rd; + known_time = timer.read_ms(); + if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { + window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + } + } + } else if (timer.read_ms() - known_time > + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { + // Dropped packet or out of order, revert to last good sequence + // and cut buffer in half + tx_seq = rx_seq; + tx_count = rx_count; + known_time = timer.read_ms(); + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: Dropped, window = %d\r\n", window); + iomutex.unlock(); + } + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + } +}; + +PressureTest *pressure_tests[MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS]; + + +void test_udp_packet_pressure_parallel() { + uint8_t *buffer; + size_t buffer_size; + generate_buffer(&buffer, &buffer_size, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); + + size_t buffer_subsize = buffer_size / MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; + printf("MBED: Generated buffer %d\r\n", buffer_size); + printf("MBED: Split into %d buffers %d\r\n", + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS, + buffer_subsize); + + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: UDPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + udp_addr.set_ip_address(ipbuf); + udp_addr.set_port(port); + + timer.start(); + + // Startup pressure tests in parallel + for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); + pressure_tests[i]->start(); + } + + for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i]->join(); + delete pressure_tests[i]; + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS* + 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net.disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP packet pressure parallel", test_udp_packet_pressure_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/esp8266-driver/mbed_lib.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,31 @@ +{ + "name": "esp8266", + "config": { + "tx": { + "help": "TX pin for serial connection", + "value": null + }, + "rx": { + "help": "RX pin for serial connection", + "value": null + }, + "debug": { + "help": "Enable debug logs", + "value": false + } + }, + "target_overrides": { + "HEXIWEAR": { + "tx": "PTD3", + "rx": "PTD2" + }, + "NUCLEO_F401RE": { + "tx": "D8", + "rx": "D2" + }, + "NUCLEO_F411RE": { + "tx": "D8", + "rx": "D2" + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mbed_lib.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,62 @@ +{ + "name": "easy-connect", + "config": { + "wifi-esp8266-tx": { + "help": "TX pin for serial connection to external device (ESP8266)", + "value": "D1" + }, + "wifi-esp8266-rx": { + "help": "RX pin for serial connection to external device (ESP8266)", + "value": "D0" + }, + "wifi-esp8266-debug": { + "help": "Enable debug logs for (ESP8266)", + "value": false + }, + "wifi-idw01m1-tx": { + "help": "TX pin for serial connection to external device (X-NUCLEO-IDW01M1)", + "value": "PA_9" + }, + "wifi-idw01m1-rx": { + "help": "RX pin for serial connection to external device (X-NUCLEO-IDW01M1)", + "value": "PA_10" + }, + "wifi-idw04a1-tx": { + "help": "TX pin for serial connection to external device (X-NUCLEO-IDW04A1)", + "value": "D8" + }, + "wifi-idw04a1-rx": { + "help": "RX pin for serial connection to external device (X-NUCLEO-IDW04A1)", + "value": "D2" + }, + "wifi-wizfi310-tx": { + "help": "TX pin for serial connection to external device (WizFi310)", + "value": "D1" + }, + "wifi-wizfi310-rx": { + "help": "RX pin for serial connection to external device (WizFi310)", + "value": "D0" + }, + "wifi-wizfi310-debug": { + "help": "Enable debug logs for (WizFi310)", + "value": false + } + }, + "target_overrides": { + "*": { + "target.features_add": ["COMMON_PAL"] + }, + "HEXIWEAR": { + "wifi-esp8266-tx": "PTD3", + "wifi-esp8266-rx": "PTD2" + }, + "NUCLEO_F401RE": { + "wifi-esp8266-tx": "D8", + "wifi-esp8266-rx": "D2" + }, + "NUCLEO_F411RE": { + "wifi-esp8266-tx": "D8", + "wifi-esp8266-rx": "D2" + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mcr20a-rf-driver/#e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/FETCH_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,5 @@ +e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a branch 'master' of https://github.com/ARMmbed/mcr20a-rf-driver +46ac6ba138ba5a3022421cb425d7020cd5950227 not-for-merge branch 'burst_access' of https://github.com/ARMmbed/mcr20a-rf-driver +4a48386354e0819b7687902f41592f1853992c26 not-for-merge branch 'device_kw24d' of https://github.com/ARMmbed/mcr20a-rf-driver +a28948345dfbd89719c60b765a9837ffbd434a2e not-for-merge branch 'fixing_mbed_path' of https://github.com/ARMmbed/mcr20a-rf-driver +2ebe27dbf63c909b953c15d5435aeaf09de59c0f not-for-merge branch 'remove_yotta' of https://github.com/ARMmbed/mcr20a-rf-driver
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/ORIG_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/config Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/mcr20a-rf-driver/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/info/exclude Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504019 +0000 clone: from https://github.com/ARMmbed/mcr20a-rf-driver/ +e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a 17c467b64ab604887fc160cbe4118a51477e334b www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504019 +0000 checkout: moving from master to 17c467b64ab604887fc160cbe4118a51477e334b +17c467b64ab604887fc160cbe4118a51477e334b e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504041 +0000 checkout: moving from 17c467b64ab604887fc160cbe4118a51477e334b to master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504019 +0000 clone: from https://github.com/ARMmbed/mcr20a-rf-driver/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504019 +0000 clone: from https://github.com/ARMmbed/mcr20a-rf-driver/
Binary file easy-connect/mcr20a-rf-driver/.git/objects/pack/pack-af6ac51d5e5c7416743f617b172f035c46142e23.idx has changed
Binary file easy-connect/mcr20a-rf-driver/.git/objects/pack/pack-af6ac51d5e5c7416743f617b172f035c46142e23.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,10 @@ +# pack-refs with: peeled +46ac6ba138ba5a3022421cb425d7020cd5950227 refs/remotes/origin/burst_access +4a48386354e0819b7687902f41592f1853992c26 refs/remotes/origin/device_kw24d +a28948345dfbd89719c60b765a9837ffbd434a2e refs/remotes/origin/fixing_mbed_path +e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a refs/remotes/origin/master +2ebe27dbf63c909b953c15d5435aeaf09de59c0f refs/remotes/origin/remove_yotta +a9131696eb205ab6cd503ea33d265513186b3b18 refs/tags/v1.0.0 +^41b0fc57241a77bd23db9619000e37df41584c95 +79219d3a39e1de04b02c25e699a54fca7f7bc466 refs/tags/v1.0.1 +^2c2d99754e7d47efe148399e6569296f00f39a06
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +e5c54f90b8a03ce6f0a582d3ed8d4e0e8017238a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.gitignore Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,6 @@ +*~ +*.swo +*.swp +build +yotta_modules +yotta_targets
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<root> + <node _type="integer" _key="update">0</node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/LICENSE Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/README.md Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/apache-2.0.txt Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/mbed_lib.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,9 @@ +{ + "name": "mcr20a", + "config": { + "provide-default": { + "help": "Provide default NanostackRfpy. [true/false]", + "value": false + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,70 @@ +/* + * 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" + +#ifdef MBED_CONF_NANOSTACK_CONFIGURATION + +#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); + virtual ~NanostackRfPhyMcr20a(); + virtual int8_t rf_register(); + virtual void rf_unregister(); + virtual void get_mac_address(uint8_t *mac); + virtual void set_mac_address(uint8_t *mac); + +private: + SPI _spi; + DigitalOut _rf_cs; + DigitalOut _rf_rst; + InterruptIn _rf_irq; + DigitalIn _rf_irq_pin; + Thread _irq_thread; + + void _pins_set(); + void _pins_clear(); +}; + +#endif /* MBED_CONF_NANOSTACK_CONFIGURATION */ +#endif /* NANOSTACK_PHY_MCR20A_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/module.json Wed Sep 05 14:28:24 2018 +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": {} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/source/MCR20Drv.c Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,683 @@ +/*! +* 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 "MCR20Drv.h" +#include "MCR20Reg.h" +#include "XcvrSpi.h" + +#ifdef MBED_CONF_NANOSTACK_CONFIGURATION + +#include "platform/arm_hal_interrupt.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(); + #if !defined(TARGET_KW24D) + MCR20Drv_RST_B_Deassert(); + #endif + 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 +) +{ + #if !defined(TARGET_KW24D) + volatile uint32_t delay = 1000; + //assert RST_B + MCR20Drv_RST_B_Assert(); + + while(delay--); + + //deassert RST_B + MCR20Drv_RST_B_Deassert(); + #endif +} + +/*--------------------------------------------------------------------------- +* 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); +} + +#endif /* MBED_CONF_NANOSTACK_CONFIGURATION */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/source/MCR20Drv.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,373 @@ +/*! +* 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__ + +#include <stdint.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__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/source/MCR20Overwrites.h Wed Sep 05 14:28:24 2018 +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_ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/source/MCR20Reg.h Wed Sep 05 14:28:24 2018 +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__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1826 @@ +/* + * 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" + +#ifdef MBED_CONF_NANOSTACK_CONFIGURATION + +#include "ns_types.h" +#include "platform/arm_hal_interrupt.h" +#include "nanostack/platform/arm_hal_phy.h" +#include <string.h> +#include "rtos.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 +#if !defined(TARGET_KW24D) + #define gXcvrLowPowerState_d gXcvrPwrHibernate_c +#else + #define gXcvrLowPowerState_d gXcvrPwrAutodoze_c +#endif + +/* 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]; + +/* 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; +static Thread *irq_thread = 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}; + +/* 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); +static void PHY_InterruptThread(void); +static void handle_interrupt(void); + + +/* + * \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) +{ + 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 */ + #if !defined(TARGET_KW24D) + MCR20Drv_Set_CLK_OUT_Freq(gMCR20_ClkOutFreq_d); + #endif + /* 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(); + /*Write initial eui64*/ + rf_set_address(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 Auto Ack frame pending status*/ + case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS: { + uint8_t reg = MCR20Drv_DirectAccessSPIRead(SRC_CTRL); + if (reg & cSRC_CTRL_ACK_FRM_PND) { + *data_ptr = 1; + } else { + *data_ptr = 0; + } + 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; + case PHY_EXTENSION_ACCEPT_ANY_BEACON: + 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) +{ +} + +/* + * \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) +{ + /* Disable and clear transceiver(IRQ_B) interrupt */ + MCR20Drv_IRQ_Disable(); + irq_thread->signal_set(1); +} + +static void PHY_InterruptThread(void) +{ + for (;;) { + osEvent event = irq_thread->signal_wait(0); + if (event.status != osEventSignal) { + continue; + } + handle_interrupt(); + } +} + +static void handle_interrupt(void) +{ + uint8_t xcvseqCopy; + + //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, 1), + _rf_irq(spi_irq), _rf_irq_pin(spi_irq), + _irq_thread(osPriorityRealtime, 1024) +{ + char mac48[6]; + mbed_mac_address(mac48); + + MAC_address[0] = mac48[0]; + MAC_address[1] = mac48[1]; + MAC_address[2] = mac48[2]; + MAC_address[3] = 0xFF; + MAC_address[4] = 0xFF; + MAC_address[5] = mac48[3]; + MAC_address[6] = mac48[4]; + MAC_address[7] = mac48[5]; +} + +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; + } + + _irq_thread.start(mbed::callback(PHY_InterruptThread)); + + _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; + irq_thread = &_irq_thread; +} + +void NanostackRfPhyMcr20a::_pins_clear() +{ + spi = NULL; + cs = NULL; + rst = NULL; + irq = NULL; + irq_pin = NULL; + irq_thread = NULL; +} + +#if MBED_CONF_MCR20A_PROVIDE_DEFAULT || DEVICE_MCR20A + +NanostackRfPhy &NanostackRfPhy::get_default_instance() +{ + static NanostackRfPhyMcr20a rf_phy(MCR20A_SPI_MOSI, MCR20A_SPI_MISO, MCR20A_SPI_SCLK, MCR20A_SPI_CS, MCR20A_SPI_RST, MCR20A_SPI_IRQ); + return rf_phy; +} + +#endif // MBED_CONF_MCR20A_PROVIDE_DEFAULT + +#endif // MBED_CONF_NANOSTACK_CONFIGURATION
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/mcr20a-rf-driver/source/XcvrSpi.h Wed Sep 05 14:28:24 2018 +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__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/stm-spirit1-rf-driver/#b8e3da9b2999d1aec1e500d0acf6e725060d3515
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/FETCH_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +b8e3da9b2999d1aec1e500d0acf6e725060d3515 branch 'master' of https://github.com/ARMmbed/stm-spirit1-rf-driver
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/ORIG_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +b8e3da9b2999d1aec1e500d0acf6e725060d3515
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/config Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/stm-spirit1-rf-driver/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/info/exclude Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 b8e3da9b2999d1aec1e500d0acf6e725060d3515 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504021 +0000 clone: from https://github.com/ARMmbed/stm-spirit1-rf-driver/ +b8e3da9b2999d1aec1e500d0acf6e725060d3515 b8e3da9b2999d1aec1e500d0acf6e725060d3515 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504022 +0000 checkout: moving from master to b8e3da9b2999d1aec1e500d0acf6e725060d3515 +b8e3da9b2999d1aec1e500d0acf6e725060d3515 b8e3da9b2999d1aec1e500d0acf6e725060d3515 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504023 +0000 checkout: moving from b8e3da9b2999d1aec1e500d0acf6e725060d3515 to master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 b8e3da9b2999d1aec1e500d0acf6e725060d3515 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504021 +0000 clone: from https://github.com/ARMmbed/stm-spirit1-rf-driver/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 b8e3da9b2999d1aec1e500d0acf6e725060d3515 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504021 +0000 clone: from https://github.com/ARMmbed/stm-spirit1-rf-driver/
Binary file easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-0689660497529bb7343db960a700c59133742283.idx has changed
Binary file easy-connect/stm-spirit1-rf-driver/.git/objects/pack/pack-0689660497529bb7343db960a700c59133742283.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,4 @@ +# pack-refs with: peeled +b8e3da9b2999d1aec1e500d0acf6e725060d3515 refs/remotes/origin/master +0ff4ca7537f0f2e9137c61ac21251ac06ca42bc3 refs/tags/v1.0.0 +ce9e2f81f95f895652789eeb196443eff5ac6ed7 refs/tags/v1.0.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +b8e3da9b2999d1aec1e500d0acf6e725060d3515
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.gitignore Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,6 @@ +BUILD +.mbed +projectfiles +*.py* +RCS +atmel-rf-driver
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.hgtags Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +a9a9807bf3edb924e06cf8117d077824f794df86 v1.0.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<root> + <node _type="integer" _key="update">0</node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/README.md Wed Sep 05 14:28:24 2018 +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 can be used together with the 6LoWPAN stack (*a.k.a.* Nanostack).
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/mbed_lib.json Wed Sep 05 14:28:24 2018 +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"] +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/source/NanostackRfPhySpirit1.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,830 @@ +#include "NanostackRfPhySpirit1.h" + +#ifdef MBED_CONF_NANOSTACK_CONFIGURATION +#if MBED_CONF_RTOS_PRESENT + +#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 (includes tracing 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 SingletonPtr<Thread> rf_ack_sender; +static volatile uint8_t rf_rx_sequence; +static volatile bool rf_ack_sent = false; +static volatile bool expecting_ack = false; +static volatile bool need_ack = 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 inline void rf_if_lock(void) +{ + platform_enter_critical(); +} + +static inline 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; +} + +/* 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 volatile 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 + + /*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 inline bool rf_check_mac_address(uint8_t *dest) { + for(int i = 0; i < 8; i++) { + if(dest[i] != stored_mac_address[7-i]) { +#ifdef HEAVY_TRACING + tr_debug("%s (%d): i=%d, dest=%x, stored=%x", + __func__, __LINE__, + i, dest[i], stored_mac_address[7-i]); +#endif + 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 != stored_pan_id) && (dst_pan_id != 0xFFFF)) { +#ifdef HEAVY_TRACING + tr_debug("%s (%d)", __func__, __LINE__); +#endif + return false; + } + + 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) && (dst_short_adr != 0xFFFF)) { +#ifdef HEAVY_TRACING + tr_debug("%s (%d): %d!=%d", __func__, __LINE__, dst_short_adr, stored_short_adr); +#endif + return false; + } + + ret = true; + 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 != stored_pan_id) && (dst_pan_id != 0xFFFF)) { +#ifdef HEAVY_TRACING + tr_debug("%s (%d)", __func__, __LINE__); +#endif + return false; + } + + if(len < 13) { +#ifdef HEAVY_TRACING + tr_debug("%s (%d)", __func__, __LINE__); +#endif + return false; + } + + ret = rf_check_mac_address(&rf_rx_buf[5]); + + if(!ret) { +#ifdef HEAVY_TRACING + tr_debug("%s (%d)", __func__, __LINE__); +#endif + return false; + } + + 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 */ + if(expecting_ack) { + uint16_t fcf = rf_read_16_bit(rf_rx_buf); + expecting_ack = false; + + 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; + } else { + /*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); + } + } + } + + /* 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 + } + + /* Transform `need_ack` in `expecting_ack` */ + if(need_ack) { + need_ack = false; + expecting_ack = true; + } + + /*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 might be in IRQ context */ +static inline void rf_handle_tx_err(phy_link_tx_status_e phy_val = PHY_LINK_TX_FAIL) { + /*Call PHY TX Done API*/ + if(device_driver.phy_tx_done_cb){ + need_ack = false; + phy_status = phy_val; + 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 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), "\r\nassert failed in: %s (%d)\r\n", __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 */ +#ifdef HEAVY_TRACING + tr_debug("%s (%d)", __func__, __LINE__); +#endif + + /* Release Lock */ + rf_if_unlock(); + + /*Return busy*/ + return -1; + } else { + uint16_t fcf = rf_read_16_bit(data_ptr); + + /*Check if transmitted data needs to be acked*/ + if((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT) + need_ack = true; + else + need_ack = false; + + /*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*/ + int ret = rf_device->send(data_ptr, data_length); + if(ret != RADIO_TX_OK) { + rf_handle_tx_err(PHY_LINK_CCA_FAIL); + } + + /* 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; +} + +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, false); + +#ifdef HEAVY_TRACING + tr_debug("%s (%d), hdr=%x, nr=%x", __func__, __LINE__, buffer[0], ptr[0]); +#endif + } + + if(signals & RF_SIG_CB_TX_DONE) { + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, phy_status, + (phy_status == PHY_LINK_CCA_FAIL) ? 0xFF : 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) { + osStatus ret; + + 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); + + ret = rf_ack_sender->start(rf_ack_loop); + if (ret == osOK) { + rf_ack_sender->set_priority(osPriorityRealtime); + } + +#ifndef NDEBUG + debug_if(!(ret == osOK), "\r\nassert failed in: %s (%d)\r\n", __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(); +} + +#endif /* MBED_CONF_RTOS_PRESENT */ +#endif /* MBED_CONF_NANOSTACK_CONFIGURATION */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/source/SimpleSpirit1.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,638 @@ +/*** 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(); \ + uint32_t limit = (uint32_t)millisecs*1000U; \ + while (!(cond)) { \ + uint32_t now = us_ticker_read(); \ + if((now - start) > limit) break; \ + } \ + } 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(10000000); // 10MHz (i.e. max speed allowed for 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); + + 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 + 5, // 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 +static const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler +int SimpleSpirit1::send(const void *payload, unsigned int payload_len, bool use_csma_ca) { + /* 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("\r\nAssert failed in: %s (%d): state=%x\r\n", __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), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + + pkt_basic_set_payload_length(payload_len); // set desired payload len + + if(use_csma_ca) { + 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("\r\n%s (%d): state=%x, _spirit_tx_started=%d\r\n", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started); +#endif + + if(use_csma_ca) { + csma_ca_state(S_DISABLE); // disable CSMA/CA + } + + cmd_strobe(SPIRIT1_STROBE_RX); // Return to RX state + + disable_spirit_irq(); + if(_spirit_tx_started) { // in case of state timeout + _spirit_tx_started = false; + enable_spirit_irq(); + return RADIO_TX_ERR; + } else { + enable_spirit_irq(); + 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("\r\nAssert failed in: %s (%d): state=%x\r\n", __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("\r\nSpirit1: failed to become ready (%x) => pls. reset!\r\n", 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("\r\nSpirit1: failed to enter standby (%x)\r\n", 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("\r\nSpirit1: failed to enter rx (%x) => retry\r\n", last_state>>1); + } + + /* Enables the mcu to get IRQ from the SPIRIT1 */ + spirit_on = ON; +#ifndef NDEBUG + debug_if(!(_nr_of_irq_disables == 1), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + enable_spirit_irq(); + } + +#ifndef NDEBUG + if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { + debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __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("\r\nBuffer is empty\r\n"); +#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("\r\nTOO SMALL BUF\r\n"); +#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; + } + +} + +/* betzw - TODO: CCA should be reviewed (completely)! */ +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("\r\nAssert failed in: %s (%d): state=%x\r\n", __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) { + debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); + } +#else // !USE_STANDBY_STATE + if(SPIRIT1_STATUS() != SPIRIT1_STATE_READY) { + debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); + } +#endif // !USE_STANDBY_STATE +#endif // NDEBUG + } else { // spirit_state != OFF + 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("\r\nSpirit1: (#2) failed to enter rx (%x) => retry\r\n", last_state>>1); + } + + enable_spirit_irq(); + +#ifndef NDEBUG + if(SPIRIT1_STATUS() != SPIRIT1_STATE_RX) { + debug("\r\nAssert failed in: %s (%d): state=%x\r\n", __func__, __LINE__, last_state>>1); + } +#endif + } + + /* If the received signal strength is above a certain level the medium is considered busy! */ + /* Compare RSSI value with threshold */ + if(rssi_value < CCA_THRESHOLD) { + return 0; // idle + } else { + return 1; // busy + } +} + +int SimpleSpirit1::get_pending_packet(void) +{ + return !IS_RXBUF_EMPTY(); +} + +/** Spirit Irq Callback **/ +/* betzw - TODO: use threaded interrupt handling when `MBED_CONF_RTOS_PRESENT` is defined (see `atmel-rf-driver`) */ +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 has been sent. Puts the SPIRIT1 in RX */ + if(x_irq_status.IRQ_TX_DATA_SENT) { /* betzw - NOTE: MUST be handled before `IRQ_RX_DATA_READY` for Nanostack integration! + Logically, Nanostack only expects the "DONE" after "SUCCESS" (if it gets + DONE before SUCCESS, it assumes you're not going to bother to send SUCCESS). + */ +#ifdef DEBUG_IRQ + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + debug_if(tx_fifo_remaining != 0, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + + if(_spirit_tx_started) { + _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; + tx_fifo_buffer = NULL; + } + +#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), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + debug_if(!_spirit_tx_started, "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); + debug_if(tx_fifo_buffer == NULL, "\r\nAssert failed in: %s (%d)\r\n", __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 + + /* TX FIFO underflow/overflow error */ + if(x_irq_status.IRQ_TX_FIFO_ERROR) { +#ifdef DEBUG_IRQ + uint32_t *tmp = (uint32_t*)&x_irq_status; + debug("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); + debug_if(!((*tmp) & IRQ_TX_FIFO_ERROR_MASK), "\r\nAssert failed in: %s (%d)\r\n", __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), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + + if(!_is_receiving) { // spurious irq?!? (betzw: see comments on macro 'RX_FIFO_THR_WA'!) +#ifdef HEAVY_DEBUG + debug("\r\n%s (%d): irq=%x\r\n", __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), "\r\n%s (%d): irq=%x\r\n", __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), "\r\nAssert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + if(!_is_receiving) { // spurious irq?!? +#ifdef DEBUG_IRQ + debug("\r\n%s (%d): irq=%x\r\n", __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("\r\n%s (%d): irq=%x\r\n", __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("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); + debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\r\nAssert failed in: %s (%d)\r\n", __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), "\r\nAssert failed in: %s (%d)\r\n", __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("\r\n%s (%d): irq=%x\r\n", __func__, __LINE__, *tmp); +#endif + } else { + _is_receiving = true; + start_rx_timeout(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/README.md Wed Sep 05 14:28:24 2018 +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 + + + + + + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/radio.h Wed Sep 05 14:28:24 2018 +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_ */ + +/** @} */ +/** @} */
--- /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 Wed Sep 05 14:28:24 2018 +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__ */ +/*---------------------------------------------------------------------------*/
--- /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 Wed Sep 05 14:28:24 2018 +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__ */ +/*---------------------------------------------------------------------------*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/source/libs/Contiki_STM32_Library/spirit1.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,184 @@ +/* + * 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 */ +/* General Remarks: + * Two SPSGRF modules will only communicate when both are having same frequency , same channel number, + * same modulation scheme, same data rate, etc. + * For example, the SPSGRF-915 module supports frequencies 902 to 928 MHz. User can select any frequency + * between this band. + */ +#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 +#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__ */ +/*---------------------------------------------------------------------------*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/source/libs/spirit1/Release_Notes.html Wed Sep 05 14:28:24 2018 +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> </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: "Times New Roman";"> +</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: "Verdana","sans-serif";">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: "Verdana","sans-serif";"><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: "Verdana","sans-serif";">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: "Verdana","sans-serif"; 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;"> 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> </o:p></p> +</div> +</body></html> \ No newline at end of file
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/ +
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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 2s 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 2s 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 2s 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 Endof 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 Endof 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/ +
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/ +
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /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 Wed Sep 05 14:28:24 2018 +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>© 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****/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/source/radio_spi.cpp Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/NanostackRfPhySpirit1.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,57 @@ +#ifndef NANOSTACK_RF_PHY_SPIRIT1_H_ +#define NANOSTACK_RF_PHY_SPIRIT1_H_ + +#include <stdint.h> + +#ifdef MBED_CONF_NANOSTACK_CONFIGURATION + +#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 /* MBED_CONF_NANOSTACK_CONFIGURATION */ +#endif /* NANOSTACK_RF_PHY_SPIRIT1_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/SimpleSpirit1.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,555 @@ +/*** 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 + + +/*** Macros for Spirit1 API ***/ +/* max payload */ +#define SPIRIT1_MAX_PAYLOAD (MAX_PACKET_LEN) + + +/*** Missing Cube External Declarations ***/ +extern "C" void SpiritManagementSetFrequencyBase(uint32_t); + + +/*** UnlockedSPI for Usage in IRQ context ***/ +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!!! +/** Simple Spirit1 Class + * + * @Note Synchronization level: implementation is IRQ-save but (intentionally) NOT thread-safe!!! + * + * Example: + * @code + * #include "mbed.h" + * #include "SimpleSpirit1.h" + * + * static char send_buf[] = "Hello World!"; + * + * static SimpleSpirit1 &myspirit = SimpleSpirit1::CreateInstance(D11, D12, D3, D9, D10, D2); + * + * static volatile bool tx_done_flag = false; + * + * static void callback_func(int event) + * { + * if (event == SimpleSpirit1::TX_DONE) { + * tx_done_flag = true; + * } + * } + * + * int main() + * { + * myspirit.attach_irq_callback(callback_func); + * myspirit.on(); + * + * while(1) + * { + * size_t curr_len = strlen((const char*)send_buf); + * myspirit.send(send_buf, curr_len); + * + * while(!tx_done_flag); + * tx_done_flag = false; + * } + * } + * @endcode + */ +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("\r\n%s (%d)\r\n", __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, "\r\nassert failed in: %s (%d)\r\n", __func__, __LINE__); +#endif + } + + void enable_spirit_irq(void) { +#ifndef NDEBUG + debug_if(_nr_of_irq_disables == 0, "\r\nassert failed in: %s (%d)\r\n", __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 + }; + + /** Create singleton instance of 'SimpleSpirit1' + * + * @param mosi 'PinName' of mosi pin to use + * @param miso 'PinName' of miso pin to use + * @param sclk 'PinName' of clock pin to use + * @param irq 'PinName' of interrupt pin to use + * @param cs 'PinName' of chip-select pin pin to use + * @param sdn 'PinName' of pin to use for device shutdown + * + * @returns reference to singleton instance + */ + 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; + } + + /** Get singleton instance of 'SimpleSpirit1' + * + * @returns reference to singleton instance + */ + 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 an event has occurred + * + * @param func A void(int) callback, or 0 to set as none + * + * @note Function 'func' will be executed in interrupt context! + * @note Function 'func' will be call with either 'RX_DONE', 'TX_DONE', or 'TX_ERR' as parameter + * to indicate which event has occurred. + */ + void attach_irq_callback(Callback<void(int)> func) { + _current_irq_callback = func; + } + + /** Switch Radio On + */ + int on(void); + + /** Switch Radio Off + */ + int off(void); + + /** Set Channel + */ + void set_channel(uint8_t channel) { + SpiritRadioSetChannel(channel); + } + + /** Send a Buffer + * + * @param payload pointer to buffer to be send + * @param payload_len length of payload buffer in bytes + * @param use_csma_ca should CSMA/CA be enabled for transmission + * + * @returns zero in case of success, non-zero error code otherwise + * + * @note the maximum payload size in bytes allowed is defined by macro 'SPIRIT1_MAX_PAYLOAD' + */ + int send(const void *payload, unsigned int payload_len, bool use_csma_ca = true); + + /** Copy received data into buffer + * + * @param buf pointer to buffer to be filled + * @param bufsize size of buffer + * + * @returns number of bytes copied into the buffer + * + * @note the buffer should be (at least) of size 'SPIRIT1_MAX_PAYLOAD' (in bytes). + */ + int read(void *buf, unsigned int bufsize); + + /** Perform a Clear-Channel Assessment (CCA) to find out whether the medium is idle or not. + * + * @returns 1 if the medium is busy. + */ + 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(); + } +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/stm-spirit1-rf-driver/stm-spirit1-rf-driver/radio_spi.h Wed Sep 05 14:28:24 2018 +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>© 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****/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/wifi-ism43362/#49d0f834dc420c98631fc33777aace9a31d8d584
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/FETCH_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +49d0f834dc420c98631fc33777aace9a31d8d584 branch 'master' of https://github.com/ARMmbed/wifi-ism43362
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/ORIG_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +49d0f834dc420c98631fc33777aace9a31d8d584
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/config Wed Sep 05 14:28:24 2018 +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/wifi-ism43362/ +[branch "master"] + remote = origin + merge = refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/wifi-ism43362/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/info/exclude Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504025 +0000 clone: from https://github.com/ARMmbed/wifi-ism43362/ +49d0f834dc420c98631fc33777aace9a31d8d584 117eb2dbd1d863f3f856c002db4ffac5032efab2 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504025 +0000 checkout: moving from master to 117eb2dbd1d863f3f856c002db4ffac5032efab2 +117eb2dbd1d863f3f856c002db4ffac5032efab2 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504045 +0000 checkout: moving from 117eb2dbd1d863f3f856c002db4ffac5032efab2 to master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504025 +0000 clone: from https://github.com/ARMmbed/wifi-ism43362/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504025 +0000 clone: from https://github.com/ARMmbed/wifi-ism43362/
Binary file easy-connect/wifi-ism43362/.git/objects/pack/pack-8bf1447bb4ae1bb2894fa2c84da739c66001d7d1.idx has changed
Binary file easy-connect/wifi-ism43362/.git/objects/pack/pack-8bf1447bb4ae1bb2894fa2c84da739c66001d7d1.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +# pack-refs with: peeled +49d0f834dc420c98631fc33777aace9a31d8d584 refs/remotes/origin/master +43817d8fe90469c57d5b21f7a8a1acb66d890392 refs/tags/v1.0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +49d0f834dc420c98631fc33777aace9a31d8d584
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<root> + <node _type="integer" _key="update">0</node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ATParser/ATParser.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,454 @@ +/* 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" + +#ifdef LF +#undef LF +#define LF 10 +#else +#define LF 10 +#endif + +#ifdef CR +#undef CR +#define CR 13 +#else +#define CR 13 +#endif +#define MIN(a,b) (((a)<(b))?(a):(b)) + +// activate / de-activate debug +#define dbg_on 0 +#define AT_DATA_PRINT 0 +#define AT_COMMAND_PRINT 0 +#define AT_HEXA_DATA 0 + +ATParser::ATParser(BufferedSpi &serial_spi, const char *delimiter, int buffer_size, int timeout) : + _serial_spi(&serial_spi), + _buffer_size(buffer_size), _in_prev(0), _oobs(NULL) +{ + _buffer = new char[buffer_size]; + setTimeout(timeout); + setDelimiter(delimiter); +} + + +// getc/putc handling with timeouts +int ATParser::putc(char c) +{ + return _serial_spi->putc(c); +} + +int ATParser::getc() +{ + return _serial_spi->getc(); +} + +void ATParser::flush() +{ + _bufferMutex.lock(); + while (_serial_spi->readable()) { + _serial_spi->getc(); + } + _bufferMutex.unlock(); +} + +// read/write handling with timeouts +int ATParser::write(const char *data, int size_of_data, int size_in_buff) +{ + int i = 0; + _bufferMutex.lock(); + debug_if(dbg_on, "ATParser write: %d BYTES\r\n", size_of_data); + debug_if(AT_DATA_PRINT, "ATParser write: (ASCII) ", size_of_data); + for (; i < size_of_data; i++) { + debug_if(AT_DATA_PRINT, "%c", data[i]); + if (putc(data[i]) < 0) { + debug_if(AT_DATA_PRINT, "\r\n"); + _bufferMutex.unlock(); + return -1; + } + } + debug_if(AT_DATA_PRINT, "\r\n"); + + _serial_spi->buffsend(size_of_data + size_in_buff); + _bufferMutex.unlock(); + + return (size_of_data + size_in_buff); +} + +int ATParser::read(char *data) +{ + int readsize; + int i = 0; + + _bufferMutex.lock(); + + //this->flush(); + if (!_serial_spi->readable()) { + readsize = _serial_spi->read(); + } else { + debug_if(dbg_on, "Pending data when reading from WIFI\r\n"); + return -1; + } + + debug_if(dbg_on, "ATParser read: %d data avail in SPI\r\n", readsize); + + if (readsize < 0) { + _bufferMutex.unlock(); + return -1; + } + + for (i = 0 ; i < readsize; i++) { + int c = getc(); + if (c < 0) { + _bufferMutex.unlock(); + return -1; + } + data[i] = c; + } + +#if AT_HEXA_DATA + debug_if(AT_DATA_PRINT, "ATParser read: (HEXA) "); + for (i = 0; i < readsize; i++) { + debug_if(AT_DATA_PRINT, "%2X ", data[i]); + if ((i + 1) % 20 == 0) { + debug_if(AT_DATA_PRINT, "\r\n"); + } + } + debug_if(AT_DATA_PRINT, "\r\n"); +#endif + debug_if(AT_DATA_PRINT, "ATParser read: (ASCII) "); + for (i = 0; i < readsize; i++) { + debug_if(AT_DATA_PRINT, "%c", data[i]); + } + debug_if(AT_DATA_PRINT, "\r\n"); + + _bufferMutex.unlock(); + + return (readsize); +} + +// printf/scanf handling +int ATParser::vprintf(const char *format, va_list args) +{ + _bufferMutex.lock(); + if (vsprintf(_buffer, format, args) < 0) { + _bufferMutex.unlock(); + return false; + } + + int i = 0; + for (; _buffer[i]; i++) { + if (putc(_buffer[i]) < 0) { + _bufferMutex.unlock(); + return -1; + } + } + _bufferMutex.unlock(); + + 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; + + _bufferMutex.lock(); + + 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) { + _bufferMutex.unlock(); + return false; + } + // Recieve next character + int c = getc(); + if (c < 0) { + _bufferMutex.unlock(); + 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); + _bufferMutex.unlock(); + return j; + } + } +} + + +// Command parsing with line handling +bool ATParser::vsend(const char *command, va_list args) +{ + int i = 0, j = 0; + _bufferMutex.lock(); + // Create and send command + if (vsprintf(_buffer, command, args) < 0) { + _bufferMutex.unlock(); + return false; + } + /* get buffer length */ + for (i = 0; _buffer[i]; i++) { + } + + for (j = 0; _delimiter[j]; j++) { + _buffer[i + j] = _delimiter[j]; + } + _buffer[i + j] = 0; // only to get a clean debug log + + bool ret = !(_serial_spi->buffwrite(_buffer, i + j) < 0); + + debug_if(AT_COMMAND_PRINT, "AT> %s\n", _buffer); + _bufferMutex.unlock(); + return ret; +} + +bool ATParser::vrecv(const char *response, va_list args) +{ + _bufferMutex.lock(); + + if (!_serial_spi->readable()) { + // debug_if(dbg_on, "NO DATA, read again\r\n"); + if (_serial_spi->read() < 0) { + return false; + } + } + // else { + // debug_if(dbg_on, "Pending data\r\n"); + // } + +restart: + _aborted = false; + // 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; + bool whole_line_wanted = false; + + while (response[i]) { + if (response[i] == '%' && response[i + 1] != '%' && response[i + 1] != '*') { + _buffer[offset++] = '%'; + _buffer[offset++] = '*'; + i++; + } else { + _buffer[offset++] = response[i++]; + // Find linebreaks, taking care not to be fooled if they're in a %[^\n] conversion specification + if (response[i - 1] == '\n' && !(i >= 3 && response[i - 3] == '[' && response[i - 2] == '^')) { + whole_line_wanted = true; + break; + } + } + } + + // 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; + + // debug_if(dbg_on, "ATParser vrecv: AT? ====%s====\n", _buffer); + // 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) { + debug_if(dbg_on, "AT(Timeout)\n"); + _bufferMutex.unlock(); + return false; + } + + // debug_if(AT_DATA_PRINT, "%2X ", c); + + _buffer[offset + j++] = c; + _buffer[offset + j] = 0; + + // Check for oob data + for (struct oob *oob = _oobs; oob; oob = oob->next) { + if ((unsigned)j == oob->len && memcmp( + oob->prefix, _buffer + offset, oob->len) == 0) { + debug_if(dbg_on, "AT! %s\n", oob->prefix); + oob->cb(); + + if (_aborted) { + debug_if(dbg_on, "AT(Aborted)\n"); + _bufferMutex.unlock(); + return false; + } + // oob may have corrupted non-reentrant buffer, + // so we need to set it up again + goto restart; + } + } + + // Check for match + int count = -1; + if (whole_line_wanted && c != '\n') { + // Don't attempt scanning until we get delimiter if they included it in format + // This allows recv("Foo: %s\n") to work, and not match with just the first character of a string + // (scanf does not itself match whitespace in its format string, so \n is not significant to it) + } else { + sscanf(_buffer + offset, _buffer, &count); + } + + // We only succeed if all characters in the response are matched + if (count == j) { + debug_if(AT_COMMAND_PRINT, "AT= ====%s====\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 ((c == '\n')) { + // debug_if(dbg_on, "New line AT<<< %s", _buffer+offset); + j = 0; + } + if ((j + 1 >= (_buffer_size - offset))) { + + debug_if(dbg_on, "Out of space AT<<< %s, j=%d", _buffer + offset, j); + j = 0; + } + } + } + + _bufferMutex.unlock(); + + 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 = new struct oob; + oob->len = strlen(prefix); + oob->prefix = prefix; + oob->cb = cb; + oob->next = _oobs; + _oobs = oob; +} + +void ATParser::abort() +{ + _aborted = true; +} + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ATParser/ATParser.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,246 @@ +/* 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 "BufferedSpi.h" +#include "Callback.h" + +#define DEFAULT_SPI_TIMEOUT 60000 /* 1 minute */ + +/** +* 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 + BufferedSpi *_serial_spi; + int _buffer_size; + char *_buffer; + Mutex _bufferMutex; + + // Parsing information + const char *_delimiter; + int _delim_size; + char _in_prev; + volatile bool _aborted; + + struct oob { + unsigned len; + const char *prefix; + mbed::Callback<void()> cb; + oob *next; + }; + oob *_oobs; + +public: + /** + * Constructor + * + * @param serial spi 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(BufferedSpi &serial_spi, const char *delimiter = "\r\n", int buffer_size = 1440, int timeout = DEFAULT_SPI_TIMEOUT); + + /** + * Destructor + */ + ~ATParser() + { + while (_oobs) { + struct oob *oob = _oobs; + _oobs = oob->next; + delete oob; + } + delete[] _buffer; + } + + /** + * Allows timeout to be changed between commands + * + * @param timeout timeout of the connection + */ + void setTimeout(int timeout) + { + _serial_spi->setTimeout(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); + } + + /** + * 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 a newline + * @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); + + /** + * Receive an AT response + * + * Receives a formatted response using scanf style formatting + * @see scanf + * + * Responses are parsed line at a time. + * Any received 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 + * assuming the header of the command is already in _txbuffer + * + * @param data the array of bytes to write + * @param size_of_data number of bytes in data array + * @param size_in_buff number of bytes already in the internal buff + * @return number of bytes written or -1 on failure + */ + int write(const char *data, int size_of_data, int size_in_buff); + + /** + * 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); + + /** + * 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); + + /** + * Flushes the underlying stream + */ + void flush(); + + /** + * Abort current recv + * + * Can be called from oob handler to interrupt the current + * recv operation. + */ + void abort(); + + /** + * Process out-of-band data + * + * Process out-of-band data in the receive buffer. This function + * returns immediately if there is no data to process. + * + * @return true if oob data processed, false otherwise + */ + bool process_oob(void); + /** + * Get buffer_size + */ + int get_size(void) + { + return _buffer_size; + } + +}; +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,86 @@ + +/** + * @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> +uint32_t MyBuffer<T>::getNbAvailable() +{ + if (_wloc >= _rloc) { + return (_wloc - _rloc); + } else { + return (_size - _rloc + _wloc); + } +} + +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>;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,164 @@ + +/** + * @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(); + uint32_t getNbAvailable(); + + /** 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; + //return 1; +} + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedPrint.c Wed Sep 05 14:28:24 2018 +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 BufferedSpiThunk(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 ) { + BufferedSpiThunk(stream, buffer, r); + } + return r; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,333 @@ +/** + * @file BufferedSpi.cpp + * @brief Software Buffer - Extends mbed SPI functionallity + * @author Armelle Duboc + * @version 1.0 + * @see + * + * Copyright (c) STMicroelectronics 2017 + * + * 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 "BufferedSpi.h" +#include <stdarg.h> +#include "mbed_debug.h" +#include "mbed_error.h" + +// change to true to add few SPI debug lines +#define local_debug false + +extern "C" int BufferedPrintfC(void *stream, int size, const char *format, va_list arg); + +void BufferedSpi::DatareadyRising(void) +{ + if (_cmddata_rdy_rising_event == 1) { + _cmddata_rdy_rising_event = 0; + } +} + +int BufferedSpi::wait_cmddata_rdy_high(void) +{ + Timer timer; + timer.start(); + + /* wait for dataready = 1 */ + while (dataready.read() == 0) { + if (timer.read_ms() > _timeout) { + debug_if(local_debug, "ERROR: SPI write timeout\r\n"); + return -1; + } + } + + _cmddata_rdy_rising_event = 1; + + return 0; +} + +int BufferedSpi::wait_cmddata_rdy_rising_event(void) +{ + Timer timer; + timer.start(); + + while (_cmddata_rdy_rising_event == 1) { + if (timer.read_ms() > _timeout) { + _cmddata_rdy_rising_event = 0; + if (dataready.read() == 1) { + debug_if(local_debug, "ERROR: We missed rising event !! (timemout=%d)\r\n", _timeout); + } + debug_if(local_debug, "ERROR: SPI read timeout\r\n"); + return -1; + } + } + + return 0; +} + +BufferedSpi::BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName _nss, PinName _datareadypin, + uint32_t buf_size, uint32_t tx_multiple, const char *name) + : SPI(mosi, miso, sclk, NC), nss(_nss), _txbuf((uint32_t)(tx_multiple * buf_size)), _rxbuf(buf_size), dataready(_datareadypin) +{ + this->_buf_size = buf_size; + this->_tx_multiple = tx_multiple; + this->_sigio_event = 0; + + _datareadyInt = new InterruptIn(_datareadypin); + _datareadyInt->rise(callback(this, &BufferedSpi::DatareadyRising)); + + _cmddata_rdy_rising_event = 1; + + return; +} + +BufferedSpi::~BufferedSpi(void) +{ + + return; +} + +void BufferedSpi::frequency(int hz) +{ + SPI::frequency(hz); +} + +void BufferedSpi::format(int bits, int mode) +{ + SPI::format(bits, mode); +} + +void BufferedSpi::disable_nss() +{ + nss = 1; + wait_us(15); +} + +void BufferedSpi::enable_nss() +{ + nss = 0; + wait_us(15); +} + +int BufferedSpi::readable(void) +{ + return _rxbuf.available(); // note: look if things are in the buffer +} + +int BufferedSpi::writeable(void) +{ + return 1; // buffer allows overwriting by design, always true +} + +int BufferedSpi::getc(void) +{ + if (_rxbuf.available()) { + return _rxbuf; + } else { + return -1; + } +} + +int BufferedSpi::putc(int c) +{ + _txbuf = (char)c; + + return c; +} + +void BufferedSpi::flush_txbuf(void) +{ + _txbuf.clear(); +} + +int BufferedSpi::puts(const char *s) +{ + if (s != NULL) { + const char *ptr = s; + + while (*(ptr) != 0) { + _txbuf = *(ptr++); + } + _txbuf = '\n'; // done per puts definition + BufferedSpi::txIrq(); // only write to hardware in one place + return (ptr - s) + 1; + } + return 0; +} + +extern "C" size_t BufferedSpiThunk(void *buf_spi, const void *s, size_t length) +{ + BufferedSpi *buffered_spi = (BufferedSpi *)buf_spi; + return buffered_spi->buffwrite(s, length); +} + +int BufferedSpi::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 BufferedSpi::buffwrite(const void *s, size_t length) +{ + /* flush buffer from previous message */ + this->flush_txbuf(); + + if (wait_cmddata_rdy_high() < 0) { + debug_if(local_debug, "BufferedSpi::buffwrite timeout (%d)\r\n", _timeout); + return -1; + } + + this->enable_nss(); + + if (s != NULL && length > 0) { + /* 1st fill _txbuf */ + const char *ptr = (const char *)s; + const char *end = ptr + length; + + while (ptr != end) { + _txbuf = *(ptr++); + } + if (length & 1) { /* padding to send the last char */ + _txbuf = '\n'; + length++; + } + + /* 2nd write in SPI */ + BufferedSpi::txIrq(); // only write to hardware in one place + + this->disable_nss(); + return ptr - (const char *)s; + } + this->disable_nss(); + + return 0; +} + +ssize_t BufferedSpi::buffsend(size_t length) +{ + /* wait for dataready = 1 */ + if (wait_cmddata_rdy_high() < 0) { + debug_if(local_debug, "BufferedSpi::buffsend timeout (%d)\r\n", _timeout); + return -1; + } + + this->enable_nss(); + + /* _txbuffer is already filled with data to send */ + /* check if _txbuffer needs padding to send the last char */ + if (length & 1) { + _txbuf = '\n'; + length++; + } + BufferedSpi::txIrq(); // only write to hardware in one place + + this->disable_nss(); + + return length; +} + +ssize_t BufferedSpi::read() +{ + return this->read(0); +} + +ssize_t BufferedSpi::read(uint32_t max) +{ + uint32_t len = 0; + uint8_t FirstRemoved = 1; + int tmp; + + disable_nss(); + + /* wait for data ready is up */ + if (wait_cmddata_rdy_rising_event() != 0) { + debug_if(local_debug, "BufferedSpi::read timeout (%d)\r\n", _timeout); + return -1; + } + + enable_nss(); + while (dataready.read() == 1 && (len < (_buf_size - 2))) { + tmp = SPI::write(0xAA); // dummy write to receive 2 bytes + + if (!((len == 0) && (tmp == 0x0A0D) && (FirstRemoved))) { + /* do not take into account the 2 firts \r \n char in the buffer */ + if ((max == 0) || (len < max)) { + _rxbuf = (char)(tmp & 0x00FF); + _rxbuf = (char)((tmp >> 8) & 0xFF); + len += 2; + } + } else { + FirstRemoved = 0; + } + } + disable_nss(); + + if (len >= _buf_size) { + debug_if(local_debug, "firmware ERROR ES_WIFI_ERROR_STUFFING_FOREVER\r\n"); + return -1; + } + + debug_if(local_debug, "SPI READ %d BYTES\r\n", len); + + return len; +} + +void BufferedSpi::txIrq(void) +{ + /* write everything available in the _txbuffer */ + int value = 0; + int dbg_cnt = 0; + while (_txbuf.available() && (_txbuf.getNbAvailable() > 0)) { + value = _txbuf.get(); + if (_txbuf.available() && ((_txbuf.getNbAvailable() % 2) != 0)) { + value |= ((_txbuf.get() << 8) & 0XFF00); + SPI::write(value); + dbg_cnt++; + } + } + debug_if(local_debug, "SPI Sent %d BYTES\r\n", 2 * dbg_cnt); + // disable the TX interrupt when there is nothing left to send + BufferedSpi::attach(NULL, BufferedSpi::TxIrq); + // trigger callback if necessary + if (_cbs[TxIrq]) { + _cbs[TxIrq](); + } + return; +} + +void BufferedSpi::prime(void) +{ + BufferedSpi::txIrq(); // only write to hardware in one place + return; +} + +void BufferedSpi::attach(Callback<void()> func, IrqType type) +{ + _cbs[type] = func; +} + +void BufferedSpi::sigio(Callback<void()> func) +{ + core_util_critical_section_enter(); + _sigio_cb = func; + if (_sigio_cb) { + if (_sigio_event == 1) { + _sigio_cb(); + _sigio_event = 0; + } + } + core_util_critical_section_exit(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,234 @@ + +/** + * @file BufferedSpi.h + * @brief Software Buffer - Extends mbed SPI functionallity + * @author Armelle Duboc + * @version 1.0 + * @see + * + * Copyright (c) STMicroelectronics 2017 + * + * 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 BUFFEREDSPI_H +#define BUFFEREDSPI_H + +#include "mbed.h" +#include "MyBuffer.h" + +/** A spi port (SPI) for communication with wifi device + * + * 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 BufferedSpi + * @brief Software buffers and interrupt driven tx and rx for Serial + */ +class BufferedSpi : public SPI { +private: + DigitalOut nss; + MyBuffer <char> _txbuf; + uint32_t _buf_size; + uint32_t _tx_multiple; + volatile int _timeout; + void txIrq(void); + void prime(void); + + InterruptIn *_datareadyInt; + volatile int _cmddata_rdy_rising_event; + void DatareadyRising(void); + int wait_cmddata_rdy_rising_event(void); + int wait_cmddata_rdy_high(void); + + + Callback<void()> _cbs[2]; + + Callback<void()> _sigio_cb; + uint8_t _sigio_event; + +public: + MyBuffer <char> _rxbuf; + DigitalIn dataready; + enum IrqType { + RxIrq = 0, + TxIrq, + + IrqCnt + }; + + /** Create a BufferedSpi Port, connected to the specified transmit and receive pins + * @param SPI mosi pin + * @param SPI miso pin + * @param SPI sclk pin + * @param SPI nss pin + * @param Dataready 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 + */ + BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName datareadypin, uint32_t buf_size = 2500, uint32_t tx_multiple = 1, const char *name = NULL); + + /** Destroy a BufferedSpi Port + */ + virtual ~BufferedSpi(void); + + /** call to SPI frequency Function + */ + virtual void frequency(int hz); + + /** clear the transmit buffer + */ + virtual void flush_txbuf(void); + + /** call to SPI format function + */ + virtual void format(int bits, int mode); + + virtual void enable_nss(void); + + virtual void disable_nss(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 BufferedSpi Port. + * Should check readable() before calling this. + * @return A byte that came in on the SPI Port + */ + virtual int getc(void); + + /** Write a single byte to the BufferedSpi Port. + * @param c The byte to write to the SPI Port + * @return The byte that was written to the SPI Port Buffer + */ + virtual int putc(int c); + + /** Write a string to the BufferedSpi Port. Must be NULL terminated + * @param s The string to write to the Spi Port + * @return The number of bytes written to the Spi Port Buffer + */ + virtual int puts(const char *s); + + /** Write a formatted string to the BufferedSpi Port. + * @param format The string + format specifiers to write to the Spi Port + * @return The number of bytes written to the Spi Port Buffer + */ + virtual int printf(const char *format, ...); + + /** Write data to the Buffered Spi 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 Spi Port Buffer + */ + virtual ssize_t buffwrite(const void *s, std::size_t length); + + /** Send datas to the Spi port that are already present + * in the internal _txbuffer + * @param length + * @return the number of bytes written on the SPI port + */ + virtual ssize_t buffsend(size_t length); + + /** Read data from the Spi Port to the _rxbuf + * @param max: optional. = max sieze of the input read + * @return The number of bytes read from the SPI port and written to the _rxbuf + */ + virtual ssize_t read(); + virtual ssize_t read(uint32_t max); + + /** + * Allows timeout to be changed between commands + * + * @param timeout timeout of the connection in ms + */ + void setTimeout(int timeout) + { + /* this is a safe guard timeout at SPI level in case module is stuck */ + _timeout = timeout; + } + + /** Register a callback once any data is ready for sockets + * @param func Function to call on state change + */ + virtual void sigio(Callback<void()> func); + + /** 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ISM43362.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,699 @@ +/* ISM43362 Example +* +* Copyright (c) STMicroelectronics 2018 + * + * 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 "ISM43362.h" +#include "mbed_debug.h" + +// activate / de-activate debug +#define ism_debug 0 + +ISM43362::ISM43362(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName resetpin, PinName datareadypin, PinName wakeup, bool debug) + : _bufferspi(mosi, miso, sclk, nss, datareadypin), + _parser(_bufferspi), + _resetpin(resetpin), + _packets(0), _packets_end(&_packets) +{ + DigitalOut wakeup_pin(wakeup); + _bufferspi.format(16, 0); /* 16bits, ploarity low, phase 1Edge, master mode */ + _bufferspi.frequency(20000000); /* up to 20 MHz */ + _active_id = 0xFF; + _FwVersionId = 0; + + _ism_debug = debug || ism_debug; + reset(); +} + +/** + * @brief Parses and returns number from string. + * @param ptr: pointer to string + * @param cnt: pointer to the number of parsed digit + * @retval integer value. + */ +#define CHARISHEXNUM(x) (((x) >= '0' && (x) <= '9') || \ + ((x) >= 'a' && (x) <= 'f') || \ + ((x) >= 'A' && (x) <= 'F')) +#define CHARISNUM(x) ((x) >= '0' && (x) <= '9') +#define CHAR2NUM(x) ((x) - '0') + + +extern "C" int32_t ParseNumber(char *ptr, uint8_t *cnt) +{ + uint8_t minus = 0, i = 0; + int32_t sum = 0; + + if (*ptr == '-') { /* Check for minus character */ + minus = 1; + ptr++; + i++; + } + if (*ptr == 'C') { /* input string from get_firmware_version is Cx.x.x.x */ + ptr++; + } + + while (CHARISNUM(*ptr) || (*ptr == '.')) { /* Parse number */ + if (*ptr == '.') { + ptr++; // next char + } else { + sum = 10 * sum + CHAR2NUM(*ptr); + ptr++; + i++; + } + } + + if (cnt != NULL) { /* Save number of characters used for number */ + *cnt = i; + } + if (minus) { /* Minus detected */ + return 0 - sum; + } + return sum; /* Return number */ +} + +uint32_t ISM43362::get_firmware_version(void) +{ + char tmp_buffer[250]; + char *ptr, *ptr2; + char _fw_version[16]; + + /* Use %[^\n] instead of %s to allow having spaces in the string */ + if (!(_parser.send("I?") && _parser.recv("%[^\n^\r]\r\n", tmp_buffer) && check_response())) { + debug_if(_ism_debug, "ISM43362: get_firmware_version is FAIL\r\n"); + return 0; + } + debug_if(_ism_debug, "ISM43362: get_firmware_version = %s\r\n", tmp_buffer); + + // Get the first version in the string + ptr = strtok((char *)tmp_buffer, ","); + ptr = strtok(NULL, ","); + ptr2 = strtok(NULL, ","); + if (ptr == NULL) { + debug_if(_ism_debug, "ISM43362: get_firmware_version decoding is FAIL\r\n"); + return 0; + } + strncpy(_fw_version, ptr, ptr2 - ptr); + _FwVersionId = ParseNumber(_fw_version, NULL); + + return _FwVersionId; +} + +bool ISM43362::reset(void) +{ + char tmp_buffer[100]; + debug_if(_ism_debug, "ISM43362: Reset Module\r\n"); + _resetpin = 0; + wait_ms(10); + _resetpin = 1; + wait_ms(500); + + /* Wait for prompt line : the string is "> ". */ + /* As the space char is not detected by sscanf function in parser.recv, */ + /* we need to use %[\n] */ + if (!_parser.recv(">%[^\n]", tmp_buffer)) { + debug_if(_ism_debug, "ISM43362: Reset Module failed\r\n"); + return false; + } + return true; +} + +void ISM43362::print_rx_buff(void) +{ + char tmp[150] = {0}; + uint16_t i = 0; + debug_if(_ism_debug, "ISM43362: "); + while (i < 150) { + int c = _parser.getc(); + if (c < 0) { + break; + } + tmp[i] = c; + debug_if(_ism_debug, "0x%2X ", c); + i++; + } + debug_if(_ism_debug, "\n"); + debug_if(_ism_debug, "ISM43362: Buffer content =====%s=====\r\n", tmp); +} + +/* checks the standard OK response of the WIFI module, shouldbe: + * \r\nDATA\r\nOK\r\n>sp + * or + * \r\nERROR\r\nUSAGE\r\n>sp + * function returns true if OK, false otherwise. In case of error, + * print error content then flush buffer */ +bool ISM43362::check_response(void) +{ + char tmp_buffer[100]; + if (!_parser.recv("OK\r\n")) { + print_rx_buff(); + _parser.flush(); + return false; + } + + /* Then we should get the prompt: "> " */ + /* As the space char is not detected by sscanf function in parser.recv, */ + /* we need to use %[\n] */ + if (!_parser.recv(">%[^\n]", tmp_buffer)) { + debug_if(_ism_debug, "ISM43362: Missing prompt in WIFI resp\r\n"); + print_rx_buff(); + _parser.flush(); + return false; + } + + /* Inventek module do stuffing / padding of data with 0x15, + * in case buffer contains such */ + while (1) { + int c = _parser.getc(); + if (c == 0x15) { + // debug_if(_ism_debug, "ISM43362: Flush char 0x%x\n", c); + continue; + } else { + /* How to put it back if needed ? */ + break; + } + } + return true; +} + +bool ISM43362::dhcp(bool enabled) +{ + return (_parser.send("C4=%d", enabled ? 1 : 0) && check_response()); +} + +int ISM43362::connect(const char *ap, const char *passPhrase, ism_security_t ap_sec) +{ + char tmp[256]; + + if (!(_parser.send("C1=%s", ap) && check_response())) { + return NSAPI_ERROR_PARAMETER; + } + + if (!(_parser.send("C2=%s", passPhrase) && check_response())) { + return NSAPI_ERROR_PARAMETER; + } + + /* Check security level is acceptable */ + if (ap_sec > ISM_SECURITY_WPA_WPA2) { + debug_if(_ism_debug, "ISM43362: Unsupported security level %d\n", ap_sec); + return NSAPI_ERROR_UNSUPPORTED; + } + + if (!(_parser.send("C3=%d", ap_sec) && check_response())) { + return NSAPI_ERROR_PARAMETER; + } + + if (_parser.send("C0")) { + while (_parser.recv("%[^\n]\n", tmp)) { + if (strstr(tmp, "OK")) { + _parser.flush(); + return NSAPI_ERROR_OK; + } + if (strstr(tmp, "JOIN")) { + if (strstr(tmp, "Failed")) { + _parser.flush(); + return NSAPI_ERROR_AUTH_FAILURE; + } + } + } + } + + return NSAPI_ERROR_NO_CONNECTION; +} + +bool ISM43362::disconnect(void) +{ + return (_parser.send("CD") && check_response()); +} + +const char *ISM43362::getIPAddress(void) +{ + char tmp_ip_buffer[250]; + char *ptr, *ptr2; + + /* Use %[^\n] instead of %s to allow having spaces in the string */ + if (!(_parser.send("C?") + && _parser.recv("%[^\n^\r]\r\n", tmp_ip_buffer) + && check_response())) { + debug_if(_ism_debug, "ISM43362: getIPAddress LINE KO: %s\n", tmp_ip_buffer); + return 0; + } + + /* Get the IP address in the result */ + /* TODO : check if the begining of the string is always = "eS-WiFi_AP_C47F51011231," */ + ptr = strtok((char *)tmp_ip_buffer, ","); + ptr = strtok(NULL, ","); + ptr = strtok(NULL, ","); + ptr = strtok(NULL, ","); + ptr = strtok(NULL, ","); + ptr = strtok(NULL, ","); + ptr2 = strtok(NULL, ","); + if (ptr == NULL) { + return 0; + } + strncpy(_ip_buffer, ptr, ptr2 - ptr); + + tmp_ip_buffer[59] = 0; + debug_if(_ism_debug, "ISM43362: receivedIPAddress: %s\n", _ip_buffer); + + return _ip_buffer; +} + +const char *ISM43362::getMACAddress(void) +{ + if (!(_parser.send("Z5") && _parser.recv("%s\r\n", _mac_buffer) && check_response())) { + debug_if(_ism_debug, "ISM43362: receivedMacAddress LINE KO: %s\n", _mac_buffer); + return 0; + } + + debug_if(_ism_debug, "ISM43362: receivedMacAddress:%s, size=%d\r\n", _mac_buffer, sizeof(_mac_buffer)); + + return _mac_buffer; +} + +const char *ISM43362::getGateway() +{ + char tmp[250]; + /* Use %[^\n] instead of %s to allow having spaces in the string */ + if (!(_parser.send("C?") && _parser.recv("%[^\n^\r]\r\n", tmp) && check_response())) { + debug_if(_ism_debug, "ISM43362: getGateway LINE KO: %s\r\n", tmp); + return 0; + } + + /* Extract the Gateway in the received buffer */ + char *ptr; + ptr = strtok(tmp, ","); + for (int i = 0; i < 7; i++) { + if (ptr == NULL) { + break; + } + ptr = strtok(NULL, ","); + } + + strncpy(_gateway_buffer, ptr, sizeof(_gateway_buffer)); + + debug_if(_ism_debug, "ISM43362: getGateway: %s\r\n", _gateway_buffer); + + return _gateway_buffer; +} + +const char *ISM43362::getNetmask() +{ + char tmp[250]; + /* Use %[^\n] instead of %s to allow having spaces in the string */ + if (!(_parser.send("C?") && _parser.recv("%[^\n^\r]\r\n", tmp) && check_response())) { + debug_if(_ism_debug, "ISM43362: getNetmask LINE KO: %s\n", tmp); + return 0; + } + + /* Extract Netmask in the received buffer */ + char *ptr; + ptr = strtok(tmp, ","); + for (int i = 0; i < 6; i++) { + if (ptr == NULL) { + break; + } + ptr = strtok(NULL, ","); + } + + strncpy(_netmask_buffer, ptr, sizeof(_netmask_buffer)); + + debug_if(_ism_debug, "ISM43362: getNetmask: %s\r\n", _netmask_buffer); + + return _netmask_buffer; +} + +int8_t ISM43362::getRSSI() +{ + int8_t rssi; + char tmp[25]; + + if (!(_parser.send("CR") && _parser.recv("%s\r\n", tmp) && check_response())) { + debug_if(_ism_debug, "ISM43362: getRSSI LINE KO: %s\r\n", tmp); + return 0; + } + + rssi = ParseNumber(tmp, NULL); + + debug_if(_ism_debug, "ISM43362: getRSSI: %d\r\n", rssi); + + return rssi; +} +/** + * @brief Parses Security type. + * @param ptr: pointer to string + * @retval Encryption type. + */ +extern "C" nsapi_security_t ParseSecurity(char *ptr) +{ + if (strstr(ptr, "Open")) { + return NSAPI_SECURITY_NONE; + } else if (strstr(ptr, "WEP")) { + return NSAPI_SECURITY_WEP; + } else if (strstr(ptr, "WPA2 AES")) { + return NSAPI_SECURITY_WPA2; + } else if (strstr(ptr, "WPA WPA2")) { + return NSAPI_SECURITY_WPA_WPA2; + } else if (strstr(ptr, "WPA2 TKIP")) { + return NSAPI_SECURITY_UNKNOWN; // no match in mbed + } else if (strstr(ptr, "WPA2")) { + return NSAPI_SECURITY_WPA2; // catch any other WPA2 formula + } else if (strstr(ptr, "WPA")) { + return NSAPI_SECURITY_WPA; + } else { + return NSAPI_SECURITY_UNKNOWN; + } +} + +/** + * @brief Convert char in Hex format to integer. + * @param a: character to convert + * @retval integer value. + */ +extern "C" uint8_t Hex2Num(char a) +{ + if (a >= '0' && a <= '9') { /* Char is num */ + return a - '0'; + } else if (a >= 'a' && a <= 'f') { /* Char is lowercase character A - Z (hex) */ + return (a - 'a') + 10; + } else if (a >= 'A' && a <= 'F') { /* Char is uppercase character A - Z (hex) */ + return (a - 'A') + 10; + } + + return 0; +} + +/** + * @brief Extract a hex number from a string. + * @param ptr: pointer to string + * @param cnt: pointer to the number of parsed digit + * @retval Hex value. + */ +extern "C" uint32_t ParseHexNumber(char *ptr, uint8_t *cnt) +{ + uint32_t sum = 0; + uint8_t i = 0; + + while (CHARISHEXNUM(*ptr)) { /* Parse number */ + sum <<= 4; + sum += Hex2Num(*ptr); + ptr++; + i++; + } + + if (cnt != NULL) { /* Save number of characters used for number */ + *cnt = i; + } + return sum; /* Return number */ +} + +bool ISM43362::isConnected(void) +{ + return getIPAddress() != 0; +} + +int ISM43362::scan(WiFiAccessPoint *res, unsigned limit) +{ + unsigned cnt = 0, num = 0; + char *ptr; + char tmp[256]; + + if (!(_parser.send("F0"))) { + debug_if(_ism_debug, "ISM43362: scan error\r\n"); + return 0; + } + + /* Parse the received buffer and fill AP buffer */ + /* Use %[^\n] instead of %s to allow having spaces in the string */ + while (_parser.recv("#%[^\n]\n", tmp)) { + if (limit != 0 && cnt >= limit) { + /* reached end */ + break; + } + nsapi_wifi_ap_t ap = {0}; + debug_if(_ism_debug, "ISM43362: received:%s\n", tmp); + ptr = strtok(tmp, ","); + num = 0; + while (ptr != NULL) { + switch (num++) { + case 0: /* Ignore index */ + case 4: /* Ignore Max Rate */ + case 5: /* Ignore Network Type */ + case 7: /* Ignore Radio Band */ + break; + case 1: + ptr[strlen(ptr) - 1] = 0; + strncpy((char *)ap.ssid, ptr + 1, 32); + break; + case 2: + for (int i = 0; i < 6; i++) { + ap.bssid[i] = ParseHexNumber(ptr + (i * 3), NULL); + } + break; + case 3: + ap.rssi = ParseNumber(ptr, NULL); + break; + case 6: + ap.security = ParseSecurity(ptr); + break; + case 8: + ap.channel = ParseNumber(ptr, NULL); + num = 1; + break; + default: + break; + } + ptr = strtok(NULL, ","); + } + if (res != NULL) { + res[cnt] = WiFiAccessPoint(ap); + } + cnt++; + } + + /* We may stop before having read all the APs list, so flush the rest of + * it as well as OK commands */ + _parser.flush(); + + debug_if(_ism_debug, "ISM43362: End of Scan: cnt=%d\n", cnt); + + return cnt; + +} + +bool ISM43362::open(const char *type, int id, const char *addr, int port) +{ + /* TODO : This is the implementation for the client socket, need to check if need to create openserver too */ + //IDs only 0-3 + if ((id < 0) || (id > 3)) { + debug_if(_ism_debug, "ISM43362: open: wrong id\n"); + return false; + } + /* Set communication socket */ + _active_id = id; + if (!(_parser.send("P0=%d", id) && check_response())) { + debug_if(_ism_debug, "ISM43362: open: P0 issue\n"); + return false; + } + /* Set protocol */ + if (!(_parser.send("P1=%s", type) && check_response())) { + debug_if(_ism_debug, "ISM43362: open: P1 issue\n"); + return false; + } + /* Set address */ + if (!(_parser.send("P3=%s", addr) && check_response())) { + debug_if(_ism_debug, "ISM43362: open: P3 issue\n"); + return false; + } + if (!(_parser.send("P4=%d", port) && check_response())) { + debug_if(_ism_debug, "ISM43362: open: P4 issue\n"); + return false; + } + /* Start client */ + if (!(_parser.send("P6=1") && check_response())) { + debug_if(_ism_debug, "ISM43362: open: P6 issue\n"); + return false; + } + + /* request as much data as possible - i.e. module max size */ + if (!(_parser.send("R1=%d", ES_WIFI_MAX_RX_PACKET_SIZE) && check_response())) { + debug_if(_ism_debug, "ISM43362: open: R1 issue\n"); + return -1; + } + + /* Non blocking mode : set Read Transport Timeout to 1ms */ + if (!(_parser.send("R2=1") && check_response())) { + debug_if(_ism_debug, "ISM43362: open: R2 issue\n"); + return -1; + } + + debug_if(_ism_debug, "ISM43362: open ok with id %d type %s addr %s port %d\n", id, type, addr, port); + + return true; +} + +bool ISM43362::dns_lookup(const char *name, char *ip) +{ + char tmp[30]; + + if (!(_parser.send("D0=%s", name) && _parser.recv("%s\r\n", tmp) + && check_response())) { + debug_if(_ism_debug, "ISM43362 dns_lookup: D0 issue: %s\n", tmp); + return 0; + } + + strncpy(ip, tmp, sizeof(tmp)); + + debug_if(_ism_debug, "ISM43362 dns_lookup: %s ok\n", ip); + return 1; +} + +bool ISM43362::send(int id, const void *data, uint32_t amount) +{ + // The Size limit has to be checked on caller side. + if (amount > ES_WIFI_MAX_TX_PACKET_SIZE) { + debug_if(_ism_debug, "ISM43362 send: max issue\n"); + return false; + } + + /* Activate the socket id in the wifi module */ + if ((id < 0) || (id > 3)) { + return false; + } + if (_active_id != id) { + _active_id = id; + if (!(_parser.send("P0=%d", id) && check_response())) { + debug_if(_ism_debug, "ISM43362 send: P0 issue\n"); + return false; + } + } + + /* set Write Transport Packet Size */ + int i = _parser.printf("S3=%d\r", (int)amount); + if (i < 0) { + debug_if(_ism_debug, "ISM43362 send: S3 issue\n"); + return false; + } + i = _parser.write((const char *)data, amount, i); + if (i < 0) { + return false; + } + + if (!check_response()) { + return false; + } + + debug_if(_ism_debug, "ISM43362 send: id %d amount %d\n", id, amount); + return true; +} + +int ISM43362::check_recv_status(int id, void *data) +{ + int read_amount; + + debug_if(_ism_debug, "ISM43362 check_recv_status: id %d\r\n", id); + + /* Activate the socket id in the wifi module */ + if ((id < 0) || (id > 3)) { + debug_if(_ism_debug, "ISM43362 check_recv_status: ERROR with id %d\r\n", id); + return -1; + } + + if (_active_id != id) { + _active_id = id; + if (!(_parser.send("P0=%d", id) && check_response())) { + return -1; + } + } + + + if (!_parser.send("R0")) { + return -1; + } + read_amount = _parser.read((char *)data); + + if (read_amount < 0) { + debug_if(_ism_debug, "ISM43362 check_recv_status: ERROR in data RECV, timeout?\r\n"); + return -1; /* nothing to read */ + } + + /* If there are spurious 0x15 at the end of the data, this is an error + * we hall can get rid off of them :-( + * This should not happen, but let's try to clean-up anyway + */ + char *cleanup = (char *) data; + while ((read_amount > 0) && (cleanup[read_amount - 1] == 0x15)) { + // debug_if(_ism_debug, "ISM43362 check_recv_status: spurious 0X15 trashed\r\n"); + /* Remove the trailling char then search again */ + read_amount--; + } + + if ((read_amount >= 6) && (strncmp("OK\r\n> ", (char *)data, 6) == 0)) { + // debug_if(_ism_debug, "ISM43362 check_recv_status: recv 2 nothing to read=%d\r\n", read_amount); + // read_amount -= 6; + return 0; /* nothing to read */ + } else if ((read_amount >= 8) && (strncmp((char *)((uint32_t) data + read_amount - 8), "\r\nOK\r\n> ", 8)) == 0) { + /* bypass ""\r\nOK\r\n> " if present at the end of the chain */ + read_amount -= 8; + } else { + debug_if(_ism_debug, "ISM43362 check_recv_status: ERROR, flushing %d bytes: ", read_amount); + // for (int i = 0; i < read_amount; i++) { + // debug_if(_ism_debug, "%2X ", cleanup[i]); + // } + // debug_if(_ism_debug, "\r\n (ASCII)", cleanup); + cleanup[read_amount] = 0; + debug_if(_ism_debug, "%s\r\n", cleanup); + return -1; /* nothing to read */ + } + + debug_if(_ism_debug, "ISM43362 check_recv_status: id %d read_amount=%d\r\n", id, read_amount); + return read_amount; +} + +bool ISM43362::close(int id) +{ + if ((id < 0) || (id > 3)) { + debug_if(_ism_debug, "ISM43362: Wrong socket number\n"); + return false; + } + /* Set connection on this socket */ + debug_if(_ism_debug, "ISM43362: CLOSE socket id=%d\n", id); + _active_id = id; + if (!(_parser.send("P0=%d", id) && check_response())) { + return false; + } + /* close this socket */ + if (!(_parser.send("P6=0") && check_response())) { + return false; + } + return true; +} + +bool ISM43362::readable() +{ + /* not applicable with SPI api */ + return true; +} + +bool ISM43362::writeable() +{ + /* not applicable with SPI api */ + return true; +} + +void ISM43362::attach(Callback<void()> func) +{ + /* not applicable with SPI api */ +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362/ISM43362.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,250 @@ +/* ISM43362Interface Example + * Copyright (c) STMicroelectronics 2017 + * + * 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 ISM43362_H +#define ISM43362_H +#include "ATParser.h" + +#define ES_WIFI_MAX_SSID_NAME_SIZE 32 +#define ES_WIFI_MAX_PSWD_NAME_SIZE 32 +#define ES_WIFI_PRODUCT_ID_SIZE 32 +#define ES_WIFI_PRODUCT_NAME_SIZE 32 +#define ES_WIFI_FW_REV_SIZE 16 +#define ES_WIFI_API_REV_SIZE 16 +#define ES_WIFI_STACK_REV_SIZE 16 +#define ES_WIFI_RTOS_REV_SIZE 16 + +// The input range for AT Command 'R1' is 0 to 1200 bytes +// 'R1' Set Read Transport Packet Size (bytes) +#define ES_WIFI_MAX_RX_PACKET_SIZE 1200 +// Module maxume DATA payload for Tx packet is 1460 +#define ES_WIFI_MAX_TX_PACKET_SIZE 1460 +typedef enum ism_security { + ISM_SECURITY_NONE = 0x0, /*!< open access point */ + ISM_SECURITY_WEP = 0x1, /*!< phrase conforms to WEP */ + ISM_SECURITY_WPA = 0x2, /*!< phrase conforms to WPA */ + ISM_SECURITY_WPA2 = 0x3, /*!< phrase conforms to WPA2 */ + ISM_SECURITY_WPA_WPA2 = 0x4, /*!< phrase conforms to WPA/WPA2 */ + ISM_SECURITY_UNKNOWN = 0xFF, /*!< unknown/unsupported security in scan results */ +} ism_security_t; + +extern "C" int32_t ParseNumber(char *ptr, uint8_t *cnt); + +/** ISM43362Interface class. + This is an interface to a ISM43362 radio. + */ +class ISM43362 { +public: + ISM43362(PinName mosi, PinName miso, PinName clk, PinName nss, PinName resetpin, PinName datareadypin, PinName wakeup, bool debug = false); + + /** + * Check firmware version of ISM43362 + * + * @return fw version or null if no version is read + */ + uint32_t get_firmware_version(void); + + /** + * Reset ISM43362 + * + * @return true only if ISM43362 resets successfully + */ + bool reset(void); + + /** + * Enable/Disable DHCP + * + * @param enabled DHCP enabled when true + * @return true only if ISM43362 enables/disables DHCP successfully + */ + bool dhcp(bool enabled); + + /** + * Connect ISM43362 to AP + * + * @param ap the name of the AP + * @param passPhrase the password of AP + * @param ap_sec the security level of network AP + * @return nsapi_error enum + */ + int connect(const char *ap, const char *passPhrase, ism_security_t ap_sec); + + /** + * Disconnect ISM43362 from AP + * + * @return true only if ISM43362 is disconnected successfully + */ + bool disconnect(void); + + /** + * Get the IP address of ISM43362 + * + * @return null-teriminated IP address or null if no IP address is assigned + */ + const char *getIPAddress(void); + + /** + * Get the MAC address of ISM43362 + * + * @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 ISM43362 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); + + /**Perform a dns query + * + * @param name Hostname to resolve + * @param ip Buffer to store IP address + * @return 0 true on success, false on failure + */ + bool dns_lookup(const char *name, char *ip); + + /** + * 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); + + /** + * 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); + + /** + * Check is datas are available to read for a socket + * @param id socket id + * @param data placeholder for returned information + * @param amount size to read for the check + * @return amount of read value, or -1 for errors + */ + int check_recv_status(int id, void *data); + + /** + * 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: + BufferedSpi _bufferspi; + ATParser _parser; + DigitalOut _resetpin; + volatile int _active_id; + void print_rx_buff(void); + bool check_response(void); + struct packet { + struct packet *next; + int id; + uint32_t len; + // data follows + } *_packets, * *_packets_end; + void _packet_handler(); + bool _ism_debug; + + char _ip_buffer[16]; + char _gateway_buffer[16]; + char _netmask_buffer[16]; + char _mac_buffer[18]; + uint32_t _FwVersionId; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362Interface.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,555 @@ +/* ISM43362 implementation of NetworkInterfaceAPI + * Copyright (c) STMicroelectronics 2018 + * + * 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 "ISM43362Interface.h" +#include "mbed_debug.h" + + // Product ID,FW Revision,API Revision,Stack Revision,RTOS Revision,CPU Clock,Product Name +#define LATEST_FW_VERSION_NUMBER "C3.5.2.5" // ISM43362-M3G-L44-SPI,C3.5.2.5.STM,v3.5.2,v1.4.0.rc1,v8.2.1,120000000,Inventek eS-WiFi + +// activate / de-activate debug +#define ism_interface_debug 0 + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +// ISM43362Interface implementation +ISM43362Interface::ISM43362Interface(bool debug) + : _ism(MBED_CONF_ISM43362_WIFI_MOSI, MBED_CONF_ISM43362_WIFI_MISO, MBED_CONF_ISM43362_WIFI_SCLK, MBED_CONF_ISM43362_WIFI_NSS, MBED_CONF_ISM43362_WIFI_RESET, MBED_CONF_ISM43362_WIFI_DATAREADY, MBED_CONF_ISM43362_WIFI_WAKEUP, debug) +{ + _ism_debug = ism_interface_debug || debug; + memset(_ids, 0, sizeof(_ids)); + memset(_socket_obj, 0, sizeof(_socket_obj)); + memset(_cbs, 0, sizeof(_cbs)); + memset(ap_ssid, 0, sizeof(ap_ssid)); + memset(ap_pass, 0, sizeof(ap_pass)); + ap_sec = ISM_SECURITY_UNKNOWN; + + thread_read_socket.start(callback(this, &ISM43362Interface::socket_check_read)); + + _mutex.lock(); + + // Check all supported firmware versions + _FwVersion = _ism.get_firmware_version(); + + if (!_FwVersion) { + error("ISM43362Interface: ERROR cannot read firmware version\r\n"); + } + + debug_if(_ism_debug, "ISM43362Interface: read_version = %lu\r\n", _FwVersion); + /* FW Revision should be with format "CX.X.X.X" with X as a single digit */ + if ( (_FwVersion < 1000) || (_FwVersion > 9999) ) { + debug_if(_ism_debug, "ISM43362Interface: read_version issue\r\n"); + } + +#if TARGET_DISCO_L475VG_IOT01A + if (_FwVersion < ParseNumber(LATEST_FW_VERSION_NUMBER, NULL)) { + debug_if(_ism_debug, "ISM43362Interface: please update FW\r\n"); + } +#endif + + _mutex.unlock(); +} + +int ISM43362Interface::connect(const char *ssid, const char *pass, nsapi_security_t security, + uint8_t channel) +{ + if (channel != 0) { + return NSAPI_ERROR_UNSUPPORTED; + } + + nsapi_error_t credentials_status = set_credentials(ssid, pass, security); + if (credentials_status) { + return credentials_status; + } + + return connect(); +} + +int ISM43362Interface::connect() +{ + if (strlen(ap_ssid) == 0) { + return NSAPI_ERROR_NO_SSID; + } + + _mutex.lock(); + + if (!_ism.dhcp(true)) { + _mutex.unlock(); + return NSAPI_ERROR_DHCP_FAILURE; + } + + int connect_status = _ism.connect(ap_ssid, ap_pass, ap_sec); + debug_if(_ism_debug, "ISM43362Interface: connect_status %d\n", connect_status); + + if (connect_status != NSAPI_ERROR_OK) { + _mutex.unlock(); + return connect_status; + } + + if (!_ism.getIPAddress()) { + _mutex.unlock(); + return NSAPI_ERROR_DHCP_FAILURE; + } + + _mutex.unlock(); + + return NSAPI_ERROR_OK; +} + +nsapi_error_t ISM43362Interface::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version) +{ + if (strlen(name) == 0) { + return NSAPI_ERROR_NO_SOCKET; + } + + _mutex.lock(); + if (address->set_ip_address(name)) { + if (version != NSAPI_UNSPEC && address->get_ip_version() != version) { + _mutex.unlock(); + return NSAPI_ERROR_DNS_FAILURE; + } + + _mutex.unlock(); + return NSAPI_ERROR_OK; + } + + char *ipbuff = new char[NSAPI_IP_SIZE]; + int ret = 0; + if (!_ism.dns_lookup(name, ipbuff)) { + ret = NSAPI_ERROR_DEVICE_ERROR; + } else { + address->set_ip_address(ipbuff); + } + _mutex.unlock(); + + delete[] ipbuff; + + return ret; +} + +int ISM43362Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) +{ + if ((strlen(ssid) == 0) || (strlen(ssid) > 32)) { + return NSAPI_ERROR_PARAMETER; + } + + if ((security != NSAPI_SECURITY_NONE) && (strcmp(pass, "") == 0)) { + return NSAPI_ERROR_PARAMETER; + } + + if (strlen(pass) > 63) { + return NSAPI_ERROR_PARAMETER; + } + + _mutex.lock(); + 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)); + + switch (security) { + case NSAPI_SECURITY_NONE: + ap_sec = ISM_SECURITY_NONE; + break; + case NSAPI_SECURITY_WEP: + ap_sec = ISM_SECURITY_WEP; + break; + case NSAPI_SECURITY_WPA: + ap_sec = ISM_SECURITY_WPA; + break; + case NSAPI_SECURITY_WPA2: + ap_sec = ISM_SECURITY_WPA2; + break; + case NSAPI_SECURITY_WPA_WPA2: + ap_sec = ISM_SECURITY_WPA_WPA2; + break; + default: + ap_sec = ISM_SECURITY_UNKNOWN; + break; + } + _mutex.unlock(); + + return NSAPI_ERROR_OK; +} + +int ISM43362Interface::set_channel(uint8_t channel) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +int ISM43362Interface::disconnect() +{ + _mutex.lock(); + + if (!_ism.disconnect()) { + _mutex.unlock(); + return NSAPI_ERROR_DEVICE_ERROR; + } + + _mutex.unlock(); + + return NSAPI_ERROR_OK; +} + +const char *ISM43362Interface::get_ip_address() +{ + _mutex.lock(); + const char *ret = _ism.getIPAddress(); + _mutex.unlock(); + return ret; +} + +const char *ISM43362Interface::get_mac_address() +{ + _mutex.lock(); + const char *ret = _ism.getMACAddress(); + _mutex.unlock(); + return ret; +} + +const char *ISM43362Interface::get_gateway() +{ + _mutex.lock(); + const char *ret = _ism.getGateway(); + _mutex.unlock(); + return ret; +} + +const char *ISM43362Interface::get_netmask() +{ + _mutex.lock(); + const char *ret = _ism.getNetmask(); + _mutex.unlock(); + return ret; +} + +int8_t ISM43362Interface::get_rssi() +{ + _mutex.lock(); + int8_t ret = _ism.getRSSI(); + _mutex.unlock(); + return ret; +} + +int ISM43362Interface::scan(WiFiAccessPoint *res, unsigned count) +{ + _mutex.lock(); + int ret = _ism.scan(res, count); + _mutex.unlock(); + return ret; +} + +struct ISM43362_socket { + int id; + nsapi_protocol_t proto; + volatile bool connected; + SocketAddress addr; + char read_data[1400]; + volatile uint32_t read_data_size; +}; + +int ISM43362Interface::socket_open(void **handle, nsapi_protocol_t proto) +{ + // Look for an unused socket + int id = -1; + for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) { + if (!_ids[i]) { + id = i; + _ids[i] = true; + break; + } + } + + if (id == -1) { + return NSAPI_ERROR_NO_SOCKET; + } + _mutex.lock(); + struct ISM43362_socket *socket = new struct ISM43362_socket; + if (!socket) { + _mutex.unlock(); + return NSAPI_ERROR_NO_SOCKET; + } + socket->id = id; + debug_if(_ism_debug, "ISM43362Interface: socket_open, id=%d\n", socket->id); + memset(socket->read_data, 0, sizeof(socket->read_data)); + socket->addr = 0; + socket->read_data_size = 0; + socket->proto = proto; + socket->connected = false; + *handle = socket; + _mutex.unlock(); + + return 0; +} + +int ISM43362Interface::socket_close(void *handle) +{ + _mutex.lock(); + struct ISM43362_socket *socket = (struct ISM43362_socket *)handle; + debug_if(_ism_debug, "ISM43362Interface: socket_close, id=%d\n", socket->id); + int err = 0; + + if (!_ism.close(socket->id)) { + err = NSAPI_ERROR_DEVICE_ERROR; + } + + socket->connected = false; + _ids[socket->id] = false; + _socket_obj[socket->id] = 0; + _mutex.unlock(); + delete socket; + return err; +} + +int ISM43362Interface::socket_bind(void *handle, const SocketAddress &address) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +int ISM43362Interface::socket_listen(void *handle, int backlog) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +int ISM43362Interface::socket_connect(void *handle, const SocketAddress &addr) +{ + _mutex.lock(); + int ret = socket_connect_nolock(handle, addr); + _mutex.unlock(); + return ret; +} + +int ISM43362Interface::socket_connect_nolock(void *handle, const SocketAddress &addr) +{ + struct ISM43362_socket *socket = (struct ISM43362_socket *)handle; + const char *proto = (socket->proto == NSAPI_UDP) ? "1" : "0"; + if (!_ism.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) { + return NSAPI_ERROR_DEVICE_ERROR; + } + _ids[socket->id] = true; + _socket_obj[socket->id] = (uint32_t)socket; + socket->connected = true; + return 0; + +} + + + +void ISM43362Interface::socket_check_read() +{ + while (1) { + for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) { + _mutex.lock(); + if (_socket_obj[i] != 0) { + struct ISM43362_socket *socket = (struct ISM43362_socket *)_socket_obj[i]; + /* Check if there is something to read for this socket. But if it */ + /* has already been read : don't read again */ + if ((socket->connected) && (socket->read_data_size == 0) && _cbs[socket->id].callback) { + /* if no callback is set, no need to read ?*/ + int read_amount = _ism.check_recv_status(socket->id, socket->read_data); + // debug_if(_ism_debug, "ISM43362Interface socket_check_read: i %d read_amount %d \r\n", i, read_amount); + if (read_amount > 0) { + socket->read_data_size = read_amount; + } else if (read_amount < 0) { + /* Mark donw connection has been lost or closed */ + debug_if(_ism_debug, "ISM43362Interface socket_check_read: i %d closed\r\n", i, read_amount); + socket->connected = false; + } + if (read_amount != 0) { + /* There is something to read in this socket*/ + if (_cbs[socket->id].callback) { + _cbs[socket->id].callback(_cbs[socket->id].data); + } + } + } + } + _mutex.unlock(); + } + wait_ms(50); + } +} + +int ISM43362Interface::socket_accept(void *server, void **socket, SocketAddress *addr) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +int ISM43362Interface::socket_send(void *handle, const void *data, unsigned size) +{ + _mutex.lock(); + int ret = socket_send_nolock(handle, data, size); + _mutex.unlock(); + return ret; +} + +/* CAREFULL LOCK must be taken before callling this function */ +int ISM43362Interface::socket_send_nolock(void *handle, const void *data, unsigned size) +{ + struct ISM43362_socket *socket = (struct ISM43362_socket *)handle; + + if (size > ES_WIFI_MAX_TX_PACKET_SIZE) { + size = ES_WIFI_MAX_TX_PACKET_SIZE; + } + + if (!_ism.send(socket->id, data, size)) { + debug_if(_ism_debug, "ISM43362Interface: socket_send ERROR\r\n"); + return NSAPI_ERROR_DEVICE_ERROR; // or WOULD_BLOCK ? + } + + return size; +} + +int ISM43362Interface::socket_recv(void *handle, void *data, unsigned size) +{ + _mutex.lock(); + unsigned recv = 0; + struct ISM43362_socket *socket = (struct ISM43362_socket *)handle; + char *ptr = (char *)data; + + // debug_if(_ism_debug, "ISM43362Interface socket_recv: req=%d read_data_size=%d connected %d\r\n", size, socket->read_data_size, socket->connected); + + if (!socket->connected) { + _mutex.unlock(); + return NSAPI_ERROR_CONNECTION_LOST; + } + + if (socket->read_data_size == 0) { + /* if no callback is set, no need to read ?*/ + int read_amount = _ism.check_recv_status(socket->id, socket->read_data); + if (read_amount > 0) { + socket->read_data_size = read_amount; + } else if (read_amount < 0) { + socket->connected = false; + debug_if(_ism_debug, "ISM43362Interface socket_recv: socket closed\r\n"); + _mutex.unlock(); + return NSAPI_ERROR_CONNECTION_LOST; + } + } + + if (socket->read_data_size != 0) { + // debug_if(_ism_debug, "ISM43362Interface socket_recv: read_data_size=%d\r\n", socket->read_data_size); + uint32_t i = 0; + while ((i < socket->read_data_size) && (i < size)) { + *ptr++ = socket->read_data[i]; + i++; + } + + recv += i; + + if (i >= socket->read_data_size) { + /* All the storeed data has been read, reset buffer */ + memset(socket->read_data, 0, sizeof(socket->read_data)); + socket->read_data_size = 0; + // debug_if(_ism_debug, "ISM43362Interface: Socket_recv buffer reset\r\n"); + } else { + /* In case there is remaining data in buffer, update socket content + * For now by shift copy of all data (not very efficient to be + * revised */ + while (i < socket->read_data_size) { + socket->read_data[i - size] = socket->read_data[i]; + i++; + } + + socket->read_data_size -= size; + } + } + // else { + // debug_if(_ism_debug, "ISM43362Interface socket_recv: Nothing in buffer\r\n"); + // } + + _mutex.unlock(); + + if (recv > 0) { + debug_if(_ism_debug, "ISM43362Interface socket_recv: recv=%d\r\n", recv); + return recv; + } else { + debug_if(_ism_debug, "ISM43362Interface socket_recv: returns WOULD BLOCK\r\n"); + return NSAPI_ERROR_WOULD_BLOCK; + } +} + +int ISM43362Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size) +{ + _mutex.lock(); + struct ISM43362_socket *socket = (struct ISM43362_socket *)handle; + + if (socket->connected && socket->addr != addr) { + if (!_ism.close(socket->id)) { + debug_if(_ism_debug, "ISM43362Interface: socket_sendto ERROR\r\n"); + _mutex.unlock(); + return NSAPI_ERROR_DEVICE_ERROR; + } + socket->connected = false; + _ids[socket->id] = false; + _socket_obj[socket->id] = 0; + } + + if (!socket->connected) { + int err = socket_connect_nolock(socket, addr); + if (err < 0) { + _mutex.unlock(); + return err; + } + socket->addr = addr; + } + + int ret = socket_send_nolock(socket, data, size); + + _mutex.unlock(); + + return ret; +} + +int ISM43362Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size) +{ + int ret = socket_recv(handle, data, size); + _mutex.lock(); + if ((ret >= 0) && addr) { + struct ISM43362_socket *socket = (struct ISM43362_socket *)handle; + *addr = socket->addr; + } + _mutex.unlock(); + return ret; +} + +void ISM43362Interface::socket_attach(void *handle, void (*cb)(void *), void *data) +{ + _mutex.lock(); + struct ISM43362_socket *socket = (struct ISM43362_socket *)handle; + _cbs[socket->id].callback = cb; + _cbs[socket->id].data = data; + _mutex.unlock(); +} + +void ISM43362Interface::event() +{ + for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) { + if (_cbs[i].callback) { + _cbs[i].callback(_cbs[i].data); + } + } +} + +#if MBED_CONF_ISM43362_PROVIDE_DEFAULT + +WiFiInterface *WiFiInterface::get_default_instance() { + static ISM43362Interface ism; + return &ism; +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/ISM43362Interface.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,298 @@ +/* ISM43362 implementation of NetworkInterfaceAPI + * Copyright (c) STMicroelectronics 2017 + * + * 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 ISM43362_INTERFACE_H +#define ISM43362_INTERFACE_H + +#include "mbed.h" +#include "ISM43362.h" + + +#define ISM43362_SOCKET_COUNT 4 + +/** ISM43362Interface class + * Implementation of the NetworkStack for the ISM43362 + */ +class ISM43362Interface : public NetworkStack, public WiFiInterface +{ +public: + /** ISM43362Interface lifetime + * @param debug Enable debugging + */ + ISM43362Interface(bool debug = MBED_CONF_ISM43362_WIFI_DEBUG); + + /** 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); + + /** 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. + * + * + * @param host Hostname to resolve + * @param address Destination for the host SocketAddress + * @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 + */ + virtual nsapi_error_t gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC); + + /** 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 + * @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: + ISM43362 _ism; + bool _ids[ISM43362_SOCKET_COUNT]; + uint32_t _socket_obj[ISM43362_SOCKET_COUNT]; // store addresses of socket handles + Mutex _mutex; + Thread thread_read_socket; + char ap_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */ + ism_security_t ap_sec; + uint8_t ap_ch; + char ap_pass[64]; /* The longest allowed passphrase */ + + bool _ism_debug; + uint32_t _FwVersion; + + void event(); + struct { + void (*callback)(void *); + void *data; + } _cbs[ISM43362_SOCKET_COUNT]; + + /** Function called by the socket read thread to check if data is available on the wifi module + * + */ + virtual void socket_check_read(); + int socket_send_nolock(void *handle, const void *data, unsigned size); + int socket_connect_nolock(void *handle, const SocketAddress &addr); + +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/README.md Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,50 @@ +# ISM43362 WiFi driver for mbed-os + +The mbed OS driver for the ISM43362 WiFi module + +https://www.inventeksys.com/products-page/wifi-modules/ism4336-m3g-l44-e-embedded-serial-to-wifi-module/ + + +## Currently supported platforms + +ISM43362 module is soldered on the following platforms from STMicroelectronics + + * [DISCO_L475VG_IOT01A](https://os.mbed.com/platforms/ST-Discovery-L475E-IOT01A/) + * [DISCO_F413ZH](https://os.mbed.com/platforms/ST-Discovery-F413H/) + +## Configuration + +Correct pins have already been configured for both supported platforms. + +Here is configured pins: + +- MBED_CONF_ISM43362_WIFI_MISO : spi-miso pin for the ism43362 connection +- MBED_CONF_ISM43362_WIFI_MOSI : spi-mosi pin for the ism43362 connection +- MBED_CONF_ISM43362_WIFI_SPI_SCLK : spi-clock pin for the ism43362 connection +- MBED_CONF_ISM43362_WIFI_SPI_NSS : spi-nss pin for the ism43362 connection +- MBED_CONF_ISM43362_WIFI_RESET : Reset pin for the ism43362 wifi module +- MBED_CONF_ISM43362_WIFI_DATAREADY : Data Ready pin for the ism43362 wifi module +- MBED_CONF_ISM43362_WIFI_WAKEUP : Wakeup pin for the ism43362 wifi module + +## Debug + +Some debug print on console can help to debug if necessary. + +- in ISM43362Interface.cpp file, set ism_interface_debug to 1 +- in ISM43362/ISM43362.cpp file, set ism_debug to 1 +- in ISM43362/ATParser/ATParser.cpp file, there are 3 different level : dbg_on / AT_DATA_PRINT / AT_COMMAND_PRINT + +Another way to enable these prints is overwrite MBED_CONF_ISM43362_WIFI_DEBUG in your json file: + "ism43362.wifi-debug": true + + +## Firmware version + +This driver has been tested with C3.5.2.2 and C3.5.2.3.BETA9 firmware version + +## wifi module FW update + +Only Wifi module from DISCO_L475VG_IOT01A can be updated (HW limitation for DISCO_F413ZH). + +For more information about the wifi FW version, refer to the detailed procedure in +http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software-expansion/x-cube-azure.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-ism43362/mbed_lib.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,63 @@ +{ + "name": "ism43362", + "config": { + "wifi-miso": { + "help": "SPI-MISO connection to external device", + "value": "NC" + }, + "wifi-mosi": { + "help": "SPI-MOSI connection to external device", + "value": "NC" + }, + "wifi-sclk": { + "help": "SPI-CLOCK connection to external device", + "value": "NC" + }, + "wifi-nss": { + "help": "SPI chip select of external device", + "value": "NC" + }, + "wifi-reset": { + "help": "ISM43362 reset", + "value": "NC" + }, + "wifi-dataready": { + "help": "ISM43362 dataready", + "value": "NC" + }, + "wifi-wakeup": { + "help": "ISM43362 wakeup", + "value": "NC" + }, + "wifi-debug": { + "help": "Defines whether logging is on or off", + "value": false + }, + "provide-default": { + "help": "Provide default WifiInterface. [true/false]", + "value": false + } + }, + "target_overrides": { + "DISCO_F413ZH": { + "ism43362.wifi-miso": "PB_4", + "ism43362.wifi-mosi": "PB_5", + "ism43362.wifi-sclk": "PB_12", + "ism43362.wifi-nss": "PG_11", + "ism43362.wifi-reset": "PH_1", + "ism43362.wifi-dataready": "PG_12", + "ism43362.wifi-wakeup": "PB_15", + "ism43362.provide-default": true + }, + "DISCO_L475VG_IOT01A": { + "ism43362.wifi-miso": "PC_11", + "ism43362.wifi-mosi": "PC_12", + "ism43362.wifi-sclk": "PC_10", + "ism43362.wifi-nss": "PE_0", + "ism43362.wifi-reset": "PE_8", + "ism43362.wifi-dataready": "PE_1", + "ism43362.wifi-wakeup": "PB_13", + "ism43362.provide-default": true + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/#b28712c890b73be18884cd323aa884310cf85e3b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/FETCH_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +b28712c890b73be18884cd323aa884310cf85e3b branch 'master' of https://github.com/ARMmbed/wifi-x-nucleo-idw01m1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/ORIG_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +b28712c890b73be18884cd323aa884310cf85e3b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/config Wed Sep 05 14:28:24 2018 +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/wifi-x-nucleo-idw01m1/ +[branch "master"] + remote = origin + merge = refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/wifi-x-nucleo-idw01m1/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/info/exclude Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 b28712c890b73be18884cd323aa884310cf85e3b www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504028 +0000 clone: from https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/ +b28712c890b73be18884cd323aa884310cf85e3b b28712c890b73be18884cd323aa884310cf85e3b www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504029 +0000 checkout: moving from master to b28712c890b73be18884cd323aa884310cf85e3b +b28712c890b73be18884cd323aa884310cf85e3b b28712c890b73be18884cd323aa884310cf85e3b www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504029 +0000 checkout: moving from b28712c890b73be18884cd323aa884310cf85e3b to master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 b28712c890b73be18884cd323aa884310cf85e3b www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504028 +0000 clone: from https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 b28712c890b73be18884cd323aa884310cf85e3b www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504028 +0000 clone: from https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/
Binary file easy-connect/wifi-x-nucleo-idw01m1/.git/objects/pack/pack-4ea3e0be59e8a7dee78f0864181543eafe0344c7.idx has changed
Binary file easy-connect/wifi-x-nucleo-idw01m1/.git/objects/pack/pack-4ea3e0be59e8a7dee78f0864181543eafe0344c7.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,40 @@ +# pack-refs with: peeled +b28712c890b73be18884cd323aa884310cf85e3b refs/remotes/origin/master +f7c2b16169949700bb3a506600203c7ea7b19483 refs/tags/release_v0.0.0 +ee306fa5f5edeceae145e6ea05b00d62c72712da refs/tags/release_v0.1.0 +d88bd648020b8cfbfed69d848380105540af0ab6 refs/tags/release_v0.1.1 +a9bc601856a3c5fc43e553907ba5355e03ec0a44 refs/tags/release_v0.1.2 +e31ca1f09ba24461d343d6233ebb4df3701aa974 refs/tags/release_v0.1.3 +ce9afc1b796f64be94a8c51919259a8531f2c388 refs/tags/release_v0.2.0 +7d74d5822be0e48d704f94b61db01095acef5276 refs/tags/release_v0.2.1 +6ce14f1f186e844e452a090fc93f2955ffa30ced refs/tags/release_v0.3.0 +5831f72291b7bb5b9789dd0bf623069df86819ab refs/tags/release_v0.3.1 +f28c51f3e8e44211674a7d5c7409fa08b62e956a refs/tags/release_v0.3.2 +82ed479b9a5650b5bcb354aab34bc510741d3a76 refs/tags/release_v1.0.0-rc1 +cefb1b79ad088442c523a72385ab9c179e30848e refs/tags/release_v1.0.0-rc2 +0d182c111485d34d53ad4580e289d8bc44d6d454 refs/tags/release_v1.0.0-rc3 +5dd2b7d994c8461f550e85a40106151498fb6006 refs/tags/release_v1.0.0-rc4 +f7c2b16169949700bb3a506600203c7ea7b19483 refs/tags/v0.0.0 +ee306fa5f5edeceae145e6ea05b00d62c72712da refs/tags/v0.1.0 +d88bd648020b8cfbfed69d848380105540af0ab6 refs/tags/v0.1.1 +a9bc601856a3c5fc43e553907ba5355e03ec0a44 refs/tags/v0.1.2 +e31ca1f09ba24461d343d6233ebb4df3701aa974 refs/tags/v0.1.3 +ce9afc1b796f64be94a8c51919259a8531f2c388 refs/tags/v0.2.0 +7d74d5822be0e48d704f94b61db01095acef5276 refs/tags/v0.2.1 +6ce14f1f186e844e452a090fc93f2955ffa30ced refs/tags/v0.3.0 +5831f72291b7bb5b9789dd0bf623069df86819ab refs/tags/v0.3.1 +f28c51f3e8e44211674a7d5c7409fa08b62e956a refs/tags/v0.3.2 +82ed479b9a5650b5bcb354aab34bc510741d3a76 refs/tags/v0.4.0 +cefb1b79ad088442c523a72385ab9c179e30848e refs/tags/v0.4.1 +0d182c111485d34d53ad4580e289d8bc44d6d454 refs/tags/v0.4.2 +5dd2b7d994c8461f550e85a40106151498fb6006 refs/tags/v0.4.3 +8c3a3fbbdc3d8e604127f6d06645d93f691a592a refs/tags/v1.0.0 +974ecf7ac236db300e30981f2e00b802007795b7 refs/tags/v1.1.0 +d24c1a0d24fb9c640ffd80a82c5a132adb28a277 refs/tags/v1.1.1 +e567dffd5831f7635465b8022105995296f78ef2 refs/tags/v1.1.2 +8877938af9c1b01ea777e42a5b74f75eef26f362 refs/tags/v1.1.3 +b1c6d9284db969b3c140affba2afb991d754e5e0 refs/tags/v1.1.4 +15026eca242707d8c1f65da4d9b1b1d4fa4c7161 refs/tags/v1.1.5 +35fc005f6fc60dedff4728e77d5a697408689aeb refs/tags/v1.1.6 +8482339d91b028dfa048528dc3c50bb7b0789968 refs/tags/v1.1.7 +b8348c58a9e6f80263f43219c56f90b81d8717cc refs/tags/v1.1.8
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +b28712c890b73be18884cd323aa884310cf85e3b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.gitignore Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +BUILD +TESTS +.mbed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<root> + <node _type="integer" _key="update">0</node> + <node _type="string" _key="repo_docs"></node> + <node _type="string" _key="repo_docs_id">https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/#b28712c890b73be18884cd323aa884310cf85e3b</node> + <node _type="string" _key="repo_docs_ts"></node> + <node _type="NULL" _key="workspace_docs"></node> + <node _type="NULL" _key="workspace_docs_ts"></node> + <node _type="NULL" _key="workspace_docs_sync_id"></node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/BlockExecuter.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,22 @@ +#ifndef BLOCK_EXEC_H +#define BLOCK_EXEC_H + +#include "mbed.h" + +/* Helper class to execute something whenever entering/leaving a basic block */ +class BlockExecuter { +public: + BlockExecuter(Callback<void()> exit_cb, Callback<void()> enter_cb = Callback<void()>()) : + _exit_cb(exit_cb) { + if((bool)enter_cb) enter_cb(); + } + + ~BlockExecuter(void) { + _exit_cb(); + } + +private: + Callback<void()> _exit_cb; +}; + +#endif //BLOCK_EXEC_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/README.md Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,68 @@ +# Prototype Driver for STM Wi-Fi Expansion Boards based on the SPWFxx Module for STM32 Nucleo # + +## Currently supported expansion boards + * [X-NUCLEO-IDW01M1](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-connect-hw/x-nucleo-idw01m1.html), by setting `mbed` configuration variable `idw0xx1.expansion-board` to value `IDW01M1` + * [X-NUCLEO-IDW04A1](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-connect-hw/x-nucleo-idw04a1.html), by setting `mbed` configuration variable `idw0xx1.expansion-board` to value `IDW04A1`. You might also need to define macro `IDW04A1_WIFI_HW_BUG_WA` _(see beyond)_. + +## Configuration examples + +### Generic concepts + +For the ones, which might be less familiar with the **"The mbed configuration system"** in general, here is a [link](https://docs.mbed.com/docs/mbed-os-handbook/en/latest/advanced/config_system/) which points to the latest version of the respective _mbed OS 5 handbook tutorial_. + +Furthermore, with respect to this driver, pls. refer to files [`mbed_app_idw01m1.json`](https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/blob/master/mbed_app_idw01m1.json) and [`mbed_app_idw04a1.json`](https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/blob/master/mbed_app_idw04a1.json) regarding additional reference for what is explained beyond. + +### IDW01M1 + +Add the following lines to the `target_overrides`-section of your `mbed_app.json` file. + +``` json + "idw0xx1.expansion-board": "IDW01M1", + "drivers.uart-serial-txbuf-size": 512, + "drivers.uart-serial-rxbuf-size": 512 +``` + +`IDW01M1` is the default value in the [`mbed_lib.json`](https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/blob/master/mbed_lib.json) file, so setting the expansion board is not mandatory for `IDW01M1`, while setting the TX & RX buffer sizes is highly recommended. + +### IDW04A1 + +Add the following lines to the `target_overrides`-section of your `mbed_app.json` file. + +``` json + "idw0xx1.expansion-board": "IDW04A1", + "drivers.uart-serial-txbuf-size": 512, + "drivers.uart-serial-rxbuf-size": 512 +``` + +### Further configuration macros + +All configuration options mentioned in this section are optional and when required have to be added to the `macros`-section of your `mbed_app.json` file, e.g.: + +``` json + "macros": [..., "IDW04A1_WIFI_HW_BUG_WA", "SPWFSAXX_RESET_PIN=D7"] +``` + +Beyond you can find the list of available configuration macros each with a short explanation: + * `IDW04A1_WIFI_HW_BUG_WA`: activates the HW bug workaround for `IDW04A1` + * `SPWFSAXX_WAKEUP_PIN`: defines module wakeup pin _(requires value)_ + * `SPWFSAXX_RESET_PIN`: defines module reset pin _(requires value)_ + * `SPWFSAXX_RTS_PIN`: defines RTS pin of the UART device used _(requires value)_ + * `SPWFSAXX_CTS_PIN`: defines CTS pin of the UART device used _(requires value)_ + +**Note**: if the values of both `SPWFSAXX_RTS_PIN` and `SPWFSAXX_CTS_PIN` are different from `NC`, hardware flow control - if available on your development board - will be enabled on the used UART device (provided you are using `mbed-os` version greater than or equal to `v5.7.0`). + + +## Firmware upgrade + +Please make sure that you are using the latest firmware available for the expansion boards. For information on how to perform a FW upgrade you may refer to [X-CUBE-WIFI1](http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software-expansion/x-cube-wifi1.html), especially to document **"X-NUCLEO-IDW0xx1- FW upgrading over UART_v1.2.pdf"** which is contained within folder **"Documentation"** of the X-CUBE-WIFI1 software archive you need to download. + +The actual firmware `.bin` or `.hex` files can be found under +- [STSW-WIFI001](http://www.st.com/content/st_com/en/products/embedded-software/wireless-connectivity-software/stsw-wifi001.html) _for what concerns expansion board_ X-NUCLEO-IDW01M1 _and under_ +- [STSW-WIFI004](http://www.st.com/content/st_com/en/products/embedded-software/wireless-connectivity-software/stsw-wifi004.html) _when considering_ X-NUCLEO-IDW04A1. + + +## Known limitations + + * Like explained in issue [#11](https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/issues/11), sockets might fail to close in case they are connected to a streaming server (e.g. a [RFC 864](https://tools.ietf.org/html/rfc864) test server). + * As highlighted by issue [#13](https://github.com/ARMmbed/wifi-x-nucleo-idw01m1/issues/13), the module FW limits the maximum segment size for TCP to 730 bytes, while the maximum UDP datagram length might even be further limited (but usually is also equal to 730 bytes). + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SPWFSA01/SPWFSA01.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,284 @@ +/* SPWFSA01 Device + * 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 "SPWFSA01.h" +#include "SpwfSAInterface.h" +#include "mbed_debug.h" + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW01M1 + +SPWFSA01::SPWFSA01(PinName tx, PinName rx, + PinName rts, PinName cts, + SpwfSAInterface &ifce, bool debug, + PinName wakeup, PinName reset) +: SPWFSAxx(tx, rx, rts, cts, ifce, debug, wakeup, reset) { +} + +bool SPWFSA01::open(const char *type, int* spwf_id, const char* addr, int port) +{ + int socket_id; + int value; + int trials; + + if(!_parser.send("AT+S.SOCKON=%s,%d,%s,ind", addr, port, type)) + { + debug_if(_dbg_on, "\r\nSPWF> `SPWFSA01::open`: error opening socket (%d)\r\n", __LINE__); + return false; + } + + /* handle both response possibilities here before returning + * otherwise module seems to remain in inconsistent state. + */ + + /* wait for first character */ + trials = 0; + while((value = _parser.getc()) < 0) { + if(trials++ > SPWFXX_MAX_TRIALS) { + debug("\r\nSPWF> error opening socket (%d)\r\n", __LINE__); + empty_rx_buffer(); + return false; + } + } + + if(value != _cr_) { // Note: this is different to what the spec exactly says + debug_if(_dbg_on, "\r\nSPWF> error opening socket (%d)\r\n", __LINE__); + empty_rx_buffer(); + return false; + } + + if(!_recv_delim_lf()) { // Note: this is different to what the spec exactly says + debug_if(_dbg_on, "\r\nSPWF> error opening socket (%d)\r\n", __LINE__); + empty_rx_buffer(); + return false; + } + + value = _parser.getc(); + switch(value) { + case ' ': + if(_parser.recv("ID: %d\n", &socket_id) + && _recv_ok()) { + debug_if(_dbg_on, "AT^ ID: %d\r\n", socket_id); + + *spwf_id = socket_id; + return true; + } else { + empty_rx_buffer(); + } + break; + case 'E': + if(_parser.recv("RROR: %255[^\n]\n", _msg_buffer) && _recv_delim_lf()) { + debug_if(_dbg_on, "AT^ ERROR: %s (%d)\r\n", _msg_buffer, __LINE__); + } else { + debug_if(_dbg_on, "\r\nSPWF> error opening socket (%d)\r\n", __LINE__); + empty_rx_buffer(); + } + break; + default: + debug_if(_dbg_on, "\r\nSPWF> error opening socket (value=%d, %d)\r\n", value, __LINE__); + break; + } + + return false; +} + +int SPWFSA01::_read_in(char* buffer, int spwf_id, uint32_t amount) { + int ret = -1; + + MBED_ASSERT(buffer != NULL); + + /* block asynchronous indications */ + if(!_winds_off()) { + return -1; + } + + /* read in data */ + if(_parser.send("AT+S.SOCKR=%d,%u", spwf_id, (unsigned int)amount)) { + /* set high timeout */ + _parser.set_timeout(SPWF_READ_BIN_TIMEOUT); + /* read in binary data */ + int read = _parser.read(buffer, amount); + /* reset timeout value */ + _parser.set_timeout(_timeout); + if(read > 0) { + if(_recv_ok()) { + ret = amount; + + /* remove from pending sizes + * (MUST be done before next async indications handling (e.g. `_winds_on()`)) */ + _remove_pending_pkt_size(spwf_id, amount); + } else { + debug_if(_dbg_on, "\r\nSPWF> failed to receive OK (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + } + } else { + debug_if(_dbg_on, "\r\nSPWF> failed to read binary data (%u:%d), (%s, %d)\r\n", amount, read, __func__, __LINE__); + empty_rx_buffer(); + } + } else { + debug_if(_dbg_on, "\r\nSPWF> failed to send SOCKR (%s, %d)\r\n", __func__, __LINE__); + } + + debug_if(_dbg_on, "\r\nSPWF> %s():\t%d:%d\r\n", __func__, spwf_id, amount); + + /* unblock asynchronous indications */ + _winds_on(); + + return ret; +} + +/* betzw - TODO: improve performance! */ +bool SPWFSA01::_recv_ap(nsapi_wifi_ap_t *ap) +{ + bool ret; + unsigned int channel; + int trials; + + ap->security = NSAPI_SECURITY_UNKNOWN; + + /* check for end of list */ + if(_recv_delim_cr_lf()) { + return false; + } + + /* run to 'horizontal tab' */ + trials = 0; + while(_parser.getc() != '\x09') { + if(trials++ > SPWFXX_MAX_TRIALS) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + return false; + } + } + + /* read in next line */ + ret = _parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf(); + + /* parse line - first phase */ + if(ret) { + int val = sscanf(_msg_buffer, + " %*s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx CHAN: %u RSSI: %hhd SSID: \'%*255[^\']\'", + &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5], + &channel, &ap->rssi); + if(val < 8) { + ret = false; + } + } + + /* parse line - second phase */ + if(ret) { // ret == true + char value; + char *rest, *first, *last; + + /* decide about position of `CAPS:` */ + first = strchr(_msg_buffer, '\''); + if(first == NULL) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + return false; + } + last = strrchr(_msg_buffer, '\''); + if((last == NULL) || (last < (first+1))) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + return false; + } + rest = strstr(last, "CAPS:"); + if(rest == NULL) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + return false; + } + + /* substitute '\'' with '\0' */ + *last = '\0'; + + /* copy values */ + memcpy(&ap->ssid, first+1, sizeof(ap->ssid)-1); + ap->ssid[sizeof(ap->ssid)-1] = '\0'; + ap->channel = channel; + + /* skip `CAPS: 0421 ` */ + if(strlen(rest) < 11) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + return false; + } + rest += 11; + + /* get next character */ + value = *rest++; + if(value != 'W') { // no security + ap->security = NSAPI_SECURITY_NONE; + return true; + } + + /* determine security */ + { + char buffer[10]; + + if(!(sscanf(rest, "%s%*[\x20]", (char*)&buffer) > 0)) { // '\0x20' == <space> + return true; + } else if(strncmp("EP", buffer, 10) == 0) { + ap->security = NSAPI_SECURITY_WEP; + return true; + } else if(strncmp("PA2", buffer, 10) == 0) { + ap->security = NSAPI_SECURITY_WPA2; + return true; + } else if(strncmp("PA", buffer, 10) != 0) { + return true; + } + + /* got a "WPA", check for "WPA2" */ + rest += strlen(buffer); + value = *rest++; + if(value == '\0') { // no further protocol + ap->security = NSAPI_SECURITY_WPA; + return true; + } else { // assume "WPA2" + ap->security = NSAPI_SECURITY_WPA_WPA2; + return true; + } + } + } else { // ret == false + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + } + + return ret; +} + +int SPWFSA01::scan(WiFiAccessPoint *res, unsigned limit) +{ + unsigned cnt = 0; + nsapi_wifi_ap_t ap; + + if (!_parser.send("AT+S.SCAN=a,s")) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + while (_recv_ap(&ap)) { + if (cnt < limit) { + res[cnt] = WiFiAccessPoint(ap); + } + + cnt++; + if (limit != 0 && cnt >= limit) { + break; + } + } + + if(!_recv_ok()) { + empty_rx_buffer(); + } + + return cnt; +} + +#endif // MBED_CONF_IDW0XX1_EXPANSION_BOARD
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SPWFSA01/SPWFSA01.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,66 @@ +/* SPWFSA01 Device + * 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 SPWFSA01_H +#define SPWFSA01_H + +#include "mbed.h" +#include "ATCmdParser.h" +#include "BlockExecuter.h" + +#include "./spwfsa01_at_strings.h" +#include "../SPWFSAxx.h" + +class SpwfSAInterface; + +/** SPWFSA01 Interface class. + This is an interface to a SPWFSA01 module. + */ +class SPWFSA01 : public SPWFSAxx +{ +public: + SPWFSA01(PinName tx, PinName rx, + PinName rts, PinName cts, + SpwfSAInterface &ifce, bool debug, + PinName wakeup, PinName reset); + + /** + * Open a socketed connection + * + * @param type the type of socket to open "u" (UDP) or "t" (TCP) + * @param id id to get the new socket number, valid 0-7 + * @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); + + /** 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 + */ + nsapi_size_or_error_t scan(WiFiAccessPoint *res, unsigned limit); + +private: + bool _recv_ap(nsapi_wifi_ap_t *ap); + + virtual int _read_in(char*, int, uint32_t); +}; + +#endif // SPWFSA01_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SPWFSA01/spwfsa01_at_strings.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,58 @@ +#ifndef SPWFSAXX_AT_STRINGS_H +#define SPWFSAXX_AT_STRINGS_H + +#if defined(TARGET_FF_MORPHO) + +#if !defined(SPWFSAXX_WAKEUP_PIN) +#define SPWFSAXX_WAKEUP_PIN PC_8 // A3 +#endif // !defined(SPWFSAXX_WAKEUP_PIN) +#if !defined(SPWFSAXX_RESET_PIN) +#define SPWFSAXX_RESET_PIN PC_12 // D7 / NC +#endif // !defined(SPWFSAXX_RESET_PIN) + +#else // !defined(TARGET_FF_MORPHO) + +#if !defined(SPWFSAXX_WAKEUP_PIN) +#define SPWFSAXX_WAKEUP_PIN NC // A3 +#endif // !defined(SPWFSAXX_WAKEUP_PIN) +#if !defined(SPWFSAXX_RESET_PIN) +#define SPWFSAXX_RESET_PIN NC // D7 / NC +#endif // !defined(SPWFSAXX_RESET_PIN) + +#endif // !defined(TARGET_FF_MORPHO) + +#define SPWFXX_SEND_RECV_PKTSIZE (730) + +#define SPWFXX_OOB_ERROR "ERROR:" // "AT-S.ERROR:" + +#define SPWFXX_RECV_OK "OK\n" // "AT-S.OK\n" +#define SPWFXX_RECV_WIFI_UP "+WIND:24:WiFi Up:%u.%u.%u.%u\n" // "+WIND:24:WiFi Up:%*u:%u.%u.%u.%u\n" +#define SPWFXX_RECV_IP_ADDR "# ip_ipaddr = %u.%u.%u.%u\n" // "AT-S.Var:ip_ipaddr=%u.%u.%u.%u\n" +#define SPWFXX_RECV_GATEWAY "# ip_gw = %u.%u.%u.%u\n" // "AT-S.Var:ip_gw=%u.%u.%u.%u\n" +#define SPWFXX_RECV_NETMASK "# ip_netmask = %u.%u.%u.%u\n" // "AT-S.Var:ip_netmask=%u.%u.%u.%u\n" +#define SPWFXX_RECV_RX_RSSI "# 0.rx_rssi = %d\n" // "AT-S.Var:0.rx_rssi=%d\n" +#define SPWFXX_RECV_MAC_ADDR "# nv_wifi_macaddr = %x:%x:%x:%x:%x:%x\n" // "AT-S.Var:nv_wifi_macaddr=%x:%x:%x:%x:%x:%x\n" +#define SPWFXX_RECV_DATALEN " DATALEN: %u\n" // "AT-S.Query:%u\n" +#define SPWFXX_RECV_PENDING_DATA ":%d:%d\n" // "::%u:%*u:%u\n" +#define SPWFXX_RECV_SOCKET_CLOSED ":%d\n" // ":%u:%*u\n" + +#define SPWFXX_SEND_FWCFG "AT&F" // "AT+S.FCFG" +#define SPWFXX_SEND_DISABLE_LE "AT+S.SCFG=localecho1,0" // "AT+S.SCFG=console_echo,0" +#define SPWFXX_SEND_DSPLY_CFGV "AT&V" // "AT+S.GCFG" +#define SPWFXX_SEND_GET_CONS_STATE "AT+S.GCFG=console1_enabled" // "AT+S.GCFG=console_enabled" +#define SPWFXX_SEND_GET_CONS_SPEED "AT+S.GCFG=console1_speed" // "AT+S.GCFG=console_speed" +#define SPWFXX_SEND_GET_HWFC_STATE "AT+S.GCFG=console1_hwfc" // "AT+S.GCFG=console_hwfc" +#define SPWFXX_SEND_GET_CONS_DELIM "AT+S.GCFG=console1_delimiter" // "AT+S.GCFG=console_delimiter" +#define SPWFXX_SEND_GET_CONS_ERRS "AT+S.GCFG=console1_errs" // "AT+S.GCFG=console_errs" +#define SPWFXX_SEND_DISABLE_FC "AT+S.SCFG=console1_hwfc,0" // "AT+S.SCFG=console_hwfc,0" +#define SPWFXX_SEND_ENABLE_FC "AT+S.SCFG=console1_hwfc,1" // "AT+S.SCFG=console_hwfc,1" +#define SPWFXX_SEND_SW_RESET "AT+CFUN=1" // "AT+S.RESET" +#define SPWFXX_SEND_SAVE_SETTINGS "AT&W" // "AT+S.WCFG" +#define SPWFXX_SEND_WIND_OFF_HIGH "AT+S.SCFG=wind_off_high," // "AT+S.SCFG=console_wind_off_high," +#define SPWFXX_SEND_WIND_OFF_MEDIUM "AT+S.SCFG=wind_off_medium," // "AT+S.SCFG=console_wind_off_medium," +#define SPWFXX_SEND_WIND_OFF_LOW "AT+S.SCFG=wind_off_low," // "AT+S.SCFG=console_wind_off_low," + +#define SPWFXX_WINDS_HIGH_ON "0x00000000" // "0x00100000" +#define SPWFXX_WINDS_MEDIUM_ON "0x00000000" // "0x80000000" + +#endif // SPWFSAXX_AT_STRINGS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SPWFSA04/SPWFSA04.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,318 @@ +/* SPWFSA04 Device + * 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 "SPWFSA04.h" +#include "SpwfSAInterface.h" +#include "mbed_debug.h" + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 + +SPWFSA04::SPWFSA04(PinName tx, PinName rx, + PinName rts, PinName cts, + SpwfSAInterface &ifce, bool debug, + PinName wakeup, PinName reset) +: SPWFSAxx(tx, rx, rts, cts, ifce, debug, wakeup, reset) { +} + +bool SPWFSA04::open(const char *type, int* spwf_id, const char* addr, int port) +{ + int socket_id; + int value; + int trials; + + if(!_parser.send("AT+S.SOCKON=%s,%d,NULL,%s", addr, port, type)) + { + debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__); + return false; + } + + /* handle both response possibilities here before returning + * otherwise module seems to remain in inconsistent state. + */ + + if(!_parser.recv("AT-S.")) { // get prefix + debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__); + empty_rx_buffer(); + return false; + } + + /* wait for next character */ + trials = 0; + while((value = _parser.getc()) < 0) { + if(++trials >= SPWFXX_MAX_TRIALS) { + debug("\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__); + empty_rx_buffer(); + return false; + } + } + + switch(value) { + case 'O': + /* get next character */ + value = _parser.getc(); + if(value != 'n') { + debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d) (%d, \'%c\')\r\n", + __LINE__, value, value); + empty_rx_buffer(); + return false; + } + + /* get socket id */ + if(!(_parser.recv(":%*u.%*u.%*u.%*u:%d\n", &socket_id) + && _recv_delim_lf() + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__); + empty_rx_buffer(); + return false; + } + debug_if(_dbg_on, "AT^ AT-S.On:%s:%d\r\n", addr, socket_id); + + *spwf_id = socket_id; + return true; + case 'E': + int err_nr; + if(_parser.recv("RROR:%d:%255[^\n]\n", &err_nr, _msg_buffer) && _recv_delim_lf()) { + debug_if(_dbg_on, "AT^ AT-S.ERROR:%d:%s (%d)\r\n", err_nr, _msg_buffer, __LINE__); + } else { + debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d)\r\n", __LINE__); + empty_rx_buffer(); + } + break; + default: + debug_if(_dbg_on, "\r\nSPWF> `SPWFSA04::open`: error opening socket (%d) (%d, \'%c\')\r\n", + __LINE__, value, value); + empty_rx_buffer(); + break; + } + + return false; +} + +int SPWFSA04::_read_in(char* buffer, int spwf_id, uint32_t amount) { + int ret = -1; + int received, cumulative; + + MBED_ASSERT(buffer != NULL); + + /* block asynchronous indications */ + if(!_winds_off()) { + return -1; + } + + /* read in data */ + if(_parser.send("AT+S.SOCKR=%d,%d", spwf_id, (unsigned int)amount)) { + if(!(_parser.recv("AT-S.Reading:%d:%d\n", &received, &cumulative) && + _recv_delim_lf())) { + debug_if(_dbg_on, "\r\nSPWF> failed to receive AT-S.Reading (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + } else { + /* set high timeout */ + _parser.set_timeout(SPWF_READ_BIN_TIMEOUT); + /* read in binary data */ + int read = _parser.read(buffer, amount); + /* reset timeout value */ + _parser.set_timeout(_timeout); + if(read > 0) { + if(_recv_ok()) { + ret = amount; + + /* remove from pending sizes + * (MUST be done before next async indications handling (e.g. `_winds_on()`)) */ + _remove_pending_pkt_size(spwf_id, amount); + } else { + debug_if(_dbg_on, "\r\nSPWF> failed to receive OK (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + } + } else { + debug_if(_dbg_on, "\r\nSPWF> failed to read binary data (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + } + } + } else { + debug_if(_dbg_on, "%s(%d): failed to send SOCKR\r\n", __func__, __LINE__); + } + + debug_if(_dbg_on, "\r\nSPWF> %s():\t%d:%d\r\n", __func__, spwf_id, amount); + + /* unblock asynchronous indications */ + _winds_on(); + + return ret; +} + +/* betzw - TODO: improve performance! */ +bool SPWFSA04::_recv_ap(nsapi_wifi_ap_t *ap) +{ + bool ret; + int curr; + unsigned int channel; + int trials; + + ap->security = NSAPI_SECURITY_UNKNOWN; + + /* determine list end */ + curr = _parser.getc(); + if(curr == 'A') { // assume end of list ("AT-S.OK") + if(!(_parser.recv("T-S.OK\n") && _recv_delim_lf())) { + empty_rx_buffer(); + } + return false; + } + + /* run to 'horizontal tab' */ + trials = 0; + while(_parser.getc() != '\x09') { + if(trials++ > SPWFXX_MAX_TRIALS) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + return false; + } + } + + /* read in next line */ + ret = _parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf(); + + /* parse line - first phase */ + if(ret) { + int val = sscanf(_msg_buffer, + " %*s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx CHAN: %u RSSI: %hhd SSID: \'%*255[^\']\'", + &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4], &ap->bssid[5], + &channel, &ap->rssi); + if(val < 8) { + ret = false; + } + } + + /* parse line - second phase */ + if(ret) { // ret == true + char value; + char *rest, *first, *last; + + /* decide about position of `CAPS:` */ + first = strchr(_msg_buffer, '\''); + if(first == NULL) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + return false; + } + last = strrchr(_msg_buffer, '\''); + if((last == NULL) || (last < (first+1))) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + return false; + } + rest = strstr(last, "CAPS:"); + if(rest == NULL) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + return false; + } + + /* substitute '\'' with '\0' */ + *last = '\0'; + + /* copy values */ + memcpy(&ap->ssid, first+1, sizeof(ap->ssid)-1); + ap->ssid[sizeof(ap->ssid)-1] = '\0'; + ap->channel = channel; + + /* skip `CAPS: 0421 ` */ + if(strlen(rest) < 11) { + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + return false; + } + rest += 11; + + /* get next character */ + value = *rest++; + if(value != 'W') { // no security + ap->security = NSAPI_SECURITY_NONE; + return true; + } + + /* determine security */ + { + char buffer[10]; + + if(!(sscanf(rest, "%s%*[\x20]", (char*)&buffer) > 0)) { // '\0x20' == <space> + return true; + } else if(strncmp("EP", buffer, 10) == 0) { + ap->security = NSAPI_SECURITY_WEP; + return true; + } else if(strncmp("PA2", buffer, 10) == 0) { + ap->security = NSAPI_SECURITY_WPA2; + return true; + } else if(strncmp("PA", buffer, 10) != 0) { + return true; + } + + /* got a "WPA", check for "WPA2" */ + rest += strlen(buffer); + value = *rest++; + if(value == '\0') { // no further protocol + ap->security = NSAPI_SECURITY_WPA; + return true; + } else { // assume "WPA2" + ap->security = NSAPI_SECURITY_WPA_WPA2; + return true; + } + } + } else { // ret == false + debug("\r\nSPWF> WARNING: might happen in case of RX buffer overflow! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + } + + return ret; +} + +nsapi_size_or_error_t SPWFSA04::scan(WiFiAccessPoint *res, unsigned limit) +{ + unsigned int cnt = 0, found; + nsapi_wifi_ap_t ap; + + if (!_parser.send("AT+S.SCAN=s,")) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + if(!(_parser.recv("AT-S.Parsing Networks:%u\n", &found) && _recv_delim_lf())) { + debug_if(_dbg_on, "SPWF> error start network scanning\r\n"); + empty_rx_buffer(); + return NSAPI_ERROR_DEVICE_ERROR; + } + + debug_if(_dbg_on, "AT^ AT-S.Parsing Networks:%u\r\n", found); + + if(found > 0) { + while (_recv_ap(&ap)) { + if (cnt < limit) { + res[cnt] = WiFiAccessPoint(ap); + } + + if (!((limit != 0) && ((cnt + 1) > limit))) { + cnt++; + } + } + } else { + if(!_recv_ok()) { + empty_rx_buffer(); + } + } + + return cnt; +} + +#endif // MBED_CONF_IDW0XX1_EXPANSION_BOARD
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SPWFSA04/SPWFSA04.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,66 @@ +/* SPWFSA04 Device + * 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 SPWFSA04_H +#define SPWFSA04_H + +#include "mbed.h" +#include "ATCmdParser.h" +#include "BlockExecuter.h" + +#include "./spwfsa04_at_strings.h" +#include "../SPWFSAxx.h" + +class SpwfSAInterface; + +/** SPWFSA04 Interface class. + This is an interface to a SPWFSA04 module. + */ +class SPWFSA04 : public SPWFSAxx +{ +public: + SPWFSA04(PinName tx, PinName rx, + PinName rts, PinName cts, + SpwfSAInterface &ifce, bool debug, + PinName wakeup, PinName reset); + + /** + * Open a socketed connection + * + * @param type the type of socket to open "u" (UDP) or "t" (TCP) + * @param id id to get the new socket number, valid 0-7 + * @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); + + /** 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 + */ + nsapi_size_or_error_t scan(WiFiAccessPoint *res, unsigned limit); + +private: + bool _recv_ap(nsapi_wifi_ap_t *ap); + + virtual int _read_in(char*, int, uint32_t); +}; + +#endif // SPWFSA04_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SPWFSA04/spwfsa04_at_strings.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,65 @@ +#ifndef SPWFSAXX_AT_STRINGS_H +#define SPWFSAXX_AT_STRINGS_H + +/* Define beyond macro if your X-NUCLEO-IDW04A1 expansion board has NOT the `WIFI_RST` HW patch applied on it */ +// #define IDW04A1_WIFI_HW_BUG_WA // delegated to mbed config system + +#if defined(TARGET_FF_ARDUINO) + +#if !defined(SPWFSAXX_WAKEUP_PIN) +#define SPWFSAXX_WAKEUP_PIN A3 +#endif +#if !defined(SPWFSAXX_RESET_PIN) +#ifndef IDW04A1_WIFI_HW_BUG_WA +#define SPWFSAXX_RESET_PIN D7 +#else // IDW04A1_WIFI_HW_PATCH +#define SPWFSAXX_RESET_PIN NC +#endif // !IDW04A1_WIFI_HW_PATCH +#endif + +#else // !defined(TARGET_FF_ARDUINO) + +#if !defined(SPWFSAXX_WAKEUP_PIN) +#define SPWFSAXX_WAKEUP_PIN NC +#endif +#if !defined(SPWFSAXX_RESET_PIN) +#define SPWFSAXX_RESET_PIN NC +#endif + +#endif // !defined(TARGET_FF_ARDUINO) + +#define SPWFXX_SEND_RECV_PKTSIZE (730) + +#define SPWFXX_OOB_ERROR "AT-S.ERROR:" // "ERROR:" + +#define SPWFXX_RECV_OK "AT-S.OK\n" // "OK\n" +#define SPWFXX_RECV_WIFI_UP "+WIND:24:WiFi Up:%*u:%u.%u.%u.%u\n" // "+WIND:24:WiFi Up:%u.%u.%u.%u\n" +#define SPWFXX_RECV_IP_ADDR "AT-S.Var:ip_ipaddr=%u.%u.%u.%u\n" // "# ip_ipaddr = %u.%u.%u.%u\n" +#define SPWFXX_RECV_GATEWAY "AT-S.Var:ip_gw=%u.%u.%u.%u\n" // "# ip_gw = %u.%u.%u.%u\n" +#define SPWFXX_RECV_NETMASK "AT-S.Var:ip_netmask=%u.%u.%u.%u\n" // "# ip_netmask = %u.%u.%u.%u\n" +#define SPWFXX_RECV_RX_RSSI "AT-S.Var:0.rx_rssi=%d\n" // "# 0.rx_rssi = %d\n" +#define SPWFXX_RECV_MAC_ADDR "AT-S.Var:nv_wifi_macaddr=%x:%x:%x:%x:%x:%x\n" // "# nv_wifi_macaddr = %x:%x:%x:%x:%x:%x\n" +#define SPWFXX_RECV_DATALEN "AT-S.Query:%u\n" // " DATALEN: %u\n" +#define SPWFXX_RECV_PENDING_DATA "::%u:%*u:%u\n" // ":%d:%d\n" +#define SPWFXX_RECV_SOCKET_CLOSED ":%u:%*u\n" // ":%d\n" + +#define SPWFXX_SEND_FWCFG "AT+S.FCFG" // "AT&F" +#define SPWFXX_SEND_DISABLE_LE "AT+S.SCFG=console_echo,0" // "AT+S.SCFG=localecho1,0" +#define SPWFXX_SEND_DSPLY_CFGV "AT+S.GCFG" // "AT&V" +#define SPWFXX_SEND_GET_CONS_STATE "AT+S.GCFG=console_enabled" // "AT+S.GCFG=console1_enabled" +#define SPWFXX_SEND_GET_CONS_SPEED "AT+S.GCFG=console_speed" // "AT+S.GCFG=console1_speed" +#define SPWFXX_SEND_GET_HWFC_STATE "AT+S.GCFG=console_hwfc" // "AT+S.GCFG=console1_hwfc" +#define SPWFXX_SEND_GET_CONS_DELIM "AT+S.GCFG=console_delimiter" // "AT+S.GCFG=console1_delimiter" +#define SPWFXX_SEND_GET_CONS_ERRS "AT+S.GCFG=console_errs" // "AT+S.GCFG=console1_errs" +#define SPWFXX_SEND_DISABLE_FC "AT+S.SCFG=console_hwfc,0" // "AT+S.SCFG=console1_hwfc,0" +#define SPWFXX_SEND_ENABLE_FC "AT+S.SCFG=console_hwfc,1" // "AT+S.SCFG=console1_hwfc,1" +#define SPWFXX_SEND_SW_RESET "AT+S.RESET" // "AT+CFUN=1" +#define SPWFXX_SEND_SAVE_SETTINGS "AT+S.WCFG" // "AT&W" +#define SPWFXX_SEND_WIND_OFF_HIGH "AT+S.SCFG=console_wind_off_high," // "AT+S.SCFG=wind_off_high," +#define SPWFXX_SEND_WIND_OFF_MEDIUM "AT+S.SCFG=console_wind_off_medium," // "AT+S.SCFG=wind_off_medium," +#define SPWFXX_SEND_WIND_OFF_LOW "AT+S.SCFG=console_wind_off_low," // "AT+S.SCFG=wind_off_low," + +#define SPWFXX_WINDS_HIGH_ON "0x00100000" // "0x00000000" +#define SPWFXX_WINDS_MEDIUM_ON "0x80000000" // "0x00000000" + +#endif // SPWFSAXX_AT_STRINGS_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SPWFSAxx.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1287 @@ +/* SPWFSAxx Devices + * 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 "mbed_debug.h" + +#include "SpwfSAInterface.h" /* must be included first */ +#include "SPWFSAxx.h" + +static const char out_delim[] = {SPWFSAxx::_cr_, '\0'}; + +SPWFSAxx::SPWFSAxx(PinName tx, PinName rx, + PinName rts, PinName cts, + SpwfSAInterface &ifce, bool debug, + PinName wakeup, PinName reset) +: _serial(tx, rx, SPWFXX_DEFAULT_BAUD_RATE), _parser(&_serial, out_delim), + _wakeup(wakeup, 1), _reset(reset, 1), + _rts(rts), _cts(cts), + _timeout(SPWF_INIT_TIMEOUT), _dbg_on(debug), + _pending_sockets_bitmap(0), + _network_lost_flag(false), + _associated_interface(ifce), + _call_event_callback_blocked(0), + _callback_func(), + _packets(0), _packets_end(&_packets) +{ + memset(_pending_pkt_sizes, 0, sizeof(_pending_pkt_sizes)); + + _serial.sigio(Callback<void()>(this, &SPWFSAxx::_event_handler)); + _parser.debug_on(debug); + _parser.set_timeout(_timeout); + + /* unlikely OOBs */ + _parser.oob("+WIND:5:WiFi Hardware Failure", callback(this, &SPWFSAxx::_wifi_hwfault_handler)); + _parser.oob("+WIND:33:WiFi Network Lost", callback(this, &SPWFSAxx::_network_lost_handler_th)); +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 + _parser.oob("+WIND:24:WiFi Up::", callback(this, &SPWFSAxx::_skip_oob)); +#endif + _parser.oob("+WIND:8:Hard Fault", callback(this, &SPWFSAxx::_hard_fault_handler)); + + /* most likely OOBs */ + _parser.oob(SPWFXX_OOB_ERROR, callback(this, &SPWFSAxx::_error_handler)); + _parser.oob("+WIND:58:Socket Closed", callback(this, &SPWFSAxx::_server_gone_handler)); + _parser.oob("+WIND:55:Pending Data", callback(this, &SPWFSAxx::_packet_handler_th)); +} + +bool SPWFSAxx::startup(int mode) +{ + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + /*Reset module*/ + if(!hw_reset()) { + debug_if(_dbg_on, "\r\nSPWF> HW reset failed\r\n"); + return false; + } + + /* factory reset */ + if(!(_parser.send(SPWFXX_SEND_FWCFG) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error restore factory default settings\r\n"); + return false; + } + + /*switch off led*/ + if(!(_parser.send("AT+S.SCFG=blink_led,0") && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error stop blinking led (%d)\r\n", __LINE__); + return false; + } + + /*set local echo to 0*/ + if(!(_parser.send(SPWFXX_SEND_DISABLE_LE) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error local echo set\r\n"); + return false; + } + + /*set the operational rates*/ + if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x003FFFCF") && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error setting ht_mode\r\n"); + return false; + } + + /*enable the 802.11n mode*/ + if(!(_parser.send("AT+S.SCFG=wifi_ht_mode,1") && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error setting operational rates\r\n"); + return false; + } + + /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ + if(!(_parser.send("AT+S.SCFG=wifi_mode,%d", mode) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set idle (%d)\r\n", __LINE__); + return false; + } + +#if defined(MBED_MAJOR_VERSION) +#if !DEVICE_SERIAL_FC || (MBED_VERSION < MBED_ENCODE_VERSION(5, 7, 0)) + /*disable HW flow control*/ + if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n"); + return false; + } +#else // DEVICE_SERIAL_FC && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 7, 0)) + if((_rts != NC) && (_cts != NC)) { + /*enable HW flow control*/ + if(!(_parser.send(SPWFXX_SEND_ENABLE_FC) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error enabling HW flow control\r\n"); + return false; + } + + /*configure pins for HW flow control*/ + _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts); + } else { + /*disable HW flow control*/ + if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n"); + return false; + } + } +#endif // DEVICE_SERIAL_FC && (MBED_VERSION >= MBED_ENCODE_VERSION(5, 7, 0)) +#else // !defined(MBED_MAJOR_VERSION) - Assuming `master` branch +#if !DEVICE_SERIAL_FC + /*disable HW flow control*/ + if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n"); + return false; + } +#else // DEVICE_SERIAL_FC + if((_rts != NC) && (_cts != NC)) { + /*enable HW flow control*/ + if(!(_parser.send(SPWFXX_SEND_ENABLE_FC) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error enabling HW flow control\r\n"); + return false; + } + + /*configure pins for HW flow control*/ + _serial.set_flow_control(SerialBase::RTSCTS, _rts, _cts); + } else { + /*disable HW flow control*/ + if(!(_parser.send(SPWFXX_SEND_DISABLE_FC) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error disabling HW flow control\r\n"); + return false; + } + } +#endif // DEVICE_SERIAL_FC +#endif // !defined(MBED_MAJOR_VERSION) + + /* Disable selected WINDs */ + _winds_on(); + + /* sw reset */ + if(!reset()) { + debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__); + return false; + } + +#ifndef NDEBUG + if (!(_parser.send(SPWFXX_SEND_GET_CONS_STATE) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> error getting console state\r\n"); + return false; + } + + if (!(_parser.send(SPWFXX_SEND_GET_CONS_SPEED) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> error getting console speed\r\n"); + return false; + } + + if (!(_parser.send(SPWFXX_SEND_GET_HWFC_STATE) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> error getting hwfc state\r\n"); + return false; + } + +#if (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) || defined(IDW01M1_FW_REL_35X) + /* betzw: IDW01M1 FW versions <3.5 seem to have problems with the following two commands. + * For the sake of simplicity, just excluding them for IDW01M1 in general. + */ + if (!(_parser.send(SPWFXX_SEND_GET_CONS_DELIM) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> error getting console delimiter\r\n"); + return false; + } + + if (!(_parser.send(SPWFXX_SEND_GET_CONS_ERRS) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> error getting console error setting\r\n"); + return false; + } +#endif // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) || defined(IDW01M1_FW_REL_35X) + + if (!(_parser.send("AT+S.GCFG=sleep_enabled") + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> error getting sleep state enabled\r\n"); + return false; + } + + if (!(_parser.send("AT+S.GCFG=wifi_powersave") + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> error getting powersave mode\r\n"); + return false; + } + + if (!(_parser.send("AT+S.GCFG=standby_enabled") + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> error getting standby state enabled\r\n"); + return false; + } +#endif + + return true; +} + +bool SPWFSAxx::_wait_console_active(void) { + int trials = 0; + + while(true) { + if (_parser.recv("+WIND:0:Console active\n") && _recv_delim_lf()) { + debug_if(_dbg_on, "AT^ +WIND:0:Console active\r\n"); + return true; + } + if(++trials >= SPWFXX_MAX_TRIALS) { + debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + return false; + } + } +} + +bool SPWFSAxx::_wait_wifi_hw_started(void) { + int trials = 0; + + while(true) { + if (_parser.recv("+WIND:32:WiFi Hardware Started\n") && _recv_delim_lf()) { + debug_if(_dbg_on, "AT^ +WIND:32:WiFi Hardware Started\r\n"); + return true; + } + if(++trials >= SPWFXX_MAX_TRIALS) { + debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + return false; + } + } +} + +bool SPWFSAxx::hw_reset(void) +{ +#if (MBED_CONF_IDW0XX1_EXPANSION_BOARD != IDW04A1) || !defined(IDW04A1_WIFI_HW_BUG_WA) // betzw: HW reset doesn't work as expected on unmodified X_NUCLEO_IDW04A1 expansion boards + _reset.write(0); + wait_ms(200); + _reset.write(1); +#else // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) && defined(IDW04A1_WIFI_HW_BUG_WA): substitute with SW reset + _parser.send(SPWFXX_SEND_SW_RESET); +#endif // (MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1) && defined(IDW04A1_WIFI_HW_BUG_WA) + return _wait_console_active(); +} + +bool SPWFSAxx::reset(void) +{ + bool ret; + + /* save current setting in flash */ + if(!(_parser.send(SPWFXX_SEND_SAVE_SETTINGS) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error saving configuration to flash (%s, %d)\r\n", __func__, __LINE__); + return false; + } + + if(!_parser.send(SPWFXX_SEND_SW_RESET)) return false; /* betzw - NOTE: "keep the current state and reset the device". + We assume that the module informs us about the + eventual closing of sockets via "WIND" asynchronous + indications! So everything regarding the clean-up + of these situations is handled there. */ + + /* waiting for HW to start */ + ret = _wait_wifi_hw_started(); + + return ret; +} + +/* Security Mode + None = 0, + WEP = 1, + WPA_Personal = 2, + */ +bool SPWFSAxx::connect(const char *ap, const char *passPhrase, int securityMode) +{ + int trials; + + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + //AT+S.SCFG=wifi_wpa_psk_text,%s + if(!(_parser.send("AT+S.SCFG=wifi_wpa_psk_text,%s", passPhrase) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error pass set\r\n"); + return false; + } + + //AT+S.SSIDTXT=%s + if(!(_parser.send("AT+S.SSIDTXT=%s", ap) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error ssid set\r\n"); + return false; + } + + //AT+S.SCFG=wifi_priv_mode,%d + if(!(_parser.send("AT+S.SCFG=wifi_priv_mode,%d", securityMode) && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error security mode set\r\n"); + return false; + } + + /*set STA mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ + if(!(_parser.send("AT+S.SCFG=wifi_mode,1") && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set 1 (STA)\r\n"); + return false; + } + + /* sw reset */ + if(!reset()) { + debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__); + return false; + } + + trials = 0; + while(true) { + if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) + { + if(strstr(_msg_buffer, ":24:") != NULL) { // WiFi Up + debug_if(_dbg_on, "AT^ %s\n", _msg_buffer); + if(strchr(_msg_buffer, '.') != NULL) { // IPv4 address + break; + } else { + continue; + } + } + if(strstr(_msg_buffer, ":40:") != NULL) { // Deauthentication + debug_if(_dbg_on, "AT~ %s\n", _msg_buffer); + if(++trials < SPWFXX_MAX_TRIALS) { // give it three trials + continue; + } + disconnect(); + empty_rx_buffer(); + return false; + } else { + debug_if(_dbg_on, "AT] %s\n", _msg_buffer); + } + continue; + } + if(++trials >= SPWFXX_MAX_TRIALS) { + debug("\r\nSPWF> ERROR: Should never happen! (%s, %d)\r\n", __func__, __LINE__); + empty_rx_buffer(); + return false; + } + } + + return true; +} + +bool SPWFSAxx::disconnect(void) +{ + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 + /*disable Wi-Fi device*/ + if(!(_parser.send("AT+S.WIFI=0") && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error disabling WiFi\r\n"); + return false; + } +#endif // IDW04A1 + + /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/ + if(!(_parser.send("AT+S.SCFG=wifi_mode,0") && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error WiFi mode set idle (%d)\r\n", __LINE__); + return false; + } + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 + /*enable Wi-Fi device*/ + if(!(_parser.send("AT+S.WIFI=1") && _recv_ok())) + { + debug_if(_dbg_on, "\r\nSPWF> error enabling WiFi\r\n"); + return false; + } +#endif // IDW04A1 + + // reset module + if(!reset()) { + debug_if(_dbg_on, "\r\nSPWF> SW reset failed (%s, %d)\r\n", __func__, __LINE__); + return false; + } + + /* clean up state */ + _associated_interface.inner_constructor(); + _free_all_packets(); + + return true; +} + +const char *SPWFSAxx::getIPAddress(void) +{ + unsigned int n1, n2, n3, n4; + + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + if (!(_parser.send("AT+S.STS=ip_ipaddr") + && _parser.recv(SPWFXX_RECV_IP_ADDR, &n1, &n2, &n3, &n4) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> get IP address error\r\n"); + return NULL; + } + + debug_if(_dbg_on, "AT^ ip_ipaddr = %u.%u.%u.%u\r\n", n1, n2, n3, n4); + + sprintf((char*)_ip_buffer,"%u.%u.%u.%u", n1, n2, n3, n4); + return _ip_buffer; +} + +const char *SPWFSAxx::getGateway(void) +{ + unsigned int n1, n2, n3, n4; + + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + if (!(_parser.send("AT+S.STS=ip_gw") + && _parser.recv(SPWFXX_RECV_GATEWAY, &n1, &n2, &n3, &n4) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> get gateway error\r\n"); + return NULL; + } + + debug_if(_dbg_on, "AT^ ip_gw = %u.%u.%u.%u\r\n", n1, n2, n3, n4); + + sprintf((char*)_gateway_buffer,"%u.%u.%u.%u", n1, n2, n3, n4); + return _gateway_buffer; +} + +const char *SPWFSAxx::getNetmask(void) +{ + unsigned int n1, n2, n3, n4; + + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + if (!(_parser.send("AT+S.STS=ip_netmask") + && _parser.recv(SPWFXX_RECV_NETMASK, &n1, &n2, &n3, &n4) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> get netmask error\r\n"); + return NULL; + } + + debug_if(_dbg_on, "AT^ ip_netmask = %u.%u.%u.%u\r\n", n1, n2, n3, n4); + + sprintf((char*)_netmask_buffer,"%u.%u.%u.%u", n1, n2, n3, n4); + return _netmask_buffer; +} + +int8_t SPWFSAxx::getRssi(void) +{ + int ret; + + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + if (!(_parser.send("AT+S.PEERS=0,rx_rssi") + && _parser.recv(SPWFXX_RECV_RX_RSSI, &ret) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> get RX rssi error\r\n"); + return 0; + } + + return (int8_t)ret; +} + +const char *SPWFSAxx::getMACAddress(void) +{ + unsigned int n1, n2, n3, n4, n5, n6; + + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + if (!(_parser.send("AT+S.GCFG=nv_wifi_macaddr") + && _parser.recv(SPWFXX_RECV_MAC_ADDR, &n1, &n2, &n3, &n4, &n5, &n6) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> get MAC address error\r\n"); + return 0; + } + + debug_if(_dbg_on, "AT^ nv_wifi_macaddr = %x:%x:%x:%x:%x:%x\r\n", n1, n2, n3, n4, n5, n6); + + sprintf((char*)_mac_buffer,"%02X:%02X:%02X:%02X:%02X:%02X", n1, n2, n3, n4, n5, n6); + return _mac_buffer; +} + +bool SPWFSAxx::isConnected(void) +{ + return _associated_interface._connected_to_network; +} + +nsapi_size_or_error_t SPWFSAxx::send(int spwf_id, const void *data, uint32_t amount, int internal_id) +{ + uint32_t sent = 0U, to_send; + nsapi_size_or_error_t ret; + + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + _process_winds(); // perform async indication handling (to early detect eventually closed sockets) + + /* betzw - WORK AROUND module FW issues: split up big packages in smaller ones */ + for(to_send = (amount > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : amount; + sent < amount; + to_send = ((amount - sent) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (amount - sent)) { + { + BlockExecuter bh_handler(Callback<void()>(this, &SPWFSAxx::_execute_bottom_halves)); + + // betzw - TODO: handle different errors more accurately! + if (!_associated_interface._socket_is_still_connected(internal_id)) { + debug_if(_dbg_on, "\r\nSPWF> Socket not connected anymore: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__); + break; + } else if(!_parser.send("AT+S.SOCKW=%d,%d", spwf_id, (unsigned int)to_send)) { + debug_if(_dbg_on, "\r\nSPWF> Sending command failed: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__); + break; + } else if(_parser.write(((char*)data)+sent, (int)to_send) != (int)to_send) { + debug_if(_dbg_on, "\r\nSPWF> Sending data failed: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__); + break; + } else if(!_recv_ok()) { + debug_if(_dbg_on, "\r\nSPWF> Sending did not receive OK: sent=%u, to_send=%u! (%s, %d)\r\n", sent, to_send, __func__, __LINE__); + break; + } + } + + sent += to_send; + } + + if(sent > 0) { // `sent == 0` indicates a potential error + ret = sent; + } else if(amount == 0) { + ret = NSAPI_ERROR_OK; + } else if(_associated_interface._socket_is_still_connected(internal_id)) { + ret = NSAPI_ERROR_DEVICE_ERROR; + } else { + ret = NSAPI_ERROR_CONNECTION_LOST; + } + + return ret; +} + +int SPWFSAxx::_read_len(int spwf_id) { + unsigned int amount; + + if (!(_parser.send("AT+S.SOCKQ=%d", spwf_id) + && _parser.recv(SPWFXX_RECV_DATALEN, &amount) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> %s failed\r\n", __func__); + return SPWFXX_ERR_LEN; + } + + if(amount > 0) { + debug_if(_dbg_on, "\r\nSPWF> %s():\t\t%d:%d\r\n", __func__, spwf_id, amount); + } + + MBED_ASSERT(((int)amount) >= 0); + + return (int)amount; +} + +#define SPWFXX_WINDS_OFF "0xFFFFFFFF" + +void SPWFSAxx::_winds_on(void) { + MBED_ASSERT(_is_event_callback_blocked()); + + if(!(_parser.send(SPWFXX_SEND_WIND_OFF_HIGH SPWFXX_WINDS_HIGH_ON) && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); + } + if(!(_parser.send(SPWFXX_SEND_WIND_OFF_MEDIUM SPWFXX_WINDS_MEDIUM_ON) && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); + } + if(!(_parser.send(SPWFXX_SEND_WIND_OFF_LOW SPWFXX_WINDS_LOW_ON) && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); + } +} + +/* Define beyond macro in case you want to report back failures in switching off WINDs to the caller */ +// #define SPWFXX_SOWF +/* Note: in case of error blocking has been (tried to be) lifted */ +bool SPWFSAxx::_winds_off(void) { + MBED_ASSERT(_is_event_callback_blocked()); + + if (!(_parser.send(SPWFXX_SEND_WIND_OFF_LOW SPWFXX_WINDS_OFF) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); +#ifdef SPWFXX_SOWF // betzw: try to continue + _winds_on(); + return false; +#endif + } + + if (!(_parser.send(SPWFXX_SEND_WIND_OFF_MEDIUM SPWFXX_WINDS_OFF) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); +#ifdef SPWFXX_SOWF // betzw: try to continue + _winds_on(); + return false; +#endif + } + + if (!(_parser.send(SPWFXX_SEND_WIND_OFF_HIGH SPWFXX_WINDS_OFF) + && _recv_ok())) { + debug_if(_dbg_on, "\r\nSPWF> %s failed at line #%d\r\n", __func__, __LINE__); +#ifdef SPWFXX_SOWF // betzw: try to continue + _winds_on(); + return false; +#endif + } + + return true; +} + +void SPWFSAxx::_execute_bottom_halves(void) { + _network_lost_handler_bh(); + _packet_handler_bh(); +} + +void SPWFSAxx::_read_in_pending(void) { + static int internal_id_cnt = 0; + + while(_is_data_pending()) { + if(_associated_interface._socket_has_connected(internal_id_cnt)) { + int spwf_id = _associated_interface._ids[internal_id_cnt].spwf_id; + + if(_is_data_pending(spwf_id)) { + int amount; + + amount = _read_in_pkt(spwf_id, false); + if(amount == SPWFXX_ERR_OOM) { /* consider only 'SPWFXX_ERR_OOM' as non recoverable */ + return; + } + } + + if(!_is_data_pending(spwf_id)) { + internal_id_cnt++; + internal_id_cnt %= SPWFSA_SOCKET_COUNT; + } + } else { + internal_id_cnt++; + internal_id_cnt %= SPWFSA_SOCKET_COUNT; + } + } +} + +/* Note: returns + * 'SPWFXX_ERR_OK' in case of success + * 'SPWFXX_ERR_OOM' in case of "out of memory" + * 'SPWFXX_ERR_READ' in case of `_read_in()` error + */ +int SPWFSAxx::_read_in_packet(int spwf_id, uint32_t amount) { + struct packet *packet = (struct packet*)malloc(sizeof(struct packet) + amount); + if (!packet) { +#ifndef NDEBUG + error("\r\nSPWF> %s(%d): Out of memory!\r\n", __func__, __LINE__); +#else // NDEBUG + debug("\r\nSPWF> %s(%d): Out of memory!\r\n", __func__, __LINE__); +#endif + debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__); + return SPWFXX_ERR_OOM; /* out of memory: give up here! */ + } + + /* init packet */ + packet->id = spwf_id; + packet->len = amount; + packet->next = 0; + + /* read data in */ + if(!(_read_in((char*)(packet + 1), spwf_id, amount) > 0)) { + free(packet); + debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__); + return SPWFXX_ERR_READ; + } else { + debug_if(_dbg_on, "\r\nSPWF> %s():\t%d:%d\r\n", __func__, spwf_id, amount); + + /* append to packet list */ + *_packets_end = packet; + _packets_end = &packet->next; + + /* force call of (external) callback */ + _call_callback(); + } + + return SPWFXX_ERR_OK; +} + +void SPWFSAxx::_free_packets(int spwf_id) { + // check if any packets are ready for `spwf_id` + for(struct packet **p = &_packets; *p;) { + if ((*p)->id == spwf_id) { + struct packet *q = *p; + if (_packets_end == &(*p)->next) { + _packets_end = p; + } + *p = (*p)->next; + free(q); + } else { + p = &(*p)->next; + } + } +} + +void SPWFSAxx::_free_all_packets() { + for (int spwf_id = 0; spwf_id < SPWFSA_SOCKET_COUNT; spwf_id++) { + _free_packets(spwf_id); + } +} + +bool SPWFSAxx::close(int spwf_id) +{ + bool ret = false; + + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); // `spwf_id` is valid + + for(int retry_cnt = 0; retry_cnt < SPWFXX_MAX_TRIALS; retry_cnt++) { + Timer timer; + timer.start(); + + // Flush out pending data + while(true) { + int amount = _read_in_pkt(spwf_id, true); + if(amount < 0) { // SPWFXX error + /* empty RX buffer & try to close */ + empty_rx_buffer(); + break; + } + if(amount == 0) break; // no more data to be read + + /* Try to work around module API bug: + * break out & try to close after 20 seconds + */ + if(timer.read() > 20) { + break; + } + + /* immediately free packet(s) (to avoid "out of memory") */ + _free_packets(spwf_id); + + /* interleave bottom halves */ + _execute_bottom_halves(); + } + + // Close socket + if (_parser.send("AT+S.SOCKC=%d", spwf_id) + && _recv_ok()) { + ret = true; + break; // finish closing + } else { // close failed + debug_if(_dbg_on, "\r\nSPWF> %s failed (%d)\r\n", __func__, __LINE__); + /* interleave bottom halves */ + _execute_bottom_halves(); + + /* free packets */ + _free_packets(spwf_id); + } + } + + /* anticipate bottom halves */ + _execute_bottom_halves(); + + if(ret) { + /* clear pending data flag (should be redundant) */ + _clear_pending_data(spwf_id); + + /* free packets for this socket */ + _free_packets(spwf_id); + + /* reset pending data sizes */ + _reset_pending_pkt_sizes(spwf_id); + } else { + debug_if(_dbg_on, "\r\nSPWF> SPWFSAxx::close failed (%d)\r\n", __LINE__); + + int internal_id = _associated_interface.get_internal_id(spwf_id); + if(!_associated_interface._socket_is_still_connected(internal_id)) { + /* clear pending data flag (should be redundant) */ + _clear_pending_data(spwf_id); + + /* free packets for this socket */ + _free_packets(spwf_id); + + /* reset pending data sizes */ + _reset_pending_pkt_sizes(spwf_id); + + ret = true; + } + } + + return ret; +} + +/* + * Buffered serial event handler + * + * Note: executed in IRQ context! + * Note: do not call (external) callback in IRQ context while performing critical module operations + */ +void SPWFSAxx::_event_handler(void) +{ + if(!_is_event_callback_blocked()) { + _call_callback(); + } +} + +/* + * Common error handler + */ +void SPWFSAxx::_error_handler(void) +{ + if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) { + debug_if(_dbg_on, "AT^ ERROR:%s (%d)\r\n", _msg_buffer, __LINE__); + } else { + debug_if(_dbg_on, "\r\nSPWF> Unknown ERROR string in SPWFSAxx::_error_handler (%d)\r\n", __LINE__); + } + + /* force call of (external) callback */ + _call_callback(); +} + +/* + * Handling oob ("+WIND:33:WiFi Network Lost") + */ +void SPWFSAxx::_network_lost_handler_th(void) +{ +#ifndef NDEBUG + static unsigned int net_loss_cnt = 0; + net_loss_cnt++; +#endif + + _recv_delim_cr_lf(); + + debug_if(_dbg_on, "AT^ +WIND:33:WiFi Network Lost\r\n"); + +#ifndef NDEBUG + debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_th: %d\r\n", net_loss_cnt); +#else // NDEBUG + debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_th: %d\r\n", __LINE__); +#endif // NDEBUG + + /* set flag to signal network loss */ + _network_lost_flag = true; + + /* force call of (external) callback */ + _call_callback(); + + return; +} + +/* betzw - WORK AROUND module FW issues: split up big packages in smaller ones */ +void SPWFSAxx::_add_pending_packet_sz(int spwf_id, uint32_t size) { + uint32_t to_add; + uint32_t added = _get_cumulative_size(spwf_id); + + if(size <= added) { // might happen due to delayed WIND delivery + debug_if(_dbg_on, "\r\nSPWF> WARNING: %s failed at line #%d\r\n", __func__, __LINE__); + return; + } + + for(to_add = ((size - added) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (size - added); + added < size; + to_add = ((size - added) > SPWFXX_SEND_RECV_PKTSIZE) ? SPWFXX_SEND_RECV_PKTSIZE : (size - added)) { + _add_pending_pkt_size(spwf_id, added + to_add); + added += to_add; + } + + /* force call of (external) callback */ + _call_callback(); + + /* set that data is pending */ + _set_pending_data(spwf_id); +} + +/* + * Handling oob ("+WIND:55:Pending Data") + */ +void SPWFSAxx::_packet_handler_th(void) +{ + int internal_id, spwf_id; + int amount; + + /* parse out the socket id & amount */ + if (!(_parser.recv(SPWFXX_RECV_PENDING_DATA, &spwf_id, &amount) && _recv_delim_lf())) { +#ifndef NDEBUG + error("\r\nSPWF> SPWFSAxx::%s failed!\r\n", __func__); +#endif + return; + } + + debug_if(_dbg_on, "AT^ +WIND:55:Pending Data:%d:%d\r\n", spwf_id, amount); + + /* check for the module to report a valid id */ + MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); + + /* set that there is pending data for socket */ + /* NOTE: it seems as if asynchronous indications might report not up-to-date data length values + * therefore we just record the socket id without considering the `amount` of data reported! + */ + internal_id = _associated_interface.get_internal_id(spwf_id); + if(internal_id != SPWFSA_SOCKET_COUNT) { + debug_if(_dbg_on, "AT^ +WIND:55:Pending Data:%d:%d - #2\r\n", spwf_id, amount); + _add_pending_packet_sz(spwf_id, amount); + + MBED_ASSERT(_get_pending_pkt_size(spwf_id) != 0); + } else { + debug_if(_dbg_on, "\r\nSPWFSAxx::%s got invalid id %d\r\n", __func__, spwf_id); + } +} + +void SPWFSAxx::_network_lost_handler_bh(void) +{ + if(!_network_lost_flag) return; + _network_lost_flag = false; + + { + bool were_connected; + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* do not call (external) callback in IRQ context as long as network is lost */ + Timer timer; + timer.start(); + + _parser.set_timeout(SPWF_NETLOST_TIMEOUT); + + were_connected = isConnected(); + _associated_interface._connected_to_network = false; + + if(were_connected) { + unsigned int n1, n2, n3, n4; + + while(true) { + if (timer.read_ms() > SPWF_CONNECT_TIMEOUT) { + debug_if(_dbg_on, "\r\nSPWF> SPWFSAxx::_network_lost_handler_bh() #%d\r\n", __LINE__); + disconnect(); + empty_rx_buffer(); + goto nlh_get_out; + } + + if((_parser.recv(SPWFXX_RECV_WIFI_UP, &n1, &n2, &n3, &n4)) && _recv_delim_lf()) { + debug_if(_dbg_on, "\r\nSPWF> Re-connected (%u.%u.%u.%u)!\r\n", n1, n2, n3, n4); + + _associated_interface._connected_to_network = true; + goto nlh_get_out; + } + } + } else { + debug_if(_dbg_on, "\r\nSPWF> Leaving SPWFSAxx::_network_lost_handler_bh\r\n"); + goto nlh_get_out; + } + + nlh_get_out: + debug_if(_dbg_on, "\r\nSPWF> Getting out of SPWFSAxx::_network_lost_handler_bh\r\n"); + _parser.set_timeout(_timeout); + + /* force call of (external) callback */ + _call_callback(); + + return; + } +} + +void SPWFSAxx::_recover_from_hard_faults(void) { + disconnect(); + empty_rx_buffer(); + + /* force call of (external) callback */ + _call_callback(); +} + +/* + * Handling oob ("+WIND:8:Hard Fault") + */ +void SPWFSAxx::_hard_fault_handler(void) +{ + _parser.set_timeout(SPWF_RECV_TIMEOUT); + if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) { +#ifndef NDEBUG + error("\r\nSPWF> hard fault error:\r\n%s\r\n", _msg_buffer); +#else // NDEBUG + debug("\r\nSPWF> hard fault error:\r\n%s\r\n", _msg_buffer); +#endif // NDEBUG + } else { +#ifndef NDEBUG + error("\r\nSPWF> unknown hard fault error\r\n"); +#else // NDEBUG + debug("\r\nSPWF> unknown hard fault error\r\n"); +#endif // NDEBUG + } + + // This is most likely the best we can do to recover from this module hard fault + _parser.set_timeout(SPWF_HF_TIMEOUT); + _recover_from_hard_faults(); + _parser.set_timeout(_timeout); + + /* force call of (external) callback */ + _call_callback(); +} + +/* + * Handling oob ("+WIND:5:WiFi Hardware Failure") + */ +void SPWFSAxx::_wifi_hwfault_handler(void) +{ + unsigned int failure_nr; + + /* parse out the socket id & amount */ + _parser.recv(":%u\n", &failure_nr); + _recv_delim_lf(); + +#ifndef NDEBUG + error("\r\nSPWF> WiFi HW fault error: %u\r\n", failure_nr); +#else // NDEBUG + debug("\r\nSPWF> WiFi HW fault error: %u\r\n", failure_nr); + + // This is most likely the best we can do to recover from this module hard fault + _parser.set_timeout(SPWF_HF_TIMEOUT); + _recover_from_hard_faults(); + _parser.set_timeout(_timeout); +#endif // NDEBUG + + /* force call of (external) callback */ + _call_callback(); +} + +/* + * Handling oob ("+WIND:58:Socket Closed") + * when server closes a client connection + * + * NOTE: When a socket client receives an indication about socket server gone (only for TCP sockets, WIND:58), + * the socket connection is NOT automatically closed! + */ +void SPWFSAxx::_server_gone_handler(void) +{ + int spwf_id, internal_id; + + if(!(_parser.recv(SPWFXX_RECV_SOCKET_CLOSED, &spwf_id) && _recv_delim_lf())) { +#ifndef NDEBUG + error("\r\nSPWF> SPWFSAxx::%s failed!\r\n", __func__); +#endif + goto _get_out; + } + + debug_if(_dbg_on, "AT^ +WIND:58:Socket Closed:%d\r\n", spwf_id); + + /* check for the module to report a valid id */ + MBED_ASSERT(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); + + /* only set `server_gone` + * user still can receive data & must still explicitly close the socket + */ + internal_id = _associated_interface.get_internal_id(spwf_id); + if(internal_id != SPWFSA_SOCKET_COUNT) { + _associated_interface._ids[internal_id].server_gone = true; + } + +_get_out: + /* force call of (external) callback */ + _call_callback(); +} + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 +/* + * Handling oob (currently only for "+WIND:24:WiFi Up::") + */ +void SPWFSAxx::_skip_oob(void) +{ + if(_parser.recv("%255[^\n]\n", _msg_buffer) && _recv_delim_lf()) { + debug_if(_dbg_on, "AT^ +WIND:24:WiFi Up::%s\r\n", _msg_buffer); + } else { + debug_if(_dbg_on, "\r\nSPWF> Invalid string in SPWFSAxx::_skip_oob (%d)\r\n", __LINE__); + } +} +#endif + +void SPWFSAxx::setTimeout(uint32_t timeout_ms) +{ + _timeout = timeout_ms; + _parser.set_timeout(timeout_ms); +} + +void SPWFSAxx::attach(Callback<void()> func) +{ + _callback_func = func; /* do not call (external) callback in IRQ context during critical module operations */ +} + +/** + * Recv Function + */ +int32_t SPWFSAxx::recv(int spwf_id, void *data, uint32_t amount, bool datagram) +{ + BlockExecuter bh_handler(Callback<void()>(this, &SPWFSAxx::_execute_bottom_halves)); + + while (true) { + /* check if any packets are ready for us */ + for (struct packet **p = &_packets; *p; p = &(*p)->next) { + if ((*p)->id == spwf_id) { + debug_if(_dbg_on, "\r\nSPWF> Read done on ID %d and length of packet is %d\r\n",spwf_id,(*p)->len); + struct packet *q = *p; + + MBED_ASSERT(q->len > 0); + + if(datagram) { // UDP => always remove pkt size + // will always consume a whole pending size + uint32_t ret; + + debug_if(_dbg_on, "\r\nSPWF> %s():\t\t\t%d:%d (datagram)\r\n", __func__, spwf_id, q->len); + + ret = (amount < q->len) ? amount : q->len; + memcpy(data, q+1, ret); + + if (_packets_end == &(*p)->next) { + _packets_end = p; + } + *p = (*p)->next; + free(q); + + return ret; + } else { // TCP + 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 { // `q->len > amount`, return only partial packet + if(amount > 0) { + memcpy(data, q+1, amount); + q->len -= amount; + memmove(q+1, (uint8_t*)(q+1) + amount, q->len); + } + + return amount; + } + } + } + } + + /* check for pending data on module */ + { + int len; + + len = _read_in_pkt(spwf_id, false); + if(len <= 0) { /* SPWFXX error or no more data to be read */ + return -1; + } + } + } +} + +void SPWFSAxx::_process_winds(void) { + do { + if(_parser.process_oob()) { + /* nothing else to do! */; + } else { + debug_if(_dbg_on, "%s():\t\tNo (more) oob's found!\r\n", __func__); + return; // no (more) oob's found + } + } while(true); +} + +/* Note: returns + * '>=0' in case of success, amount of read in data (in bytes) + * 'SPWFXX_ERR_OOM' in case of "out of memory" + * 'SPWFXX_ERR_READ' in case of other `_read_in_packet()` error + * 'SPWFXX_ERR_LEN' in case of `_read_len()` error + */ +int SPWFSAxx::_read_in_pkt(int spwf_id, bool close) { + int pending; + uint32_t wind_pending; + BlockExecuter netsock_wa_obj(Callback<void()>(this, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(this, &SPWFSAxx::_block_event_callback)); /* do not call (external) callback in IRQ context while receiving */ + + _process_winds(); // perform async indication handling + + if(close) { // read in all data + wind_pending = pending = _read_len(spwf_id); // triggers also async indication handling! + + if(pending > 0) { + /* reset pending data sizes */ + _reset_pending_pkt_sizes(spwf_id); + /* create new entry for pending size */ + _add_pending_pkt_size(spwf_id, (uint32_t)pending); +#ifndef NDEBUG + wind_pending = _get_pending_pkt_size(spwf_id); + MBED_ASSERT(pending == (int)wind_pending); +#endif + } else if(pending < 0) { + debug_if(_dbg_on, "\r\nSPWF> %s(), #%d:`_read_len()` failed (%d)!\r\n", __func__, __LINE__, pending); + } + } else { // only read in already notified data + pending = wind_pending = _get_pending_pkt_size(spwf_id); + if(pending == 0) { // special handling for no packets pending (to WORK AROUND missing WINDs)! + pending = _read_len(spwf_id); // triggers also async indication handling! + + if(pending > 0) { + _process_winds(); // perform async indication handling (again) + wind_pending = _get_pending_pkt_size(spwf_id); + + if(wind_pending == 0) { + /* betzw - WORK AROUND module FW issues: create new entry for pending size */ + debug_if(_dbg_on, "%s():\t\tAdd packet w/o WIND (%d)!\r\n", __func__, pending); + _add_pending_packet_sz(spwf_id, (uint32_t)pending); + + pending = wind_pending = _get_pending_pkt_size(spwf_id); + MBED_ASSERT(wind_pending > 0); + } + } else if(pending < 0) { + debug_if(_dbg_on, "\r\nSPWF> %s(), #%d:`_read_len()` failed (%d)!\r\n", __func__, __LINE__, pending); + } + } + } + + if((pending > 0) && (wind_pending > 0)) { + int ret = _read_in_packet(spwf_id, wind_pending); + if(ret < 0) { /* "out of memory" or `_read_in_packet()` error */ + /* we do not know if data is still pending at this point + but leaving the pending data bit set might lead to an endless loop */ + _clear_pending_data(spwf_id); + /* also reset pending data sizes */ + _reset_pending_pkt_sizes(spwf_id); + + return ret; + } + + if((_get_cumulative_size(spwf_id) == 0) && (pending <= (int)wind_pending)) { + _clear_pending_data(spwf_id); + } + } else if(pending < 0) { /* 'SPWFXX_ERR_LEN' error */ + MBED_ASSERT(pending == SPWFXX_ERR_LEN); + /* we do not know if data is still pending at this point + but leaving the pending data bit set might lead to an endless loop */ + _clear_pending_data(spwf_id); + /* also reset pending data sizes */ + _reset_pending_pkt_sizes(spwf_id); + + return pending; + } else if(pending == 0) { + MBED_ASSERT(wind_pending == 0); + _clear_pending_data(spwf_id); + } else if(wind_pending == 0) { // `pending > 0` + /* betzw: should never happen! */ + MBED_ASSERT(false); + } + + return (int)wind_pending; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SPWFSAxx.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,446 @@ +/* SPWFSAxx Devices + * 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 SPWFSAXX_H +#define SPWFSAXX_H + +#include "mbed.h" +#include "ATCmdParser.h" +#include "BlockExecuter.h" + +/* Common SPWFSAxx macros */ +#define SPWFXX_WINDS_LOW_ON "0x00000000" +#define SPWFXX_DEFAULT_BAUD_RATE 115200 +#define SPWFXX_MAX_TRIALS 3 + +#if !defined(SPWFSAXX_RTS_PIN) +#define SPWFSAXX_RTS_PIN NC +#endif // !defined(SPWFSAXX_RTS_PIN) +#if !defined(SPWFSAXX_CTS_PIN) +#define SPWFSAXX_CTS_PIN NC +#endif // !defined(SPWFSAXX_CTS_PIN) + +#define SPWFXX_ERR_OK (+1) +#define SPWFXX_ERR_OOM (-1) +#define SPWFXX_ERR_READ (-2) +#define SPWFXX_ERR_LEN (-3) + + +/* Max number of sockets & packets */ +#define SPWFSA_SOCKET_COUNT (8) +#define SPWFSA_MAX_PACKETS (4) + +#define PENDING_DATA_SLOTS (13) + +/* Pending data packets size buffer */ +class SpwfRealPendingPackets { +public: + SpwfRealPendingPackets() { + reset(); + } + + void add(uint32_t new_cum_size) { + MBED_ASSERT(new_cum_size >= cumulative_size); + + if(new_cum_size == cumulative_size) { + /* nothing to do */ + return; + } + + /* => `new_cum_size > cumulative_size` */ + real_pkt_sizes[last_pkt_ptr] = (uint16_t)(new_cum_size - cumulative_size); + cumulative_size = new_cum_size; + + last_pkt_ptr = (last_pkt_ptr + 1) % PENDING_DATA_SLOTS; + + MBED_ASSERT(first_pkt_ptr != last_pkt_ptr); + } + + uint32_t get(void) { + if(empty()) return 0; + + return real_pkt_sizes[first_pkt_ptr]; + } + + uint32_t cumulative(void) { + return cumulative_size; + } + + uint32_t remove(uint32_t size) { + MBED_ASSERT(!empty()); + + uint32_t ret = real_pkt_sizes[first_pkt_ptr]; + first_pkt_ptr = (first_pkt_ptr + 1) % PENDING_DATA_SLOTS; + + MBED_ASSERT(ret == size); + MBED_ASSERT(ret <= cumulative_size); + cumulative_size -= ret; + + return ret; + } + + void reset(void) { + memset(this, 0, sizeof(*this)); + } + +private: + bool empty(void) { + if(first_pkt_ptr == last_pkt_ptr) { + MBED_ASSERT(cumulative_size == 0); + return true; + } + return false; + } + + uint16_t real_pkt_sizes[PENDING_DATA_SLOTS]; + uint8_t first_pkt_ptr; + uint8_t last_pkt_ptr; + uint32_t cumulative_size; +}; + +class SpwfSAInterface; + +/** SPWFSAxx Interface class. + This is an interface to a SPWFSAxx module. + */ +class SPWFSAxx +{ +private: + /* abstract class*/ + SPWFSAxx(PinName tx, PinName rx, PinName rts, PinName cts, + SpwfSAInterface &ifce, bool debug, + PinName wakeup, PinName reset); + +public: + /** + * Init the SPWFSAxx + * + * @param mode mode in which to startup + * @return true only if SPWFSAxx has started up correctly + */ + bool startup(int mode); + + /** + * Connect SPWFSAxx to AP + * + * @param ap the name of the AP + * @param passPhrase the password of AP + * @param securityMode the security mode of AP (WPA/WPA2, WEP, Open) + * @return true only if SPWFSAxx is connected successfully + */ + bool connect(const char *ap, const char *passPhrase, int securityMode); + + /** + * Disconnect SPWFSAxx from AP + * + * @return true only if SPWFSAxx is disconnected successfully + */ + bool disconnect(void); + + /** + * Get the IP address of SPWFSAxx + * + * @return null-terminated IP address or null if no IP address is assigned + */ + const char *getIPAddress(void); + + /** + * Get the MAC address of SPWFSAxx + * + * @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 received + */ + const char *getGateway(void); + + /** Get the local network mask + * + * @return Null-terminated representation of the local network mask + * or null if no network mask has been received + */ + const char *getNetmask(void); + + /** Gets the current radio signal strength for active connection + * + * @return Connection strength in dBm (negative value) + */ + int8_t getRssi(); + + /** + * Sends data to an open socket + * + * @param spwf_id module id of socket to send to + * @param data data to be sent + * @param amount amount of data to be sent - max 1024 + * @param internal_id driver id of socket to send to + * @return number of written bytes on success, negative on failure + */ + nsapi_size_or_error_t send(int spwf_id, const void *data, uint32_t amount, int internal_id); + + /** + * 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 + * @param datagram receive a datagram packet + * @return the number of bytes received + */ + int32_t recv(int id, void *data, uint32_t amount, bool datagram); + + /** + * 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); + + /** + * 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)); + } + + static const char _cr_ = '\x0d'; // '\r' carriage return + static const char _lf_ = '\x0a'; // '\n' line feed + +private: + UARTSerial _serial; + ATCmdParser _parser; + + DigitalOut _wakeup; + DigitalOut _reset; + PinName _rts; + PinName _cts; + + int _timeout; + bool _dbg_on; + + int _pending_sockets_bitmap; + SpwfRealPendingPackets _pending_pkt_sizes[SPWFSA_SOCKET_COUNT]; + + bool _network_lost_flag; + SpwfSAInterface &_associated_interface; + + /** + * Reset SPWFSAxx + * + * @return true only if SPWFSAxx resets successfully + */ + bool hw_reset(void); + bool reset(void); + + /** + * Check if SPWFSAxx is connected + * + * @return true only if the chip has an IP address + */ + bool isConnected(void); + + /** + * Checks if data is available + */ + bool readable(void) { + return _serial.FileHandle::readable(); + } + + /** + * Checks if data can be written + */ + bool writeable(void) { + return _serial.FileHandle::writable(); + } + + /** + * Try to empty RX buffer + * Can be used when commands fail receiving expected response to try to recover situation + * @note Gives no guarantee that situation improves + */ + void empty_rx_buffer(void) { + while(readable()) _parser.getc(); + } + + /* block calling (external) callback */ + volatile unsigned int _call_event_callback_blocked; + Callback<void()> _callback_func; + + struct packet { + struct packet *next; + int id; + uint32_t len; + // data follows + } *_packets, **_packets_end; + + void _packet_handler_th(void); + void _execute_bottom_halves(void); + void _network_lost_handler_th(void); + void _network_lost_handler_bh(void); + void _hard_fault_handler(void); + void _wifi_hwfault_handler(void); + void _server_gone_handler(void); +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 + void _skip_oob(void); +#endif + bool _wait_wifi_hw_started(void); + bool _wait_console_active(void); + int _read_len(int); + int _flush_in(char*, int); + bool _winds_off(void); + void _winds_on(void); + void _read_in_pending(void); + int _read_in_pkt(int spwf_id, bool close); + int _read_in_packet(int spwf_id, uint32_t amount); + void _recover_from_hard_faults(void); + void _free_packets(int spwf_id); + void _free_all_packets(void); + void _process_winds(); + + virtual int _read_in(char*, int, uint32_t) = 0; + + bool _recv_delim_lf(void) { + return (_parser.getc() == _lf_); + } + + bool _recv_delim_cr(void) { + return (_parser.getc() == _cr_); + } + + bool _recv_delim_cr_lf(void) { + return _recv_delim_cr() && _recv_delim_lf(); + } + + bool _recv_ok(void) { + return _parser.recv(SPWFXX_RECV_OK) && _recv_delim_lf(); + } + + void _add_pending_packet_sz(int spwf_id, uint32_t size); + void _add_pending_pkt_size(int spwf_id, uint32_t size) { + _pending_pkt_sizes[spwf_id].add(size); + } + + uint32_t _get_cumulative_size(int spwf_id) { + return _pending_pkt_sizes[spwf_id].cumulative(); + } + + uint32_t _remove_pending_pkt_size(int spwf_id, uint32_t size) { + return _pending_pkt_sizes[spwf_id].remove(size); + } + + uint32_t _get_pending_pkt_size(int spwf_id) { + return _pending_pkt_sizes[spwf_id].get(); + } + + void _reset_pending_pkt_sizes(int spwf_id) { + _pending_pkt_sizes[spwf_id].reset(); + } + + void _set_pending_data(int spwf_id) { + _pending_sockets_bitmap |= (1 << spwf_id); + } + + void _clear_pending_data(int spwf_id) { + _pending_sockets_bitmap &= ~(1 << spwf_id); + } + + bool _is_data_pending(int spwf_id) { + return (_pending_sockets_bitmap & (1 << spwf_id)) ? true : false; + } + + bool _is_data_pending(void) { + if(_pending_sockets_bitmap != 0) return true; + else return false; + } + + void _packet_handler_bh(void) { + /* read in other eventually pending packages */ + _read_in_pending(); + } + + /* Do not call the (external) callback in IRQ context while performing critical module operations */ + void _event_handler(void); + + void _error_handler(void); + + void _call_callback(void) { + if((bool)_callback_func) { + _callback_func(); + } + } + + bool _is_event_callback_blocked(void) { + return (_call_event_callback_blocked != 0); + } + + void _block_event_callback(void) { + _call_event_callback_blocked++; + } + + void _unblock_event_callback(void) { + MBED_ASSERT(_call_event_callback_blocked > 0); + _call_event_callback_blocked--; + if(_call_event_callback_blocked == 0) { + _trigger_event_callback(); + } + } + + /* trigger call of (external) callback in case there is still data */ + void _trigger_event_callback(void) { + MBED_ASSERT(_call_event_callback_blocked == 0); + /* if still data available */ + if(readable()) { + _call_callback(); + } + } + + char _ip_buffer[16]; + char _gateway_buffer[16]; + char _netmask_buffer[16]; + char _mac_buffer[18]; + + char _msg_buffer[256]; + +private: + friend class SPWFSA01; + friend class SPWFSA04; + friend class SpwfSAInterface; +}; + +#endif // SPWFSAXX_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SpwfSAInterface.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,500 @@ +/* mbed Microcontroller Library + * Copyright (c) 20015 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 SpwfSAInterface.cpp + * @author STMicroelectronics + * @brief Implementation of the NetworkStack for the SPWF Device + ****************************************************************************** + * @copy + * + * 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. + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + ****************************************************************************** + */ + +#include "SpwfSAInterface.h" +#include "mbed_debug.h" +#include "BlockExecuter.h" + +#if MBED_CONF_RTOS_PRESENT +#define SYNC_HANDLER ScopedMutexLock sync_handler(_spwf_mutex) // assuming a recursive mutex +#else +#define SYNC_HANDLER +#endif + + +SpwfSAInterface::SpwfSAInterface(PinName tx, PinName rx, + PinName rts, PinName cts, bool debug, + PinName wakeup, PinName reset) +: _spwf(tx, rx, rts, cts, *this, debug, wakeup, reset), + _dbg_on(debug) +{ + inner_constructor(); + reset_credentials(); +} + +nsapi_error_t SpwfSAInterface::init(void) +{ + _spwf.setTimeout(SPWF_INIT_TIMEOUT); + + if(_spwf.startup(0)) { + return NSAPI_ERROR_OK; + } + else return NSAPI_ERROR_DEVICE_ERROR; +} + +nsapi_error_t SpwfSAInterface::connect(void) +{ + int mode; + char *pass_phrase = ap_pass; + SYNC_HANDLER; + + // check for valid SSID + if(ap_ssid[0] == '\0') { + return NSAPI_ERROR_PARAMETER; + } + + switch(ap_sec) + { + case NSAPI_SECURITY_NONE: + mode = 0; + pass_phrase = NULL; + break; + case NSAPI_SECURITY_WEP: + mode = 1; + break; + case NSAPI_SECURITY_WPA: + case NSAPI_SECURITY_WPA2: + mode = 2; + break; + default: + mode = 2; + break; + } + + // First: disconnect + if(_connected_to_network) { + if(!disconnect()) { + return NSAPI_ERROR_DEVICE_ERROR; + } + } + + //initialize the device before connecting + if(!_isInitialized) + { + if(init() != NSAPI_ERROR_OK) return NSAPI_ERROR_DEVICE_ERROR; + _isInitialized=true; + } + + // Then: (re-)connect + _spwf.setTimeout(SPWF_CONNECT_TIMEOUT); + + if (!_spwf.connect(ap_ssid, pass_phrase, mode)) { + return NSAPI_ERROR_AUTH_FAILURE; + } + + if (!_spwf.getIPAddress()) { + return NSAPI_ERROR_DHCP_FAILURE; + } + + _connected_to_network = true; + return NSAPI_ERROR_OK; +} + +nsapi_error_t SpwfSAInterface::connect(const char *ssid, const char *pass, nsapi_security_t security, + uint8_t channel) +{ + nsapi_error_t ret; + SYNC_HANDLER; + + if (channel != 0) { + return NSAPI_ERROR_UNSUPPORTED; + } + + ret = set_credentials(ssid, pass, security); + if(ret != NSAPI_ERROR_OK) return ret; + + return connect(); +} + +nsapi_error_t SpwfSAInterface::disconnect(void) +{ + SYNC_HANDLER; + + _spwf.setTimeout(SPWF_DISCONNECT_TIMEOUT); + + if (!_spwf.disconnect()) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + return NSAPI_ERROR_OK; +} + +const char *SpwfSAInterface::get_ip_address(void) +{ + SYNC_HANDLER; + + _spwf.setTimeout(SPWF_MISC_TIMEOUT); + return _spwf.getIPAddress(); +} + +const char *SpwfSAInterface::get_mac_address(void) +{ + SYNC_HANDLER; + + _spwf.setTimeout(SPWF_MISC_TIMEOUT); + return _spwf.getMACAddress(); +} + +const char *SpwfSAInterface::get_gateway(void) +{ + SYNC_HANDLER; + + if(!_connected_to_network) return NULL; + + _spwf.setTimeout(SPWF_MISC_TIMEOUT); + return _spwf.getGateway(); +} + +const char *SpwfSAInterface::get_netmask(void) +{ + SYNC_HANDLER; + + if(!_connected_to_network) return NULL; + + _spwf.setTimeout(SPWF_MISC_TIMEOUT); + return _spwf.getNetmask(); +} + +nsapi_error_t SpwfSAInterface::socket_open(void **handle, nsapi_protocol_t proto) +{ + int internal_id; + SYNC_HANDLER; + + for (internal_id = 0; internal_id < SPWFSA_SOCKET_COUNT; internal_id++) { + if(_ids[internal_id].internal_id == SPWFSA_SOCKET_COUNT) break; + } + + if(internal_id == SPWFSA_SOCKET_COUNT) { + debug_if(_dbg_on, "NO Socket ID Error\r\n"); + return NSAPI_ERROR_NO_SOCKET; + } + + spwf_socket_t *socket = &_ids[internal_id]; + socket->internal_id = internal_id; + socket->spwf_id = SPWFSA_SOCKET_COUNT; + socket->server_gone = false; + socket->no_more_data = false; + socket->proto = proto; + socket->addr = SocketAddress(); + + *handle = socket; + return NSAPI_ERROR_OK; +} + +nsapi_error_t SpwfSAInterface::socket_connect(void *handle, const SocketAddress &addr) +{ + spwf_socket_t *socket = (spwf_socket_t*)handle; + SYNC_HANDLER; + + MBED_ASSERT(((unsigned int)socket->internal_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); + + if(_socket_has_connected(socket->internal_id)) { + return NSAPI_ERROR_IS_CONNECTED; + } + + _spwf.setTimeout(SPWF_OPEN_TIMEOUT); + + const char *proto = (socket->proto == NSAPI_UDP) ? "u" : "t"; //"s" for secure socket? + + if(addr.get_ip_version() != NSAPI_IPv4) { // IPv6 not supported (yet) + return NSAPI_ERROR_UNSUPPORTED; + } + + { + BlockExecuter netsock_wa_obj(Callback<void()>(&_spwf, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(&_spwf, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + /* block asynchronous indications */ + if(!_spwf._winds_off()) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + { + BlockExecuter bh_handler(Callback<void()>(&_spwf, &SPWFSAxx::_execute_bottom_halves)); + { + BlockExecuter winds_enabler(Callback<void()>(&_spwf, &SPWFSAxx::_winds_on)); + + if(!_spwf.open(proto, &socket->spwf_id, addr.get_ip_address(), addr.get_port())) { + MBED_ASSERT(_spwf._call_event_callback_blocked == 1); + + return NSAPI_ERROR_DEVICE_ERROR; + } + + /* check for the module to report a valid id */ + MBED_ASSERT(((unsigned int)socket->spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)); + + _internal_ids[socket->spwf_id] = socket->internal_id; + socket->addr = addr; + + MBED_ASSERT(_spwf._call_event_callback_blocked == 1); + + return NSAPI_ERROR_OK; + } + } + } +} + +nsapi_error_t SpwfSAInterface::socket_bind(void *handle, const SocketAddress &address) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +nsapi_error_t SpwfSAInterface::socket_listen(void *handle, int backlog) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +nsapi_error_t SpwfSAInterface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +nsapi_error_t SpwfSAInterface::socket_close(void *handle) +{ + spwf_socket_t *socket = (spwf_socket_t*)handle; + int internal_id = socket->internal_id; + SYNC_HANDLER; + + if(!_socket_is_open(internal_id)) return NSAPI_ERROR_NO_SOCKET; + + if(_socket_has_connected(socket)) { + _spwf.setTimeout(SPWF_CLOSE_TIMEOUT); + if (!_spwf.close(socket->spwf_id)) { + return NSAPI_ERROR_DEVICE_ERROR; + } + _internal_ids[socket->spwf_id] = SPWFSA_SOCKET_COUNT; + } + + _ids[internal_id].internal_id = SPWFSA_SOCKET_COUNT; + _ids[internal_id].spwf_id = SPWFSA_SOCKET_COUNT; + + return NSAPI_ERROR_OK; +} + +nsapi_size_or_error_t SpwfSAInterface::socket_send(void *handle, const void *data, unsigned size) +{ + spwf_socket_t *socket = (spwf_socket_t*)handle; + SYNC_HANDLER; + + CHECK_NOT_CONNECTED_ERR(); + + _spwf.setTimeout(SPWF_SEND_TIMEOUT); + return _spwf.send(socket->spwf_id, data, size, socket->internal_id); +} + +nsapi_size_or_error_t SpwfSAInterface::socket_recv(void *handle, void *data, unsigned size) +{ + SYNC_HANDLER; + + return _socket_recv(handle, data, size, false); +} + +nsapi_size_or_error_t SpwfSAInterface::_socket_recv(void *handle, void *data, unsigned size, bool datagram) +{ + spwf_socket_t *socket = (spwf_socket_t*)handle; + + CHECK_NOT_CONNECTED_ERR(); + + if(!_socket_has_connected(socket)) { + return NSAPI_ERROR_WOULD_BLOCK; + } else if(socket->no_more_data) { + return 0; + } + + _spwf.setTimeout(SPWF_RECV_TIMEOUT); + + int32_t recv = _spwf.recv(socket->spwf_id, (char*)data, (uint32_t)size, datagram); + + MBED_ASSERT(!_spwf._is_event_callback_blocked()); + MBED_ASSERT((recv != 0) || (size == 0)); + + if (recv < 0) { + if(!_socket_is_still_connected(socket)) { + socket->no_more_data = true; + return 0; + } + + return NSAPI_ERROR_WOULD_BLOCK; + } + + return recv; +} + +nsapi_size_or_error_t SpwfSAInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size) +{ + spwf_socket_t *socket = (spwf_socket_t*)handle; + SYNC_HANDLER; + + CHECK_NOT_CONNECTED_ERR(); + + if ((_socket_has_connected(socket)) && (socket->addr != addr)) { + _spwf.setTimeout(SPWF_CLOSE_TIMEOUT); + if (!_spwf.close(socket->spwf_id)) { + return NSAPI_ERROR_DEVICE_ERROR; + } + _internal_ids[socket->spwf_id] = SPWFSA_SOCKET_COUNT; + socket->spwf_id = SPWFSA_SOCKET_COUNT; + } + + _spwf.setTimeout(SPWF_CONN_SND_TIMEOUT); + if (!_socket_has_connected(socket)) { + nsapi_error_t err = socket_connect(socket, addr); + if (err < 0) { + return err; + } + } + + return socket_send(socket, data, size); +} + +nsapi_size_or_error_t SpwfSAInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size) +{ + spwf_socket_t *socket = (spwf_socket_t*)handle; + nsapi_error_t ret; + SYNC_HANDLER; + + ret = _socket_recv(socket, data, size, true); + if (ret >= 0 && addr) { + *addr = socket->addr; + } + + return ret; +} + +void SpwfSAInterface::socket_attach(void *handle, void (*callback)(void *), void *data) +{ + spwf_socket_t *socket = (spwf_socket_t*)handle; + SYNC_HANDLER; + + if(!_socket_is_open(socket)) return; // might happen e.g. after module hard fault or voluntary disconnection + + _cbs[socket->internal_id].callback = callback; + _cbs[socket->internal_id].data = data; +} + +void SpwfSAInterface::event(void) { + for (int internal_id = 0; internal_id < SPWFSA_SOCKET_COUNT; internal_id++) { + if (_cbs[internal_id].callback && (_ids[internal_id].internal_id != SPWFSA_SOCKET_COUNT)) { + _cbs[internal_id].callback(_cbs[internal_id].data); + } + } +} + +nsapi_error_t SpwfSAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) +{ + SYNC_HANDLER; + + if((ssid == NULL) || (strlen(ssid) == 0)) { + return NSAPI_ERROR_PARAMETER; + } + + if((pass != NULL) && (strlen(pass) > 0)) { + if(strlen(pass) < sizeof(ap_pass)) { + if(security == NSAPI_SECURITY_NONE) { + return NSAPI_ERROR_PARAMETER; + } + } else { + return NSAPI_ERROR_PARAMETER; + } + } else if(security != NSAPI_SECURITY_NONE) { + return NSAPI_ERROR_PARAMETER; + } + + reset_credentials(); + + ap_sec = security; + strncpy(ap_ssid, ssid, sizeof(ap_ssid) - 1); + strncpy(ap_pass, pass, sizeof(ap_pass) - 1); + + return NSAPI_ERROR_OK; +} + +nsapi_error_t SpwfSAInterface::set_channel(uint8_t channel) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +int8_t SpwfSAInterface::get_rssi(void) +{ + SYNC_HANDLER; + + if(!_connected_to_network) return 0; + + _spwf.setTimeout(SPWF_MISC_TIMEOUT); + return _spwf.getRssi(); +} + +nsapi_size_or_error_t SpwfSAInterface::scan(WiFiAccessPoint *res, unsigned count) +{ + SYNC_HANDLER; + + nsapi_size_or_error_t ret; + + //initialize the device before scanning + if(!_isInitialized) + { + if(init() != NSAPI_ERROR_OK) return NSAPI_ERROR_DEVICE_ERROR; + } + + _spwf.setTimeout(SPWF_SCAN_TIMEOUT); + + { + BlockExecuter netsock_wa_obj(Callback<void()>(&_spwf, &SPWFSAxx::_unblock_event_callback), + Callback<void()>(&_spwf, &SPWFSAxx::_block_event_callback)); /* disable calling (external) callback in IRQ context */ + + /* block asynchronous indications */ + if(!_spwf._winds_off()) { + MBED_ASSERT(_spwf._call_event_callback_blocked == 1); + + return NSAPI_ERROR_DEVICE_ERROR; + } + + ret = _spwf.scan(res, count); + + /* unblock asynchronous indications */ + _spwf._winds_on(); + } + + MBED_ASSERT(!_spwf._is_event_callback_blocked()); + + //de-initialize the device after scanning + if(!_isInitialized) + { + nsapi_error_t err = disconnect(); + if(err != NSAPI_ERROR_OK) return err; + } + + return ret; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/SpwfSAInterface.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,443 @@ +/* mbed Microcontroller Library + * 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. + */ + +/** + ****************************************************************************** + * @file SpwfSAInterface.h + * @author STMicroelectronics + * @brief Header file of the NetworkStack for the SPWF Device + ****************************************************************************** + * @copy + * + * 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. + * + * <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2> + ****************************************************************************** + */ + +#ifndef SPWFSA_INTERFACE_H +#define SPWFSA_INTERFACE_H + +#include <limits.h> + +#include "mbed.h" + +#define IDW01M1 1 +#define IDW04A1 2 + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW01M1 +#include "SPWFSA01/SPWFSA01.h" +#elif MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 +#include "SPWFSA04/SPWFSA04.h" +#else +#error No (valid) Wi-Fi exapnsion board defined (MBED_CONF_IDW0XX1_EXPANSION_BOARD: options are IDW01M1 and IDW04A1) +#endif + +// Various timeouts for different SPWF operations +#define SPWF_CONNECT_TIMEOUT 60000 +#define SPWF_DISCONNECT_TIMEOUT 30002 +#define SPWF_HF_TIMEOUT 30001 +#define SPWF_NETLOST_TIMEOUT 30000 +#define SPWF_READ_BIN_TIMEOUT 13000 +#define SPWF_CLOSE_TIMEOUT 10001 +#define SPWF_SEND_TIMEOUT 10000 +#define SPWF_INIT_TIMEOUT 8000 +#define SPWF_OPEN_TIMEOUT 5002 +#define SPWF_CONN_SND_TIMEOUT 5001 +#define SPWF_SCAN_TIMEOUT 5000 +#define SPWF_MISC_TIMEOUT 301 +#define SPWF_RECV_TIMEOUT 300 + +/** SpwfSAInterface class + * Implementation of the NetworkStack for the SPWF Device + */ +// NOTE - betzw - TODO: MUST become singleton! +class SpwfSAInterface : public NetworkStack, public WiFiInterface +{ +public: + /** SpwfSAInterface constructor + * @param tx TX pin + * @param rx RX pin + * @param rts RTS pin + * @param cts CTS pin + * @param debug Enable debugging + * @param wakeup Wakeup pin + * @param reset Reset pin + */ + SpwfSAInterface(PinName tx = MBED_CONF_IDW0XX1_TX, PinName rx = MBED_CONF_IDW0XX1_RX, + PinName rts = SPWFSAXX_RTS_PIN, PinName cts = SPWFSAXX_CTS_PIN, bool debug = false, + PinName wakeup = SPWFSAXX_WAKEUP_PIN, PinName reset = SPWFSAXX_RESET_PIN); + + /** 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 nsapi_error_t 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 nsapi_error_t 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 nsapi_error_t 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 nsapi_error_t set_channel(uint8_t channel); + + /** Stop the interface + * @return `NSAPI_ERROR_OK` on success, negative on failure + */ + virtual nsapi_error_t 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 received + */ + 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 received + */ + 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. If the @a count is 0, function will only return count of available networks, so that + * user can allocated necessary memory. If the @count is grater than 0 and the @a ap is not NULL it'll be populated + * with discovered networks up to value of @a count. + * + * @param res Pointer to allocated array to store discovered AP + * @param count Size of allocated @a res array, or 0 to only count available AP + * @return Number of entries in @a, or if @a count was 0 number of available networks, + * negative on error see @a nsapi_error + */ + virtual nsapi_size_or_error_t 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; + +private: + /** 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 `NSAPI_ERROR_OK` on success, negative on failure + */ + virtual nsapi_error_t socket_open(void **handle, nsapi_protocol_t proto); + + /** Close the socket + * @param handle Socket handle + * @return `NSAPI_ERROR_OK` on success, negative on failure + * @note On failure, any memory associated with the socket must still + * be cleaned up + */ + virtual nsapi_error_t socket_close(void *handle); + + /** Bind a server socket to a specific port - NOT SUPPORTED + * + * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED + * + * @param handle Socket handle + * @param address Local address to listen for incoming connections on + * @return Not supported, returns NSAPI_ERROR_UNSUPPORTED + */ + virtual nsapi_error_t socket_bind(void *handle, const SocketAddress &address); + + /** Start listening for incoming connections - NOT SUPPORTED + * + * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED + * + * @param handle Socket handle + * @param backlog Number of pending connections that can be queued up at any + * one time [Default: 1] + * @return Not supported, returns NSAPI_ERROR_UNSUPPORTED + */ + virtual nsapi_error_t socket_listen(void *handle, int backlog); + + /** Connects this TCP socket to the server + * @param handle Socket handle + * @param address SocketAddress to connect to + * @return `NSAPI_ERROR_OK` on success, negative on failure + */ + virtual nsapi_error_t socket_connect(void *handle, const SocketAddress &address); + + /** Accept a new connection - NOT SUPPORTED + * + * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED + * + * @param handle Handle in which to store new socket + * @param server Socket handle to server to accept from + * @return Not supported, returns NSAPI_ERROR_UNSUPPORTED + */ + virtual nsapi_error_t 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_BLOCK + */ + virtual nsapi_size_or_error_t 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_BLOCK + */ + virtual nsapi_size_or_error_t 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_BLOCK + */ + virtual nsapi_size_or_error_t 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_BLOCK + */ + virtual nsapi_size_or_error_t 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: + /** spwf_socket class + * Implementation of SPWF socket structure + */ + typedef struct spwf_socket { + int8_t internal_id; + int spwf_id; + bool server_gone; + bool no_more_data; + nsapi_protocol_t proto; + SocketAddress addr; + } spwf_socket_t; + + bool _socket_is_open(spwf_socket_t *sock) { + if(((unsigned int)sock->internal_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)) { + return (_ids[sock->internal_id].internal_id == sock->internal_id); + } + return false; + } + + bool _socket_has_connected(spwf_socket_t *sock) { + return (_socket_is_open(sock) && (((unsigned int)sock->spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT))); + } + + bool _socket_is_still_connected(spwf_socket_t *sock) { + return (_socket_has_connected(sock) && !sock->server_gone); + } + + bool _socket_is_open(int internal_id) { + if(((unsigned int)internal_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)) { + return (_ids[internal_id].internal_id == internal_id); + } + return false; + } + + bool _socket_has_connected(int internal_id) { + if(!_socket_is_open(internal_id)) return false; + + spwf_socket_t &sock = _ids[internal_id]; + return (sock.spwf_id != SPWFSA_SOCKET_COUNT); + } + + bool _socket_is_still_connected(int internal_id) { + if(!_socket_has_connected(internal_id)) return false; + + spwf_socket_t &sock = _ids[internal_id]; + return (!sock.server_gone); + } + + void reset_credentials() { + memset(ap_ssid, 0, sizeof(ap_ssid)); + memset(ap_pass, 0, sizeof(ap_pass)); + ap_sec = NSAPI_SECURITY_NONE; + } + +#if MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW01M1 + SPWFSA01 _spwf; +#elif MBED_CONF_IDW0XX1_EXPANSION_BOARD == IDW04A1 + SPWFSA04 _spwf; +#endif + + bool _isInitialized; + bool _dbg_on; + bool _connected_to_network; + + spwf_socket_t _ids[SPWFSA_SOCKET_COUNT]; + struct { + void (*callback)(void *); + void *data; + } _cbs[SPWFSA_SOCKET_COUNT]; + int _internal_ids[SPWFSA_SOCKET_COUNT]; + +#if MBED_CONF_RTOS_PRESENT + Mutex _spwf_mutex; +#endif + + char ap_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */ + nsapi_security_t ap_sec; + char ap_pass[64]; /* The longest allowed passphrase */ + +private: + void event(void); + nsapi_error_t init(void); + nsapi_size_or_error_t _socket_recv(void *handle, void *data, unsigned size, bool datagram); + + + int get_internal_id(int spwf_id) { // checks also if `spwf_id` is (still) "valid" + if(((unsigned int)spwf_id) < ((unsigned int)SPWFSA_SOCKET_COUNT)) { // valid `spwf_id` + int internal_id = _internal_ids[spwf_id]; + if((_socket_is_open(internal_id)) && (_ids[internal_id].spwf_id == spwf_id)) { + return internal_id; + } else { + return SPWFSA_SOCKET_COUNT; + } + } else { // invalid `spwf_id` + return SPWFSA_SOCKET_COUNT; + } + } + + /* Called at initialization or after module hard fault */ + void inner_constructor() { + memset(_ids, 0, sizeof(_ids)); + memset(_cbs, 0, sizeof(_cbs)); + + for (int sock_cnt = 0; sock_cnt < SPWFSA_SOCKET_COUNT; sock_cnt++) { + _ids[sock_cnt].internal_id = SPWFSA_SOCKET_COUNT; + _ids[sock_cnt].spwf_id = SPWFSA_SOCKET_COUNT; + _internal_ids[sock_cnt] = SPWFSA_SOCKET_COUNT; + } + + _spwf.attach(this, &SpwfSAInterface::event); + + _connected_to_network = false; + _isInitialized = false; + } + +private: + friend class SPWFSAxx; + friend class SPWFSA01; + friend class SPWFSA04; +}; + +#define CHECK_NOT_CONNECTED_ERR() { \ + if(!_connected_to_network) return NSAPI_ERROR_NO_CONNECTION; \ +} \ + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/mbed_app_idw01m1.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,11 @@ +{ + "target_overrides": { + "*": { + "idw0xx1.expansion-board": "IDW01M1", + "drivers.uart-serial-txbuf-size": 512, + "drivers.uart-serial-rxbuf-size": 512, + "idw0xx1.tx": "PA_9", + "idw0xx1.rx": "PA_10" + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/mbed_app_idw04a1.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,12 @@ +{ + "target_overrides": { + "*": { + "idw0xx1.expansion-board": "IDW04A1", + "drivers.uart-serial-txbuf-size": 512, + "drivers.uart-serial-rxbuf-size": 512, + "idw0xx1.tx": "D8", + "idw0xx1.rx": "D2" + } + }, + "macros": ["IDW04A1_WIFI_HW_BUG_WA"] +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wifi-x-nucleo-idw01m1/mbed_lib.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,17 @@ +{ + "name": "idw0xx1", + "config": { + "expansion-board":{ + "help": "Options are IDW01M1 and IDW04A1", + "value": "IDW01M1" + }, + "tx":{ + "help": "TX pin for serial connection to external device", + "value": "NC" + }, + "rx":{ + "help": "RX pin for serial connection to external device", + "value": "NC" + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/wizfi310-driver/#f00390eb6a3e6f003720ca1d589c150b92aa745c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/FETCH_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +f00390eb6a3e6f003720ca1d589c150b92aa745c branch 'master' of https://github.com/ARMmbed/wizfi310-driver
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/ORIG_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +f00390eb6a3e6f003720ca1d589c150b92aa745c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/config Wed Sep 05 14:28:24 2018 +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/wizfi310-driver/ +[branch "master"] + remote = origin + merge = refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/wizfi310-driver/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/info/exclude Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 f00390eb6a3e6f003720ca1d589c150b92aa745c www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504031 +0000 clone: from https://github.com/ARMmbed/wizfi310-driver/ +f00390eb6a3e6f003720ca1d589c150b92aa745c e0f7b9355e7e23daaa2d3f1d5c389c52528d6178 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504031 +0000 checkout: moving from master to e0f7b9355e7e23daaa2d3f1d5c389c52528d6178 +e0f7b9355e7e23daaa2d3f1d5c389c52528d6178 f00390eb6a3e6f003720ca1d589c150b92aa745c www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504048 +0000 checkout: moving from e0f7b9355e7e23daaa2d3f1d5c389c52528d6178 to master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 f00390eb6a3e6f003720ca1d589c150b92aa745c www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504031 +0000 clone: from https://github.com/ARMmbed/wizfi310-driver/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 f00390eb6a3e6f003720ca1d589c150b92aa745c www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504031 +0000 clone: from https://github.com/ARMmbed/wizfi310-driver/
Binary file easy-connect/wizfi310-driver/.git/objects/pack/pack-f49da3dab872e56eb9417504c8576ea9396c9055.idx has changed
Binary file easy-connect/wizfi310-driver/.git/objects/pack/pack-f49da3dab872e56eb9417504c8576ea9396c9055.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +# pack-refs with: peeled +f00390eb6a3e6f003720ca1d589c150b92aa745c refs/remotes/origin/master +e78ec79cf496133c2afe4196d953b69af5b3c6ab refs/tags/V1.0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +f00390eb6a3e6f003720ca1d589c150b92aa745c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<root> + <node _type="integer" _key="update">0</node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/README.md Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,34 @@ +# The WizFi310 WiFi driver for mbed-os +The mbed OS driver for the WizFi310 Wi-Fi module + +## Testing +The WizFi310 library contains the core network tests taken from mbed OS. To run the tests you will need mbed CLI and mbed OS. + +First, setup the the WizFi310-driver and mbed-os repositories for testing: +``` bash +# Sets up the WizFi310 for testing +mbed import wizfi310-driver +cd wizfi310-driver +mbed add mbed-os +``` + +Now you should be able to run the network tests with `mbed test`: +``` bash +# Runs the WizFi310 network tests, requires a wifi access point +mbed test -t <COMPILER HERE> -m <BOARD HERE> -n tests-net* --compile -DMBED_CFG_WIZFI310_SSID=<SSID HERE> -DMBED_CFG_WIZFI310_PASS=<PASS HERE> +mbed test -t <COMPILER HERE> -m <BOARD HERE> -n tests-net* --run --verbose +``` + +There are a couple other options that can be used during testing: +- MBED_CFG_WIZFI310_SSID - SSID of the wifi access point to connect to +- MBED_CFG_WIZFI310_PASS - Passphrase of the wifi access point to connect to +- MBED_CFG_WIZFI310_TX - TX pin for the WizFi310 serial connection (defaults to D1) +- MBED_CFG_WIZFI310_RX - TX pin for the WizFi310 serial connection (defaults to D0) +- MBED_CFG_WIZFI310_DEBUG - Enabled debug output from the WizFi310 + +For example, here is how to enabled the debug output from the WizFi310: +``` bash +# Run the WizFi310 network tests with debug output, requires a wifi access point +mbed test -t <COMPILER HERE> -m <BOARD HERE> -n tests-net* --compile -DMBED_CFG_WIZFI310_SSID=<SSID HERE> -DMBED_CFG_WIZFI310_PASS=<PASS HERE> -MBED_CFG_WIZFI310_DEBUG=true +mbed test -t <COMPILER HERE> -m <BOARD HERE> -n tests-net* --run --verbose +```
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/connectivity/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,76 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" + +#include "WizFi310Interface.h" + +using namespace utest::v1; + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Bringing the network up and down +template <int COUNT> +void test_bring_up_down() { + WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); + net.set_credentials(STRINGIZEWIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + + for (int i = 0; i < COUNT; i++) { + int err = net.connect(); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: IP Address %s\r\n", net.get_ip_address()); + printf("MBED: Netmask %s\r\n", net.get_netmask()); + printf("MBED: Gateway %s\r\n", net.get_gateway()); + TEST_ASSERT(net.get_ip_address()); + TEST_ASSERT(net.get_netmask()); + TEST_ASSERT(net.get_gateway()); + + UDPSocket udp; + err = udp.open(&net); + TEST_ASSERT_EQUAL(0, err); + err = udp.close(); + TEST_ASSERT_EQUAL(0, err); + + TCPSocket tcp; + err = tcp.open(&net); + TEST_ASSERT_EQUAL(0, err); + err = tcp.close(); + TEST_ASSERT_EQUAL(0, err); + + err = net.disconnect(); + TEST_ASSERT_EQUAL(0, err); + } +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Bringing the network up and down", test_bring_up_down<1>), + Case("Bringing the network up and down twice", test_bring_up_down<2>), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/gethostbyname/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,118 @@ +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include "WizFi310Interface.h" + +using namespace utest::v1; + +// Hostname for testing against +// Must have A and AAAA records +#ifndef MBED_DNS_TEST_HOST +#define MBED_DNS_TEST_HOST "connector.mbed.com" +#endif + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + +// Address info from stack +const char *ip_literal; +nsapi_version_t ip_pref; +const char *ip_pref_repr; + +// Network setup +WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); +void net_bringup() { + int err = net.connect(STRINGIZE(MBED_CFG_WIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + TEST_ASSERT_EQUAL(0, err); + printf("MBED: Connected to network\n"); + printf("MBED: IP Address: %s\n", net.get_ip_address()); + + ip_literal = net.get_ip_address(); + ip_pref = SocketAddress(ip_literal).get_ip_version(); + ip_pref_repr = (ip_pref == NSAPI_IPv4) ? "ipv4" : + (ip_pref == NSAPI_IPv6) ? "ipv6" : "unspec"; +} + + +// DNS tests +void test_dns_query() { + SocketAddress addr; + int err = net.gethostbyname(MBED_DNS_TEST_HOST, &addr); + printf("DNS: query \"%s\" => \"%s\"\n", + MBED_DNS_TEST_HOST, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); +} + +void test_dns_query_pref() { + SocketAddress addr; + int err = net.gethostbyname(MBED_DNS_TEST_HOST, &addr, ip_pref); + printf("DNS: query %s \"%s\" => \"%s\"\n", + ip_pref_repr, MBED_DNS_TEST_HOST, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT_EQUAL(ip_pref, addr.get_ip_version()); +} + +void test_dns_literal() { + SocketAddress addr; + int err = net.gethostbyname(ip_literal, &addr); + printf("DNS: literal \"%s\" => \"%s\"\n", + ip_literal, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT(strcmp(ip_literal, addr.get_ip_address()) == 0); +} + +void test_dns_literal_pref() { + SocketAddress addr; + int err = net.gethostbyname(ip_literal, &addr, ip_pref); + printf("DNS: literal %s \"%s\" => \"%s\"\n", + ip_pref_repr, ip_literal, addr.get_ip_address()); + + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT((bool)addr); + TEST_ASSERT(strlen(addr.get_ip_address()) > 1); + TEST_ASSERT_EQUAL(ip_pref, addr.get_ip_version()); + TEST_ASSERT(strcmp(ip_literal, addr.get_ip_address()) == 0); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + net_bringup(); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("DNS query", test_dns_query), + Case("DNS preference query", test_dns_query_pref), + Case("DNS literal", test_dns_literal), + Case("DNS preference literal", test_dns_literal_pref), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/host_tests/tcp_echo.py Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,195 @@ +# Copyright 2015 ARM Limited, All rights reserved +# +# 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. + +import sys +import select +import socket +import logging +from threading import Thread +from sys import stdout +from SocketServer import BaseRequestHandler, TCPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class TCPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ + Handles a connection. Test starts by client(i.e. mbed) connecting to server. + This connection handler receives data and echoes back to the client util + {{end}} is received. Then it sits on recv() for client to terminate the + connection. + + Note: reason for not echoing data back after receiving {{end}} is that send + fails raising a SocketError as client closes connection. + """ + while self.server.isrunning(): + try: + data = self.recv() + if not data: break + except Exception as e: + break + + try: + # echo data back to the client + self.send(data) + except Exception as e: + break + + def recv(self): + """ + Try to receive until server is shutdown + """ + while self.server.isrunning(): + rl, wl, xl = select.select([self.request], [], [], 1) + if len(rl): + return self.request.recv(1024) + + def send(self, data): + """ + Try to send until server is shutdown + """ + while self.server.isrunning(): + rl, wl, xl = select.select([], [self.request], [], 1) + if len(wl): + self.request.sendall(data) + break + + +class TCPServerWrapper(TCPServer): + """ + Wrapper over TCP server to implement server initiated shutdown. + Adds a flag:= running that a request handler can check and come out of + recv loop when shutdown is called. + """ + + def __init__(self, addr, request_handler): + # hmm, TCPServer is not sub-classed from object! + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).__init__(addr, request_handler) + else: + TCPServer.__init__(self, addr, request_handler) + self.running = False + + def serve_forever(self): + self.running = True + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).serve_forever() + else: + TCPServer.serve_forever(self) + + def shutdown(self): + self.running = False + if issubclass(TCPServer, object): + super(TCPServerWrapper, self).shutdown() + else: + TCPServer.shutdown(self) + + def isrunning(self): + return self.running + + +class TCPEchoClientTest(BaseHostTest): + + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_tcp_server(self): + """ + sets up a TCP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_tcp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = TCPServerWrapper((self.SERVER_IP, self.SERVER_PORT), TCPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for TCP connections: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=TCPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_tcp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join()
Binary file easy-connect/wizfi310-driver/TESTS/net/host_tests/tcp_echo.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/host_tests/udp_echo.py Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,127 @@ +""" +mbed SDK +Copyright (c) 2011-2013 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. +""" + +import sys +import socket +from sys import stdout +from threading import Thread +from SocketServer import BaseRequestHandler, UDPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class UDPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ UDP packet handler. Echoes data back to sender's address. + """ + data, sock = self.request + sock.sendto(data, self.client_address) + + +class UDPEchoClientTest(BaseHostTest): + + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_udp_server(self): + """ + sets up a UDP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_udp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_udp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join()
Binary file easy-connect/wizfi310-driver/TESTS/net/host_tests/udp_echo.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/host_tests/udp_shotgun.py Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,142 @@ +""" +mbed SDK +Copyright (c) 2011-2013 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. +""" + +import sys +import socket +import json +import random +import itertools +import time +from sys import stdout +from threading import Thread +from SocketServer import BaseRequestHandler, UDPServer +from mbed_host_tests import BaseHostTest, event_callback + + +class UDPEchoClientHandler(BaseRequestHandler): + def handle(self): + """ UDP packet handler. Responds with multiple simultaneous packets + """ + data, sock = self.request + pattern = [ord(d) << 4 for d in data] + + # Each byte in request indicates size of packet to recieve + # Each packet size is shifted over by 4 to fit in a byte, which + # avoids any issues with endianess or decoding + for packet in pattern: + data = [random.randint(0, 255) for _ in range(packet-1)] + data.append(reduce(lambda a,b: a^b, data)) + data = ''.join(map(chr, data)) + sock.sendto(data, self.client_address) + + # Sleep a tiny bit to compensate for local network + time.sleep(0.01) + + +class UDPEchoClientTest(BaseHostTest): + def __init__(self): + """ + Initialise test parameters. + + :return: + """ + BaseHostTest.__init__(self) + self.SERVER_IP = None # Will be determined after knowing the target IP + self.SERVER_PORT = 0 # Let TCPServer choose an arbitrary port + self.server = None + self.server_thread = None + self.target_ip = None + + @staticmethod + def find_interface_to_target_addr(target_ip): + """ + Finds IP address of the interface through which it is connected to the target. + + :return: + """ + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((target_ip, 0)) # Target IP, any port + except socket.error: + s.connect((target_ip, 8000)) # Target IP, 'random' port + ip = s.getsockname()[0] + s.close() + return ip + + def setup_udp_server(self): + """ + sets up a UDP server for target to connect and send test data. + + :return: + """ + # !NOTE: There should mechanism to assert in the host test + if self.SERVER_IP is None: + self.log("setup_udp_server() called before determining server IP!") + self.notify_complete(False) + + # Returning none will suppress host test from printing success code + self.server = UDPServer((self.SERVER_IP, self.SERVER_PORT), UDPEchoClientHandler) + ip, port = self.server.server_address + self.SERVER_PORT = port + self.server.allow_reuse_address = True + self.log("HOST: Listening for UDP packets: " + self.SERVER_IP + ":" + str(self.SERVER_PORT)) + self.server_thread = Thread(target=UDPEchoClientTest.server_thread_func, args=(self,)) + self.server_thread.start() + + @staticmethod + def server_thread_func(this): + """ + Thread function to run TCP server forever. + + :param this: + :return: + """ + this.server.serve_forever() + + @event_callback("target_ip") + def _callback_target_ip(self, key, value, timestamp): + """ + Callback to handle reception of target's IP address. + + :param key: + :param value: + :param timestamp: + :return: + """ + self.target_ip = value + self.SERVER_IP = self.find_interface_to_target_addr(self.target_ip) + self.setup_udp_server() + + @event_callback("host_ip") + def _callback_host_ip(self, key, value, timestamp): + """ + Callback for request for host IP Addr + + """ + self.send_kv("host_ip", self.SERVER_IP) + + @event_callback("host_port") + def _callback_host_port(self, key, value, timestamp): + """ + Callback for request for host port + """ + self.send_kv("host_port", self.SERVER_PORT) + + def teardown(self): + if self.server: + self.server.shutdown() + self.server_thread.join()
Binary file easy-connect/wizfi310-driver/TESTS/net/host_tests/udp_shotgun.pyc has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/tcp_echo/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,112 @@ +#include "mbed.h" +#include "WizFi310Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 256 +#endif + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + +namespace { + char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + const char ASCII_MAX = '~' - ' '; +} + +void prep_buffer(char *tx_buffer, size_t tx_size) { + for (size_t i=0; i<tx_size; ++i) { + tx_buffer[i] = (rand() % 10) + '0'; + } +} + +void test_tcp_echo() { + WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); + int err = net.connect(STRINGIZE(MBED_CFG_WIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + + if (err) { + printf("MBED: failed to connect with an error of %d\r\n", err); + TEST_ASSERT_EQUAL(0, err); + } + + printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + bool result = false; + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + + TCPSocket sock(&net); + SocketAddress tcp_addr(ipbuf, port); + if (sock.connect(tcp_addr) == 0) { + printf("HTTP: Connected to %s:%d\r\n", ipbuf, port); + printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer)); + printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer)); + + prep_buffer(tx_buffer, sizeof(tx_buffer)); + sock.send(tx_buffer, sizeof(tx_buffer)); + printf("MBED: Finished sending\r\n"); + // Server will respond with HTTP GET's success code + const int ret = sock.recv(rx_buffer, sizeof(rx_buffer)); + printf("MBED: Finished receiving\r\n"); + + result = !memcmp(tx_buffer, rx_buffer, sizeof(tx_buffer)); + TEST_ASSERT_EQUAL(ret, sizeof(rx_buffer)); + TEST_ASSERT_EQUAL(true, result); + } + + sock.close(); + net.disconnect(); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP echo", test_tcp_echo), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/tcp_echo_parallel/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,159 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel tests are not supported by default +#endif + +#include "mbed.h" +#include "WizFi310Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_ECHO_THREADS +#define MBED_CFG_TCP_CLIENT_ECHO_THREADS 3 +#endif + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); +SocketAddress tcp_addr; +Mutex iomutex; + +void prep_buffer(char *tx_buffer, size_t tx_size) { + for (size_t i=0; i<tx_size; ++i) { + tx_buffer[i] = (rand() % 10) + '0'; + } +} + + +// Each echo class is in charge of one parallel transaction +class Echo { +private: + char tx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE]; + char rx_buffer[MBED_CFG_TCP_CLIENT_ECHO_BUFFER_SIZE]; + + TCPSocket sock; + Thread thread; + +public: + // Limiting stack size to 1k + Echo(): thread(osPriorityNormal, 1024) { + } + + void start() { + osStatus status = thread.start(callback(this, &Echo::echo)); + TEST_ASSERT_EQUAL(osOK, status); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void echo() { + int err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + + iomutex.lock(); + printf("HTTP: Connected to %s:%d\r\n", + tcp_addr.get_ip_address(), tcp_addr.get_port()); + printf("tx_buffer buffer size: %u\r\n", sizeof(tx_buffer)); + printf("rx_buffer buffer size: %u\r\n", sizeof(rx_buffer)); + iomutex.unlock(); + + prep_buffer(tx_buffer, sizeof(tx_buffer)); + sock.send(tx_buffer, sizeof(tx_buffer)); + + // Server will respond with HTTP GET's success code + const int ret = sock.recv(rx_buffer, sizeof(rx_buffer)); + bool result = !memcmp(tx_buffer, rx_buffer, sizeof(tx_buffer)); + TEST_ASSERT_EQUAL(ret, sizeof(rx_buffer)); + TEST_ASSERT_EQUAL(true, result); + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } +}; + +Echo *echoers[MBED_CFG_TCP_CLIENT_ECHO_THREADS]; + + +void test_tcp_echo_parallel() { + int err = net.connect(STRINGIZE(MBED_CFG_WIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + tcp_addr.set_ip_address(ipbuf); + tcp_addr.set_port(port); + + // Startup echo threads in parallel + for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { + echoers[i] = new Echo; + echoers[i]->start(); + } + + for (int i = 0; i < MBED_CFG_TCP_CLIENT_ECHO_THREADS; i++) { + echoers[i]->join(); + delete echoers[i]; + } + + net.disconnect(); +} + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP echo parallel", test_tcp_echo_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/tcp_hello_world/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,115 @@ +#include <algorithm> +#include "mbed.h" +#include "WizFi310Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +namespace { + // Test connection information + const char *HTTP_SERVER_NAME = "os.mbed.com"; + const char *HTTP_SERVER_FILE_PATH = "/media/uploads/mbed_official/hello.txt"; + const int HTTP_SERVER_PORT = 80; +#if defined(TARGET_VK_RZ_A1H) + const int RECV_BUFFER_SIZE = 300; +#else + const int RECV_BUFFER_SIZE = 512; +#endif + // Test related data + const char *HTTP_OK_STR = "200 OK"; + const char *HTTP_HELLO_STR = "Hello world!"; + + // Test buffers + char buffer[RECV_BUFFER_SIZE] = {0}; +} + +bool find_substring(const char *first, const char *last, const char *s_first, const char *s_last) { + const char *f = std::search(first, last, s_first, s_last); + return (f != last); +} + +void test_tcp_hello_world() { + bool result = false; + WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); + net.connect(STRINGIZE(MBED_CFG_WIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + printf("TCP client IP Address is %s\r\n", net.get_ip_address()); + + TCPSocket sock(&net); + printf("HTTP: Connection to %s:%d\r\n", HTTP_SERVER_NAME, HTTP_SERVER_PORT); + if (sock.connect(HTTP_SERVER_NAME, HTTP_SERVER_PORT) == 0) { + printf("HTTP: OK\r\n"); + + // We are constructing GET command like this: + // GET http://os.mbed.com/media/uploads/mbed_official/hello.txt HTTP/1.0\n\n + strcpy(buffer, "GET http://"); + strcat(buffer, HTTP_SERVER_NAME); + strcat(buffer, HTTP_SERVER_FILE_PATH); + strcat(buffer, " HTTP/1.0\n\n"); + // Send GET command + sock.send(buffer, strlen(buffer)); + + // Server will respond with HTTP GET's success code + const int ret = sock.recv(buffer, sizeof(buffer) - 1); + buffer[ret] = '\0'; + + // Find 200 OK HTTP status in reply + bool found_200_ok = find_substring(buffer, buffer + ret, HTTP_OK_STR, HTTP_OK_STR + strlen(HTTP_OK_STR)); + // Find "Hello World!" string in reply + bool found_hello = find_substring(buffer, buffer + ret, HTTP_HELLO_STR, HTTP_HELLO_STR + strlen(HTTP_HELLO_STR)); + + TEST_ASSERT_TRUE(found_200_ok); + TEST_ASSERT_TRUE(found_hello); + + if (found_200_ok && found_hello) result = true; + + printf("HTTP: Received %d chars from server\r\n", ret); + printf("HTTP: Received 200 OK status ... %s\r\n", found_200_ok ? "[OK]" : "[FAIL]"); + printf("HTTP: Received '%s' status ... %s\r\n", HTTP_HELLO_STR, found_hello ? "[OK]" : "[FAIL]"); + printf("HTTP: Received message:\r\n"); + printf("%s", buffer); + sock.close(); + } else { + printf("HTTP: ERROR\r\n"); + } + + net.disconnect(); + printf("Network disconnected\r\n"); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP hello world", test_tcp_hello_world), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/tcp_packet_pressure/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,253 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Pressure tests are not supported by default +#endif + +#include "mbed.h" +#include "WizFi310Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Shared buffer for network transactions +uint8_t *buffer; +size_t buffer_size; + +// Tries to get the biggest buffer possible on the device. Exponentially +// grows a buffer until heap runs out of space, and uses half to leave +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +void test_tcp_packet_pressure() { + generate_buffer(&buffer, &buffer_size, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); + printf("MBED: Generated buffer %d\r\n", buffer_size); + + WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); + int err = net.connect(STRINGIZE(MBED_CFG_WIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + + TCPSocket sock; + SocketAddress tcp_addr(ipbuf, port); + + Timer timer; + timer.start(); + + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + printf("TCP: %s:%d streaming %d bytes\r\n", ipbuf, port, size); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out data + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.send(buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: tx -> %d\r\n", td); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, + // cut buffer in half + if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: Not sent (%d), window = %d\r\n", td, window); + } + } + } + + // Verify recieved data + while (rx_count < size) { + int rd = sock.recv(buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + if (rd > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("TCP: rx <- %d\r\n", rd); + } + int diff = rx_seq.cmp(buffer, rd); + TEST_ASSERT_EQUAL(0, diff); + rx_seq.skip(rd); + rx_count += rd; + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net.disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP packet pressure", test_tcp_packet_pressure), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/tcp_packet_pressure_parallel/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,315 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default +#endif + +#include "mbed.h" +#include "WizFi310Interface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS 3 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + + +// Tries to get the biggest buffer possible on the device. Exponentially +// grows a buffer until heap runs out of space, and uses half to leave +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +// Global variables shared between pressure tests +WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); +SocketAddress tcp_addr; +Timer timer; +Mutex iomutex; + +// Single instance of a pressure test +class PressureTest { +private: + uint8_t *buffer; + size_t buffer_size; + + TCPSocket sock; + Thread thread; + +public: + PressureTest(uint8_t *buffer, size_t buffer_size) + : buffer(buffer), buffer_size(buffer_size) { + } + + void start() { + osStatus status = thread.start(callback(this, &PressureTest::run)); + TEST_ASSERT_EQUAL(osOK, status); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void run() { + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + int err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + iomutex.lock(); + printf("TCP: %s:%d streaming %d bytes\r\n", + tcp_addr.get_ip_address(), tcp_addr.get_port(), size); + iomutex.unlock(); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out data + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.send(buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: tx -> %d\r\n", td); + iomutex.unlock(); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, + // cut buffer in half + if (window > MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: Not sent (%d), window = %d\r\n", td, window); + iomutex.unlock(); + } + } + } + + // Verify recieved data + while (rx_count < size) { + int rd = sock.recv(buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + if (rd > 0) { + if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("TCP: rx <- %d\r\n", rd); + iomutex.unlock(); + } + int diff = rx_seq.cmp(buffer, rd); + TEST_ASSERT_EQUAL(0, diff); + rx_seq.skip(rd); + rx_count += rd; + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + } +}; + +PressureTest *pressure_tests[MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS]; + + +void test_tcp_packet_pressure_parallel() { + uint8_t *buffer; + size_t buffer_size; + generate_buffer(&buffer, &buffer_size, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX); + + size_t buffer_subsize = buffer_size / MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; + printf("MBED: Generated buffer %d\r\n", buffer_size); + printf("MBED: Split into %d buffers %d\r\n", + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS, + buffer_subsize); + + int err = net.connect(STRINGIZE(MBED_CFG_WIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + tcp_addr.set_ip_address(ipbuf); + tcp_addr.set_port(port); + + timer.start(); + + // Startup pressure tests in parallel + for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); + pressure_tests[i]->start(); + } + + for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i]->join(); + delete pressure_tests[i]; + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS* + 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net.disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "tcp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("TCP packet pressure parallel", test_tcp_packet_pressure_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
Binary file easy-connect/wizfi310-driver/TESTS/net/udp_dtls_handshake/.main.cpp.swp has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/udp_dtls_handshake/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,159 @@ +#include "mbed.h" +#include "WizFi310Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE +#define MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE 512 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES +#define MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES 16 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN +#define MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN 112, 384, 200, 219, 25 +#endif + +#ifndef MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT +#define MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT 1500 +#endif + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + +uint8_t buffer[MBED_CFG_UDP_DTLS_HANDSHAKE_BUFFER_SIZE] = {0}; +int udp_dtls_handshake_pattern[] = {MBED_CFG_UDP_DTLS_HANDSHAKE_PATTERN}; +const int udp_dtls_handshake_count = sizeof(udp_dtls_handshake_pattern) / sizeof(int); + +void test_udp_dtls_handshake() { + WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); + int err = net.connect(STRINGIZE(MBED_CFG_WIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: UDPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + bool result = false; + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); + + // align each size to 4-bits + for (int i = 0; i < udp_dtls_handshake_count; i++) { + udp_dtls_handshake_pattern[i] = (~0xf & udp_dtls_handshake_pattern[i]) + 0x10; + } + + printf("MBED: DTLS pattern ["); + for (int i = 0; i < udp_dtls_handshake_count; i++) { + printf("%d", udp_dtls_handshake_pattern[i]); + if (i != udp_dtls_handshake_count-1) { + printf(", "); + } + } + printf("]\r\n"); + + UDPSocket sock; + SocketAddress udp_addr(ipbuf, port); + sock.set_timeout(MBED_CFG_UDP_DTLS_HANDSHAKE_TIMEOUT); + + for (int attempt = 0; attempt < MBED_CFG_UDP_DTLS_HANDSHAKE_RETRIES; attempt++) { + err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + + for (int i = 0; i < udp_dtls_handshake_count; i++) { + buffer[i] = udp_dtls_handshake_pattern[i] >> 4; + } + + err = sock.sendto(udp_addr, buffer, udp_dtls_handshake_count); + printf("UDP: tx -> %d\r\n", err); + TEST_ASSERT_EQUAL(udp_dtls_handshake_count, err); + + int step = 0; + while (step < udp_dtls_handshake_count) { + err = sock.recvfrom(NULL, buffer, sizeof(buffer)); + printf("UDP: rx <- %d ", err); + + // check length + if (err != udp_dtls_handshake_pattern[step]) { + printf("x (expected %d)\r\n", udp_dtls_handshake_pattern[step]); + break; + } + + // check quick xor of packet + uint8_t check = 0; + for (int j = 0; j < udp_dtls_handshake_pattern[step]; j++) { + check ^= buffer[j]; + } + + if (check != 0) { + printf("x (checksum 0x%02x)\r\n", check); + break; + } + + // successfully got a packet + printf("\r\n"); + step += 1; + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + + // got through all steps, test passed + if (step == udp_dtls_handshake_count) { + result = true; + break; + } + } + + net.disconnect(); + TEST_ASSERT_EQUAL(true, result); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_shotgun"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP DTLS handshake", test_udp_dtls_handshake), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/udp_echo/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,151 @@ +#include "mbed.h" +#include "WizFi310Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT +#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 +#endif + +#ifndef MBED_CFG_WIZFI310_TX +#define MBED_CFG_WIZFI310_TX D1 +#endif + +#ifndef MBED_CFG_WIZFI310_RX +#define MBED_CFG_WIZFI310_RX D0 +#endif + +#ifndef MBED_CFG_WIZFI310_DEBUG +#define MBED_CFG_WIZFI310_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +namespace { + char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE] = {0}; + const char ASCII_MAX = '~' - ' '; + const int ECHO_LOOPS = 16; + char uuid[48] = {0}; +} + +void prep_buffer(char *uuid, char *tx_buffer, size_t tx_size) { + size_t i = 0; + + memcpy(tx_buffer, uuid, strlen(uuid)); + i += strlen(uuid); + + tx_buffer[i++] = ' '; + + for (; i<tx_size; ++i) { + tx_buffer[i] = (rand() % 10) + '0'; + } +} + +void test_udp_echo() { + WizFi310Interface net(MBED_CFG_WIZFI310_TX, MBED_CFG_WIZFI310_RX, MBED_CFG_WIZFI310_DEBUG); + + int err = net.connect(STRINGIZE(MBED_CFG_WIZFI310_SSID), STRINGIZE(MBED_CFG_WIZFI310_PASS)); + TEST_ASSERT_EQUAL(0, err); + + if (err) { + printf("MBED: failed to connect with an error of %d\r\n", err); + TEST_ASSERT_EQUAL(0, err); + } + + printf("UDP client IP Address is %s\n", net.get_ip_address()); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + UDPSocket sock; + sock.open(&net); + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); + SocketAddress udp_addr(ipbuf, port); + + int success = 0; + for (int i = 0; success < ECHO_LOOPS; i++) { + prep_buffer(uuid, tx_buffer, sizeof(tx_buffer)); + const int ret = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer)); + if (ret >= 0) { + printf("[%02d] sent %d bytes - %.*s \n", i, ret, ret, tx_buffer); + } else { + printf("[%02d] Network error %d\n", i, ret); + continue; + } + + SocketAddress temp_addr; + const int n = sock.recvfrom(&temp_addr, rx_buffer, sizeof(rx_buffer)); + if (n >= 0) { + printf("[%02d] recv %d bytes - %.*s \n", i, n, n, tx_buffer); + } else { + printf("[%02d] Network error %d\n", i, n); + continue; + } + + if ((temp_addr == udp_addr && + n == sizeof(tx_buffer) && + memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { + success += 1; + + printf("[%02d] success #%d\n", i, success); + continue; + } + + // failed, clean out any remaining bad packets + sock.set_timeout(0); + while (true) { + err = sock.recvfrom(NULL, NULL, 0); + if (err == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + } + + sock.close(); + net.disconnect(); + TEST_ASSERT_EQUAL(ECHO_LOOPS, success); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP echo", test_udp_echo), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/udp_echo_parallel/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,231 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE +#define MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT +#define MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT 500 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_ECHO_THREADS +#define MBED_CFG_UDP_CLIENT_ECHO_THREADS 3 +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +const int ECHO_LOOPS = 16; +ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); +SocketAddress udp_addr; +Mutex iomutex; +char uuid[48] = {0}; + +// NOTE: assuming that "id" stays in the single digits +void prep_buffer(int id, char *uuid, char *tx_buffer, size_t tx_size) { + size_t i = 0; + + tx_buffer[i++] = '0' + id; + tx_buffer[i++] = ' '; + + memcpy(tx_buffer+i, uuid, strlen(uuid)); + i += strlen(uuid); + + tx_buffer[i++] = ' '; + + for (; i<tx_size; ++i) { + tx_buffer[i] = (rand() % 10) + '0'; + } +} + + +// Each echo class is in charge of one parallel transaction +class Echo { +private: + char tx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE]; + char rx_buffer[MBED_CFG_UDP_CLIENT_ECHO_BUFFER_SIZE]; + + UDPSocket sock; + Thread thread; + bool result; + int id; + char *uuid; + +public: + // Limiting stack size to 1k + Echo(): thread(osPriorityNormal, 1024), result(false) { + } + + void start(int id, char *uuid) { + this->id = id; + this->uuid = uuid; + osStatus status = thread.start(callback(this, &Echo::echo)); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void echo() { + int success = 0; + + int err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + + for (int i = 0; success < ECHO_LOOPS; i++) { + prep_buffer(id, uuid, tx_buffer, sizeof(tx_buffer)); + const int ret = sock.sendto(udp_addr, tx_buffer, sizeof(tx_buffer)); + if (ret >= 0) { + iomutex.lock(); + printf("[ID:%01d][%02d] sent %d bytes - %.*s \n", id, i, ret, ret, tx_buffer); + iomutex.unlock(); + } else { + iomutex.lock(); + printf("[ID:%01d][%02d] Network error %d\n", id, i, ret); + iomutex.unlock(); + continue; + } + + SocketAddress temp_addr; + const int n = sock.recvfrom(&temp_addr, rx_buffer, sizeof(rx_buffer)); + if (n >= 0) { + iomutex.lock(); + printf("[ID:%01d][%02d] recv %d bytes - %.*s \n", id, i, n, n, tx_buffer); + iomutex.unlock(); + } else { + iomutex.lock(); + printf("[ID:%01d][%02d] Network error %d\n", id, i, n); + iomutex.unlock(); + continue; + } + + if ((temp_addr == udp_addr && + n == sizeof(tx_buffer) && + memcmp(rx_buffer, tx_buffer, sizeof(rx_buffer)) == 0)) { + success += 1; + iomutex.lock(); + printf("[ID:%01d][%02d] success #%d\n", id, i, success); + iomutex.unlock(); + continue; + } + + // failed, clean out any remaining bad packets + sock.set_timeout(0); + while (true) { + err = sock.recvfrom(NULL, NULL, 0); + if (err == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + sock.set_timeout(MBED_CFG_UDP_CLIENT_ECHO_TIMEOUT); + } + + result = success == ECHO_LOOPS; + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + if (err) { + result = false; + } + } + + bool get_result() { + return result; + } +}; + +Echo *echoers[MBED_CFG_UDP_CLIENT_ECHO_THREADS]; + + +void test_udp_echo_parallel() { + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + if (err) { + printf("MBED: failed to connect with an error of %d\r\n", err); + GREENTEA_TESTSUITE_RESULT(false); + } else { + printf("UDP client IP Address is %s\n", net.get_ip_address()); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: UDP Server IP address received: %s:%d \n", ipbuf, port); + udp_addr.set_ip_address(ipbuf); + udp_addr.set_port(port); + + // Startup echo threads in parallel + for (int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { + echoers[i] = new Echo; + echoers[i]->start(i, uuid); + } + + bool result = true; + + for (int i = 0; i < MBED_CFG_UDP_CLIENT_ECHO_THREADS; i++) { + echoers[i]->join(); + result = result && echoers[i]->get_result(); + delete echoers[i]; + } + + net.disconnect(); + TEST_ASSERT_EQUAL(true, result); + } +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP echo parallel", test_udp_echo_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/udp_packet_pressure/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,276 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Pressure tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Shared buffer for network transactions +uint8_t *buffer; +size_t buffer_size; + +// Tries to get the biggest buffer possible on the device. Exponentially +// grows a buffer until heap runs out of space, and uses half to leave +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 4; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + +void test_udp_packet_pressure() { + generate_buffer(&buffer, &buffer_size, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); + printf("MBED: Generated buffer %d\r\n", buffer_size); + + ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: UDPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + + UDPSocket sock; + SocketAddress udp_addr(ipbuf, port); + + Timer timer; + timer.start(); + + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + printf("UDP: %s:%d streaming %d bytes\r\n", ipbuf, port, size); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + int known_time = timer.read_ms(); + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out packets + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.sendto(udp_addr, buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: tx -> %d\r\n", td); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, revert to + // last good sequence and cut buffer in half + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: Not sent (%d), window = %d\r\n", td, window); + } + } + } + + // Prioritize recieving over sending packets to avoid flooding + // the network while handling erronous packets + while (rx_count < size) { + int rd = sock.recvfrom(NULL, buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + + if (rd > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: rx <- %d\r\n", rd); + } + + if (rx_seq.cmp(buffer, rd) == 0) { + rx_seq.skip(rd); + rx_count += rd; + known_time = timer.read_ms(); + if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { + window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + } + } + } else if (timer.read_ms() - known_time > + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { + // Dropped packet or out of order, revert to last good sequence + // and cut buffer in half + tx_seq = rx_seq; + tx_count = rx_count; + known_time = timer.read_ms(); + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + printf("UDP: Dropped, window = %d\r\n", window); + } + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net.disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP packet pressure", test_udp_packet_pressure), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/TESTS/net/udp_packet_pressure_parallel/main.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,341 @@ +#ifndef MBED_EXTENDED_TESTS + #error [NOT_SUPPORTED] Parallel pressure tests are not supported by default +#endif + +#include "mbed.h" +#include "ESP8266Interface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" + +using namespace utest::v1; + + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS 3 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG false +#endif + +#ifndef MBED_CFG_ESP8266_TX +#define MBED_CFG_ESP8266_TX D1 +#endif + +#ifndef MBED_CFG_ESP8266_RX +#define MBED_CFG_ESP8266_RX D0 +#endif + +#ifndef MBED_CFG_ESP8266_DEBUG +#define MBED_CFG_ESP8266_DEBUG false +#endif + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + buffer[i] = lookahead.next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + RandSeq lookahead = *this; + + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (lookahead.next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Tries to get the biggest buffer possible on the device. Exponentially +// grows a buffer until heap runs out of space, and uses half to leave +// space for the rest of the program +void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) { + size_t i = min; + while (i < max) { + void *b = malloc(i); + if (!b) { + i /= 8; + if (i < min) { + i = min; + } + break; + } + free(b); + i *= 2; + } + + *buffer = (uint8_t *)malloc(i); + *size = i; + TEST_ASSERT(buffer); +} + + +// Global variables shared between pressure tests +ESP8266Interface net(MBED_CFG_ESP8266_TX, MBED_CFG_ESP8266_RX, MBED_CFG_ESP8266_DEBUG); +SocketAddress udp_addr; +Timer timer; +Mutex iomutex; + +// Single instance of a pressure test +class PressureTest { +private: + uint8_t *buffer; + size_t buffer_size; + + UDPSocket sock; + Thread thread; + +public: + PressureTest(uint8_t *buffer, size_t buffer_size) + : buffer(buffer), buffer_size(buffer_size) { + } + + void start() { + osStatus status = thread.start(callback(this, &PressureTest::run)); + TEST_ASSERT_EQUAL(osOK, status); + } + + void join() { + osStatus status = thread.join(); + TEST_ASSERT_EQUAL(osOK, status); + } + + void run() { + // Tests exponentially growing sequences + for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + int err = sock.open(&net); + TEST_ASSERT_EQUAL(0, err); + iomutex.lock(); + printf("UDP: %s:%d streaming %d bytes\r\n", + udp_addr.get_ip_address(), udp_addr.get_port(), size); + iomutex.unlock(); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + int known_time = timer.read_ms(); + size_t window = buffer_size; + + while (tx_count < size || rx_count < size) { + // Send out packets + if (tx_count < size) { + size_t chunk_size = size - tx_count; + if (chunk_size > window) { + chunk_size = window; + } + + tx_seq.buffer(buffer, chunk_size); + int td = sock.sendto(udp_addr, buffer, chunk_size); + + if (td > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: tx -> %d\r\n", td); + iomutex.unlock(); + } + tx_seq.skip(td); + tx_count += td; + } else if (td != NSAPI_ERROR_WOULD_BLOCK) { + // We may fail to send because of buffering issues, revert to + // last good sequence and cut buffer in half + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: Not sent (%d), window = %d\r\n", td, window); + iomutex.unlock(); + } + } + } + + // Prioritize recieving over sending packets to avoid flooding + // the network while handling erronous packets + while (rx_count < size) { + int rd = sock.recvfrom(NULL, buffer, buffer_size); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + + if (rd > 0) { + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: rx <- %d\r\n", rd); + iomutex.unlock(); + } + + if (rx_seq.cmp(buffer, rd) == 0) { + rx_seq.skip(rd); + rx_count += rd; + known_time = timer.read_ms(); + if (window < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX) { + window += MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + } + } + } else if (timer.read_ms() - known_time > + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT) { + // Dropped packet or out of order, revert to last good sequence + // and cut buffer in half + tx_seq = rx_seq; + tx_count = rx_count; + known_time = timer.read_ms(); + if (window > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + window /= 2; + } + + if (MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_DEBUG) { + iomutex.lock(); + printf("UDP: Dropped, window = %d\r\n", window); + iomutex.unlock(); + } + } else if (rd == NSAPI_ERROR_WOULD_BLOCK) { + break; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + } +}; + +PressureTest *pressure_tests[MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS]; + + +void test_udp_packet_pressure_parallel() { + uint8_t *buffer; + size_t buffer_size; + generate_buffer(&buffer, &buffer_size, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN, + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX); + + size_t buffer_subsize = buffer_size / MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; + printf("MBED: Generated buffer %d\r\n", buffer_size); + printf("MBED: Split into %d buffers %d\r\n", + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS, + buffer_subsize); + + int err = net.connect(STRINGIZE(MBED_CFG_ESP8266_SSID), STRINGIZE(MBED_CFG_ESP8266_PASS)); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", net.get_ip_address()); + printf("MBED: UDPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", net.get_ip_address()); + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + udp_addr.set_ip_address(ipbuf); + udp_addr.set_port(port); + + timer.start(); + + // Startup pressure tests in parallel + for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize); + pressure_tests[i]->start(); + } + + for (int i = 0; i < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS; i++) { + pressure_tests[i]->join(); + delete pressure_tests[i]; + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %.3fkb/s\r\n", + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_THREADS* + 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read())); + + net.disconnect(); +} + + +// Test setup +utest::v1::status_t test_setup(const size_t number_of_cases) { + GREENTEA_SETUP(120, "udp_echo"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("UDP packet pressure parallel", test_udp_packet_pressure_parallel), +}; + +Specification specification(test_setup, cases); + +int main() { + return !Harness::run(specification); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/WizFi310/WizFi310.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,506 @@ +/* + * 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. + */ + +/** + ****************************************************************************** + * @file WizFi310.cpp + * @author Gateway Team + * @brief Implementation file of the WizFi310 WiFi Device + ****************************************************************************** + * @attention + * + * 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, WIZnet 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. + * + * <h2><center>© COPYRIGHT 2017 WIZnet Co.,Ltd.</center></h2> + ****************************************************************************** + */ + +#include "WizFi310.h" +#define WIZFI310_DEFAULT_BAUD_RATE 115200 + +#define AT_CMD_PARSER_DEFAULT_TIMEOUT 500 +#define AT_CMD_PARSER_INIT_TIMEOUT 1000 +#define AT_CMD_PARSER_RECV_TIMEOUT 20000 + +using namespace mbed; +WizFi310::WizFi310(PinName tx, PinName rx, bool debug) + : _serial(tx, rx, WIZFI310_DEFAULT_BAUD_RATE), + _parser(&_serial), + _packets(0), + _packets_end(&_packets) +{ + _serial.set_baud( WIZFI310_DEFAULT_BAUD_RATE ); + _parser.debug_on(debug); + _parser.set_delimiter("\r\n"); + + setTimeout(AT_CMD_PARSER_INIT_TIMEOUT); + for(int i=0; i<10; i++) + { + if( _parser.send("AT") && _parser.recv("[OK]") ) + { + _parser.send("AT+MECHO=0"); + _parser.recv("[OK]"); + _parser.send("AT+MPROF=S"); + _parser.recv("[OK]"); + _parser.send("AT+MRESET"); + _parser.recv("[OK]"); + break; + } + } + + _parser.recv("WizFi310 Version %s (WIZnet Co.Ltd)", _firmware_version); +} + +const char* WizFi310::get_firmware_version() +{ + if( strlen(_firmware_version) != 0 ) + { + return _firmware_version; + } + + _parser.send("AT+MINFO"); + if( _parser.recv("%s/WizFi310 Rev", _firmware_version) ) + { + return _firmware_version; + } + + return 0; +} + +bool WizFi310::startup(int mode) +{ + if( mode != 0 && mode != 1 ) + { + return false; + } + _op_mode = mode; + + _parser.oob("{", callback(this, &WizFi310::_packet_handler)); + //_parser.oob("\n{", callback(this, &WizFi310::_packet_handler)); + return true; +} + +bool WizFi310::reset(void) +{ + for (int i=0; i<2; i++) + { + if(_parser.send("AT+MRESET") + && _parser.recv("[OK]")) + { + return true; + } + } + + return false; +} + +bool WizFi310::dhcp(bool enabled) +{ + _dhcp = enabled; + return _dhcp; +} + +bool WizFi310::connect(const char *ap, const char *passPhrase, const char *sec) +{ + if ( !(_parser.send("AT+WSET=0,%s", ap) && _parser.recv("[OK]")) ) + { + return false; + } + + //if ( !(_parser.send("AT+WSEC=0,%s,%s", sec, passPhrase) && _parser.recv("[OK]")) ) + if ( !(_parser.send("AT+WSEC=0,,%s", passPhrase) && _parser.recv("[OK]")) ) + { + return false; + } + + if (_dhcp) + { + if ( !(_parser.send("AT+WNET=1") && _parser.recv("[OK]")) ) + { + return false; + } + } + else + { + if ( !(_parser.send("AT+WNET=0,%s,%s,%s",_ip_buffer,_netmask_buffer,_gateway_buffer) + && _parser.recv("[OK]")) ) + { + return false; + } + } + + if ( !(_parser.send("AT+WJOIN") && _parser.recv("[Link-Up Event]") + && _parser.recv(" IP Addr : %[^\n]\r\n",_ip_buffer) + && _parser.recv(" Gateway : %[^\n]\r\n",_gateway_buffer) + && _parser.recv("[OK]")) ) + { + return false; + } + + return true; +} + +bool WizFi310::disconnect(void) +{ + return _parser.send("AT+WLEAVE") && _parser.recv("[OK]"); +} + +const char *WizFi310::getIPAddress(void) +{ + if (!(_parser.send("AT+WSTATUS") && _parser.recv("IF/SSID/IP-Addr/Gateway/MAC/TxPower(dBm)/RSSI(-dBm)") + && _parser.recv("%*[^/]/%*[^/]/%15[^/]/",_ip_buffer) + && _parser.recv("[OK]")) ) + { + return 0; + } + + return _ip_buffer; +} + +const char *WizFi310::getMACAddress(void) +{ + if (!(_parser.send("AT+MMAC=?") + && _parser.recv("%[^\n]\r\n",_mac_buffer) + && _parser.recv("[OK]"))) { + return 0; + } + + return _mac_buffer; +} + +const char *WizFi310::getGateway() +{ + return _gateway_buffer; +} + +const char *WizFi310::getNetmask() +{ + return _netmask_buffer; +} + +int8_t WizFi310::getRSSI() +{ + char rssi[3]; + + if (!(_parser.send("AT+WSTATUS") && _parser.recv("IF/SSID/IP-Addr/Gateway/MAC/TxPower(dBm)/RSSI(-dBm)") + //&& _parser.recv("%*[^/]/%*[^/]/%*[^/]/%*[^/]/%*[^/]/%*[^/]/%[^\n]\r\n",&rssi) + && _parser.recv("%*[^/]/%*[^/]/%*[^/]/%*[^/]/%*[^/]//%[^\n]\r\n",rssi) + && _parser.recv("[OK]")) ) + { + return 0; + } + + return atoi(rssi); +} + +bool WizFi310::isConnected(void) +{ + return getIPAddress() != 0; +} + +int WizFi310::scan(WiFiAccessPoint *res, unsigned limit) +{ + unsigned int cnt = 0; + nsapi_wifi_ap_t ap; + + // Scan Time out : 50ms + if (!(_parser.send("AT+WSCAN=,,,50") + && _parser.recv("Index/SSID/BSSID/RSSI(-dBm)/MaxDataRate(Mbps)/Security/RadioBand(GHz)/Channel"))) + { + 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 WizFi310::open(const char *type, int id, const char* addr, int port) +{ + int created_sock_id; + + //IDs only 0-7 + if(id > 7) { + return false; + } + + if( !(_parser.send("AT+SCON=O,%s,%s,%d,,0",type,addr,port) && _parser.recv("[OK]") + && _parser.recv("[CONNECT %d]",&created_sock_id))) { + return false; + } + + if( created_sock_id != id ) { + close(created_sock_id); + return false; + } + + return true; +} + +bool WizFi310::dns_lookup(const char* name, char* ip) +{ + return (_parser.send("AT+FDNS=%s,5000", name) && _parser.recv("%[^\n]\r\n",ip) && _parser.recv("[OK]")); +} + +bool WizFi310::send(int id, const void *data, uint32_t amount) +{ + char str_result[20]; + + if(id > 8) { + return false; + } + + sprintf(str_result,"[%d,,,%d]",id,(int)amount); + + // Using _parser.printf because MCU can't send CR LF + if( _parser.printf("AT+SSEND=%d,,,%d\r",id, (int)amount) + && _parser.recv(str_result) + && _parser.write((char*)data, (int)amount) >= 0 + && _parser.recv("[OK]") ){ + return true; + } + + return false; +} + +void WizFi310::_packet_handler() +{ + int id; + char ip_addr[16]; + int port; + uint32_t amount; + + // parse out the packet + _parser.set_timeout(AT_CMD_PARSER_RECV_TIMEOUT); + if (!_parser.recv("%d,%[^,],%d,%d}",&id, ip_addr,&port, &amount) ) { + setTimeout(_timeout_ms); + return; + } + + struct packet *packet = new struct packet; + if (!packet) { + return; + } + + packet->id = id; + packet->len = amount; + packet->next = 0; + packet->data = (char*)malloc(amount); + + + if (!(_parser.read((char*)packet->data, amount))) { + free(packet); + setTimeout(_timeout_ms); + return; + } + setTimeout(_timeout_ms); + + *_packets_end = packet; + _packets_end = &packet->next; +} + +int32_t WizFi310::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) { + memcpy(data,q->data, 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->data, amount); + + q->len -= amount; + memmove(q->data, (uint8_t*)(q->data) + amount, q->len); + return amount; + } + } + } + + // check for inbound packets + if (!_parser.process_oob()) { + return -1; + } + } +} + +bool WizFi310::close(int id) +{ + char sock_event_msg[15]; + + if(id > 7) { + return false; + } + + if (_parser.send("AT+SMGMT=%d", id) && _parser.recv(sock_event_msg) && _parser.recv("[OK]") ) + { + return true; + } + + return false; +} + +void WizFi310::setTimeout(uint32_t timeout_ms) +{ + _parser.set_timeout(timeout_ms); + _timeout_ms = timeout_ms; +} + +bool WizFi310::readable() +{ + return _serial.FileHandle::readable(); +} + +bool WizFi310::writeable() +{ + return _serial.FileHandle::writable(); +} + +void WizFi310::attach(Callback<void()> func) +{ + _serial.sigio(func); +} + +bool WizFi310::recv_ap(nsapi_wifi_ap_t *ap) +{ + char scan_result[100]; + char sec[10]; + char bssid[32]; + char* idx_ptr; + char* bssid_ptr; + + _parser.recv("%s\r\n",scan_result); + if( strcmp(scan_result,"[OK]") == 0 ) + { + return false; + } + + idx_ptr = strtok((char*)scan_result, "/"); // index + + idx_ptr = strtok( NULL, "/" ); // ssid + strncpy(ap->ssid,idx_ptr,strlen(idx_ptr)); + ap->ssid[strlen(idx_ptr)] = '\0'; + + idx_ptr = strtok( NULL, "/" ); // bssid + strncpy(bssid,idx_ptr,strlen(idx_ptr)); + bssid[strlen(idx_ptr)] = '\0'; + + idx_ptr = strtok( NULL, "/" ); // RSSI + ap->rssi = atoi(idx_ptr); + + //idx_ptr = strtok( NULL, "/" ); // DataRate + + idx_ptr = strtok( NULL, "/" ); // Security + strncpy(sec,idx_ptr,strlen(idx_ptr)); + sec[strlen(idx_ptr)] = '\0'; + ap->security = str2sec(sec); + + idx_ptr = strtok( NULL, "/" ); // RadioBand + + idx_ptr = strtok( NULL, "/" ); // Channel + ap->channel = atoi(idx_ptr); + + // Set BSSID + bssid_ptr = strtok( (char*)bssid, ":"); + ap->bssid[0] = hex_str_to_int(bssid_ptr); + + for(int i=1; i<6; i++) + { + bssid_ptr = strtok( NULL, ":"); + ap->bssid[i] = hex_str_to_int(bssid_ptr); + } + + return true; +} + +nsapi_security_t WizFi310::str2sec(const char *str_sec) +{ + if( strcmp(str_sec,"Open") == 0 ) + { + return NSAPI_SECURITY_NONE; + } + else if( strcmp(str_sec,"WEP") == 0 ) + { + return NSAPI_SECURITY_WEP; + } + else if( strcmp(str_sec,"WPA") == 0 ) + { + return NSAPI_SECURITY_WPA; + } + else if( strcmp(str_sec,"WPA2") == 0 ) + { + return NSAPI_SECURITY_WPA2; + } + else if( strcmp(str_sec,"WPAWPA2") == 0 ) + { + return NSAPI_SECURITY_WPA_WPA2; + } + + return NSAPI_SECURITY_UNKNOWN; +} + +int WizFi310::hex_str_to_int(const char* hex_str) +{ + int n = 0; + uint32_t value = 0; + int shift = 7; + while (hex_str[n] != '\0' && n < 8) + { + if ( hex_str[n] > 0x21 && hex_str[n] < 0x40 ) + { + value |= (hex_str[n] & 0x0f) << (shift << 2); + } + else if ( (hex_str[n] >= 'a' && hex_str[n] <= 'f') || (hex_str[n] >= 'A' && hex_str[n] <= 'F') ) + { + value |= ((hex_str[n] & 0x0f) + 9) << (shift << 2); + } + else + { + break; + } + n++; + shift--; + } + + return (value >> ((shift + 1) << 2)); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/WizFi310/WizFi310.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,258 @@ +/* + * 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. + */ + +/** + ****************************************************************************** + * @file WizFi310.h + * @author Gateway Team + * @brief Header file of the WizFi310 WiFi Device + ****************************************************************************** + * @attention + * + * 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, WIZnet 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. + * + * <h2><center>© COPYRIGHT 2017 WIZnet Co.,Ltd.</center></h2> + ****************************************************************************** + */ + +#ifndef WIZFI310_H_ +#define WIZFI310_H_ + +#include "ATCmdParser.h" +#include "netsocket/WiFiAccessPoint.h" +#include "UARTSerial.h" + +/** WizFi310Interface class. + This is an interface to a WizFi310Interface radio. +*/ +class WizFi310 +{ +public: + WizFi310(PinName tx, PinName rx, bool debug=false); + + /** + * Check firmware version of WizFi310 + * + * @return character array firmware version or 0 if firmware query command gives outdated response + */ + const char* get_firmware_version(void); + + /** + * Startup the WizFi310 + * + * @param mode mode of WIFI 0-client, 1-host + * @return true only if WizFi310 was setup correctly + */ + bool startup(int mode); + + /** + * Reset WizFi310 + * + * @return true only if WizFi310 resets successfully + */ + bool reset(void); + + /** + * Enable/Disable DHCP + * + * @param enabled DHCP enabled when true + * @return true only if WizFi310 enables/disables DHCP successfully + */ + bool dhcp(bool enabled); + + /** + * Connect WizFi310 to AP + * + * @param ap the name of the AP + * @param passPhrase the password of AP + * @param security type of AP + * @return true only if WizFi310 is connected successfully + */ + bool connect(const char *ap, const char *passPhrase, const char *sec); + + /** + * Disconnect WizFi310 from AP + * + * @return true only if WizFi310 is disconnected successfully + */ + bool disconnect(void); + + /** + * Get the IP address of WizFi310 + * + * @return null-teriminated IP address or null if no IP address is assigned + */ + const char *getIPAddress(void); + + /** + * Get the MAC address of WizFi310 + * + * @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 WizFi310 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); + + /**Perform a dns query + * + * @param name Hostname to resolve + * @param ip Buffer to store IP address + * @return 0 true on success, false on failure + */ + bool dns_lookup(const char *name, char *ip); + + /** + * 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(mbed::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(mbed::Callback<void()>(obj, method)); + } + +private: + mbed::UARTSerial _serial; + mbed::ATCmdParser _parser; + + struct packet { + struct packet *next; + int id; + uint32_t len; + // data follows + char *data; + } *_packets, **_packets_end; + void _packet_handler(); + //void _socket_close_handler(); + bool recv_ap(nsapi_wifi_ap_t *ap); + nsapi_security_t str2sec(const char *str_sec); + int hex_str_to_int(const char* hex_str); + + char _ip_buffer[16]; + char _gateway_buffer[16]; + char _netmask_buffer[16]; + char _mac_buffer[18]; + char _firmware_version[8]; + + int _op_mode; // 0 : Station Mode, 1 : AP Mode + bool _dhcp; + uint32_t _timeout_ms; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/WizFi310Interface.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,385 @@ +/* WizFi310 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. + */ + +/** + ****************************************************************************** + * @file WizFi310Interface.h + * @author Gateway Team + * @brief Implementation file of the NetworkStack for the WizFi310 WiFi Device + ****************************************************************************** + * @attention + * + * 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, WIZnet 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. + * + * <h2><center>© COPYRIGHT 2017 WIZnet Co.,Ltd.</center></h2> + ****************************************************************************** + */ + +#include <string.h> +#include "WizFi310Interface.h" +#include "mbed_debug.h" + +using namespace mbed; +// Various timeouts for different WizFi310 operations +#ifndef WIZFI310_CONNECT_TIMEOUT +#define WIZFI310_CONNECT_TIMEOUT 15000 +#endif +#ifndef WIZFI310_SEND_TIMEOUT +#define WIZFI310_SEND_TIMEOUT 500 +#endif +#ifndef WIZFI310_RECV_TIMEOUT +#define WIZFI310_RECV_TIMEOUT 0 +#endif +#ifndef WIZFI310_MISC_TIMEOUT +#define WIZFI310_MISC_TIMEOUT 500 +#endif +#ifndef WIZFI310_OPEN_TIMEOUT +#define WIZFI310_OPEN_TIMEOUT 10000 +#endif +#ifndef WIZFI310_CLOSE_TIMEOUT +#define WIZFI310_CLOSE_TIMEOUT 500 +#endif + +#ifndef WIZFI310_MAX_CONNECT_COUNT +#define WIZFI310_MAX_CONNECT 2 +#endif + +#ifndef WIZFI310_DELAY_MS +#define WIZFI310_DELAY_MS 300 +#endif + +// WizFi310Interface implementation +WizFi310Interface::WizFi310Interface(PinName tx, PinName rx, bool debug) + : _wizfi310(tx, rx, debug) +{ + memset(_ids, 0, sizeof(_ids)); + memset(_cbs, 0, sizeof(_cbs)); + + _wizfi310.attach(this, &WizFi310Interface::event); +} + +int WizFi310Interface::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 WizFi310Interface::connect() +{ + char sec[10]; + int i; + + _wizfi310.setTimeout(WIZFI310_CONNECT_TIMEOUT); + + _wizfi310.startup(0); + + if( !_wizfi310.dhcp(true) ) + { + return NSAPI_ERROR_DHCP_FAILURE; + } + + if( ap_sec == NSAPI_SECURITY_NONE && (strlen(ap_pass) > 0) ) + { + ap_sec = NSAPI_SECURITY_UNKNOWN; + } + + switch( ap_sec ) + { + case NSAPI_SECURITY_NONE: + strncpy(sec,"OPEN",strlen("OPEN")+1); + break; + case NSAPI_SECURITY_WEP: + strncpy(sec,"WEP",strlen("WEP")+1); + break; + case NSAPI_SECURITY_WPA: + strncpy(sec,"WPA",strlen("WPA")+1); + break; + case NSAPI_SECURITY_WPA2: + strncpy(sec,"WPA2",strlen("WPA2")+1); + break; + case NSAPI_SECURITY_WPA_WPA2: + strncpy(sec,"WPAWPA2",strlen("WPAWPA2")+1); + break; + default: + strncpy(sec,"",strlen("")+1); + break; + } + + for( i=0; i<WIZFI310_MAX_CONNECT; i++ ) + { + if( _wizfi310.connect(ap_ssid, ap_pass, sec) ) { + break; + } + + _wizfi310.reset(); + } + + if( i > WIZFI310_MAX_CONNECT ){ + return NSAPI_ERROR_NO_CONNECTION; + } + + if( !_wizfi310.getIPAddress() ) + { + return NSAPI_ERROR_DHCP_FAILURE; + } + + return NSAPI_ERROR_OK; +} + + +int WizFi310Interface::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 WizFi310Interface::set_channel(uint8_t channel) +{ + return 0; +} + +int WizFi310Interface::disconnect() +{ + _wizfi310.setTimeout(WIZFI310_MISC_TIMEOUT); + + if (!_wizfi310.disconnect()) + { + return NSAPI_ERROR_DEVICE_ERROR; + } + return NSAPI_ERROR_OK; +} + +const char *WizFi310Interface::get_ip_address() +{ + return _wizfi310.getIPAddress(); +} + +const char *WizFi310Interface::get_mac_address() +{ + return _wizfi310.getMACAddress(); +} + +const char *WizFi310Interface::get_gateway() +{ + return _wizfi310.getGateway(); +} + +const char *WizFi310Interface::get_netmask() +{ + return _wizfi310.getNetmask(); +} + +int8_t WizFi310Interface::get_rssi() +{ + return _wizfi310.getRSSI(); +} + +int WizFi310Interface::scan(WiFiAccessPoint *res, unsigned count) +{ + return _wizfi310.scan(res, count); +} + +nsapi_error_t WizFi310Interface::gethostbyname(const char *host, + SocketAddress *address, nsapi_version_t version) +{ + char host_ip[16]; + + if( !_wizfi310.dns_lookup(host,host_ip) ){ + return NSAPI_ERROR_DNS_FAILURE; + } + if ( !address->set_ip_address(host_ip) ){ + return NSAPI_ERROR_DNS_FAILURE; + } + + return NSAPI_ERROR_OK; +} + +struct wizfi310_socket { + int id; + nsapi_protocol_t proto; + bool connected; + SocketAddress addr; +}; + + +int WizFi310Interface::socket_open(void **handle, nsapi_protocol_t proto) +{ + // Look for an unused socket + int id = -1; + + for (int i=0; i<WIZFI310_SOCKET_COUNT; i++) { + if (!_ids[i]){ + id = i; + //_ids[i] = true; + break; + } + } + + if (id == -1){ + return NSAPI_ERROR_NO_SOCKET; + } + + struct wizfi310_socket *socket = new struct wizfi310_socket; + if (!socket){ + return NSAPI_ERROR_NO_SOCKET; + } + + socket->id = id; + socket->proto = proto; + socket->connected = false; + *handle = socket; + + return 0; +} + +int WizFi310Interface::socket_close(void *handle) +{ + struct wizfi310_socket *socket = (struct wizfi310_socket *)handle; + int err = 0; + _wizfi310.setTimeout(WIZFI310_CLOSE_TIMEOUT); + + if (socket->connected && !_wizfi310.close(socket->id)) { + err = NSAPI_ERROR_DEVICE_ERROR; + } + + socket->connected = false; + _ids[socket->id] = false; + delete socket; + return err; +} + +int WizFi310Interface::socket_bind(void *handle, const SocketAddress &address) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +int WizFi310Interface::socket_listen(void *handle, int backlog) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +int WizFi310Interface::socket_connect(void *handle, const SocketAddress &addr) +{ + struct wizfi310_socket *socket = (struct wizfi310_socket *)handle; + _wizfi310.setTimeout(WIZFI310_OPEN_TIMEOUT); + + const char *proto = (socket->proto == NSAPI_UDP) ? "UCN" : "TCN"; + if (!_wizfi310.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + socket->connected = true; + _ids[socket->id] = true; + return 0; +} + +int WizFi310Interface::socket_accept(void *server, void **socket, SocketAddress *addr) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + +int WizFi310Interface::socket_send(void *handle, const void *data, unsigned size) +{ + struct wizfi310_socket *socket = (struct wizfi310_socket *)handle; + _wizfi310.setTimeout(WIZFI310_SEND_TIMEOUT); + + if (!_wizfi310.send(socket->id, data, size)) { + return NSAPI_ERROR_DEVICE_ERROR; + } + + return size; +} + +int WizFi310Interface::socket_recv(void *handle, void *data, unsigned size) +{ + struct wizfi310_socket *socket = (struct wizfi310_socket *)handle; + _wizfi310.setTimeout(WIZFI310_RECV_TIMEOUT); + + int32_t recv = _wizfi310.recv(socket->id, data, size); + if (recv < 0) { + return NSAPI_ERROR_WOULD_BLOCK; + } + + return recv; +} + +int WizFi310Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size) +{ + struct wizfi310_socket *socket = (struct wizfi310_socket *)handle; + + if (socket->connected && socket->addr != addr) { + _wizfi310.setTimeout(WIZFI310_MISC_TIMEOUT); + if (!_wizfi310.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 WizFi310Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size) +{ + struct wizfi310_socket *socket = (struct wizfi310_socket *)handle; + int ret = socket_recv(socket, data, size); + if (ret >= 0 && addr) { + *addr = socket->addr; + } + + return ret; +} + +void WizFi310Interface::socket_attach(void *handle, void (*callback)(void *), void *data) +{ + struct wizfi310_socket *socket = (struct wizfi310_socket *)handle; + _cbs[socket->id].callback = callback; + _cbs[socket->id].data = data; +} + +void WizFi310Interface::event() +{ + for(int i=0; i<WIZFI310_SOCKET_COUNT; i++){ + if (_cbs[i].callback) { + _cbs[i].callback(_cbs[i].data); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/WizFi310Interface.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,296 @@ +/* WizFi310 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. + */ + +/** + ****************************************************************************** + * @file WizFi310Interface.h + * @author Gateway Team + * @brief Header file of the NetworkStack for the WizFi310 WiFi Device + ****************************************************************************** + * @attention + * + * 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, WIZnet 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. + * + * <h2><center>© COPYRIGHT 2017 WIZnet Co.,Ltd.</center></h2> + ****************************************************************************** + */ + +#ifndef WIZFI310_INTERFACE_H +#define WIZFI310_INTERFACE_H + +#include "NetworkStack.h" +#include "WiFiInterface.h" +#include "WizFi310.h" + +#define WIZFI310_SOCKET_COUNT 8 + +/** WizFi310Interface class + * Implementation of the NetworkStack for the WizFi310 + */ +class WizFi310Interface : public NetworkStack, public WiFiInterface +{ +public: + /* WizFi310Interface constructor + */ + + WizFi310Interface(PinName tx = MBED_CONF_WIZFI310_TX, + PinName rx = MBED_CONF_WIZFI310_RX, + bool debug = MBED_CONF_WIZFI310_DEBUG); + + /** 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 + * @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; + virtual nsapi_error_t gethostbyname(const char *host, + SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC); + + /** 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: + WizFi310 _wizfi310; + bool _ids[WIZFI310_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[WIZFI310_SOCKET_COUNT]; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/compile_test.bat Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +mbed test -t GCC_ARM -m NUCLEO_L073RZ -n tests-net-udp_echo --compile -DMBED_CFG_WIZFI310_SSID=Dap -DMBED_CFG_WIZFI310_PASS=00001111 -DMBED_CFG_WIZFI310_TX=D8 -DMBED_CFG_WIZFI310_RX=D2 -DMBED_CFG_WIZFI310_DEBUG=true -DMBED_CONF_DRIVERS_UART_SERIAL_RXBUF_SIZE=512 -DMBED_CONF_DRIVERS_UART_SERIAL_TXBUF_SIZE=512 -c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/mbed_lib.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,18 @@ +{ + "name": "wizfi310", + "config": { + + "tx": { + "help": "TX pin for serial connection to external device (WizFi310)", + "value": "NC" + }, + "rx": { + "help": "RX pin for serial connection to external device (WizFi310)", + "value": "NC" + }, + "debug": { + "help": "Enable debug logs for (WizFi310)", + "value": false + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wizfi310-driver/run_test.bat Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +mbed test -t GCC_ARM -m NUCLEO_L073RZ -n tests-net* --run --verbose --parallel 1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/Avnet/wnc14a2a-driver/#889b7f130c4d714489d0f103b0183f15a7a41852
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/FETCH_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +889b7f130c4d714489d0f103b0183f15a7a41852 branch 'master' of https://github.com/Avnet/wnc14a2a-driver
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/ORIG_HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +889b7f130c4d714489d0f103b0183f15a7a41852
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/config Wed Sep 05 14:28:24 2018 +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/Avnet/wnc14a2a-driver/ +[branch "master"] + remote = origin + merge = refs/heads/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/description Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/hooks/applypatch-msg.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/hooks/commit-msg.sample Wed Sep 05 14:28:24 2018 +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 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/hooks/post-update.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/hooks/pre-applypatch.sample Wed Sep 05 14:28:24 2018 +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+"$@"} +:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/hooks/pre-commit.sample Wed Sep 05 14:28:24 2018 +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 --
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/hooks/pre-rebase.sample Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/hooks/prepare-commit-msg.sample Wed Sep 05 14:28:24 2018 +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"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/hooks/update.sample Wed Sep 05 14:28:24 2018 +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
Binary file easy-connect/wnc14a2a-driver/.git/index has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/info/exclude Wed Sep 05 14:28:24 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/logs/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 889b7f130c4d714489d0f103b0183f15a7a41852 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504034 +0000 clone: from https://github.com/Avnet/wnc14a2a-driver/ +889b7f130c4d714489d0f103b0183f15a7a41852 889b7f130c4d714489d0f103b0183f15a7a41852 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504035 +0000 checkout: moving from master to 889b7f130c4d714489d0f103b0183f15a7a41852 +889b7f130c4d714489d0f103b0183f15a7a41852 889b7f130c4d714489d0f103b0183f15a7a41852 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504035 +0000 checkout: moving from 889b7f130c4d714489d0f103b0183f15a7a41852 to master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/logs/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 889b7f130c4d714489d0f103b0183f15a7a41852 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504034 +0000 clone: from https://github.com/Avnet/wnc14a2a-driver/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/logs/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +0000000000000000000000000000000000000000 889b7f130c4d714489d0f103b0183f15a7a41852 www-data <www-data@developer-sjc-cyan-compiler.local.mbed.org> 1535504034 +0000 clone: from https://github.com/Avnet/wnc14a2a-driver/
Binary file easy-connect/wnc14a2a-driver/.git/objects/pack/pack-8f8295d00215c3dc11636b0c3957dc852b022275.idx has changed
Binary file easy-connect/wnc14a2a-driver/.git/objects/pack/pack-8f8295d00215c3dc11636b0c3957dc852b022275.pack has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/packed-refs Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,2 @@ +# pack-refs with: peeled +889b7f130c4d714489d0f103b0183f15a7a41852 refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/refs/heads/master Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +889b7f130c4d714489d0f103b0183f15a7a41852
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.git/refs/remotes/origin/HEAD Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +ref: refs/remotes/origin/master
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/.meta Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<root> + <node _type="integer" _key="update">0</node> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/LICENSE Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,201 @@ + 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: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) 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 + + (d) 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 + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/README.md Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,57 @@ + +# Easy Connect with the wnc14a2a-library + +## Specifying the connectivity method + +Add the following to your `mbed_app.json` file: + +```json +{ + "config": { + "network-interface":{ + "help": "options are ETHERNET, WIFI_ESP8266, WIFI_IDW0XX1, WIFI_ODIN, WIFI_RTW, WIFI_WIZFI310, WIFI_ISM43362, MESH_LOWPAN_ND, MESH_THREAD, CELLULAR_ONBOARD, CELLULAR_WNC14A2A", + "value": "CELLULAR_WNC14A2A" + } + }, + } +} +``` + +## Debug settings +You may also want to specify the following to obtain debug output. This is added to the "config" section: + +```json + "config": { + "wnc_debug": { + "help" : "enable or disable WNC debug messages.", + "value": 0 + }, + "wnc_debug_setting": { + "help" : "bit value 1 and/or 2 enable WncController debug output, bit value 4 enables mbed driver debug output.", + "value": "4" + } + } +``` + +where the wnc_debug is either 'true' or 'false' to enable or disable debug output and the `wnc_debug_setting` variable is a +bit-field with the following settings: + 0x01 - Basic WNC driver debug output + 0x02 - Comprehensive WNC driver debug output + 0x04 - Driver Enter/Exit debug information + 0x08 - Driver Event Queue debug information + 0x10 - SMS debug information + 0x20 - Dump Driver Arrays + +## Overriding settings +You need to increase the size of the Tx and Rx buffers used when communicating to the WNC device by adding (increas the buffer +size to 4KB from 256 Bytes): + + +```json + "target_overrides": { + "*": { + "drivers.uart-serial-txbuf-size": 4096, + "drivers.uart-serial-rxbuf-size": 4096 + } +``` +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/WNC14A2AInterface/WNC14A2AInterface.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,957 @@ +/** +* copyright (c) 2017-2018, James Flynn +* 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. + * + */ + +/** +* @file WNC14A2AInterface.cpp +* @brief WNC14A2A implementation of NetworkInterfaceAPI for Mbed OS +* +* @author James Flynn +* +* @date 1-Feb-2018 +*/ + +#include "WNC14A2AInterface.h" +#include <Thread.h> +#include "mbed_events.h" +#include "WNCIO.h" + +#include <string> +#include <ctype.h> + +#define WNC_DEBUG 0 //1=enable the WNC startup debug output + //0=disable the WNC startup debug output +#define STOP_ON_FE 1 //1=hang forever if a fatal error occurs + //0=simply return failed response for all socket calls +#define DISPLAY_FE 1 //1 to display the fatal error when it occurs + //0 to NOT display the fatal error +#define RESETON_FE 0 //1 to cause the MCU to reset on fatal error + //0 to NOT reset the MCU + +/** Error Handling macros & data +* @brief The macros CHK_WNCFE is used to check if a fatal error has occured. If it has +* then execute the action specified: fail, void, null, resume +* +* CHK_WNCFE( condition-to-check, fail|void|null|resume ) +* +* 'fail' if you want FATAL_WNC_ERROR to be called. +* 'void' if you want to execute a void return +* 'null' if you want to execute a null return +* 'resume' if you simply want to resume program execution +* +* There are several settings that control how FATAL_WNC_ERROR behaves: +* 1) RESETON_FE determines if the system will reset or hang. +* 2) DISPLAY_FE determine if an error message is generated or not +* +* The DISPLAY_FE setting determines if a failure message is displayed. +* If set to 1, user sees this messageo: +* +* WNC FAILED @ source-file-name:source-file-line-number +* +* if not set, nothing is displayed. +*/ + +#define FATAL_FLAG WncController::WNC_NO_RESPONSE +#define WNC_GOOD WncController::WNC_ON + +#define RETfail return -1 +#define RETvoid return +#define RETnull return NULL +#define RETresume + +#define DORET(x) RET##x + +#define TOSTR(x) #x +#define INTSTR(x) TOSTR(x) +#define FATAL_STR (char*)(__FILE__ ":" INTSTR(__LINE__)) + +#if RESETON_FE == 1 //reset on fatal error +#define MCURESET ((*((volatile unsigned long *)0xE000ED0CU))=(unsigned long)((0x5fa<<16) | 0x04L)) +#define RSTMSG "RESET MCU! " +#else +#define MCURESET +#define RSTMSG "" +#endif + +#if DISPLAY_FE == 1 //display fatal error message +#define PFE {if(_debugUart)_debugUart->printf((char*)RSTMSG "\r\n>>WNC FAILED @ %s\r\n", FATAL_STR);} +#else +#define PFE +#endif + +#if STOP_ON_FE == 1 //halt cpu on fatal error +#define FATAL_WNC_ERROR(v) {_fatal_err_loc=FATAL_STR;PFE;MCURESET;while(1);} +#else +#define FATAL_WNC_ERROR(v) {_fatal_err_loc=FATAL_STR;PFE;DORET(v);} +#endif + +#define CHK_WNCFE(x,y) if( x ){FATAL_WNC_ERROR(y);} + +// +// Define different levels of debug output +// +#define DBGMSG_DRV 0x04 //driver enter/exit info +#define DBGMSG_EQ 0x08 //driver event queue info +#define DBGMSG_SMS 0x10 //driver SMS info +#define DBGMSG_ARRY 0x20 //dump driver arrays + +#define WNC14A2A_READ_TIMEOUTMS 4000 //duration to read no data to receive in MS +#define WNC14A2A_COMMUNICATION_TIMEOUT 100 //how long (ms) to wait for a WNC14A2A connect response +#define WNC_BUFF_SIZE 1500 //total number of bytes in a single WNC call +#define UART_BUFF_SIZE 4096 //size of our internal uart buffer.. define in *.json file + +#define EQ_FREQ 250 //frequency in ms to check for Tx/Rx data +#define EQ_FREQ_SLOW 2000 //frequency in ms to check when in slow monitor mode + +// +// The WNC device does not generate interrutps on received data, so this software polls +// for data availablility. To implement a non-blocking mode, simulate interrupts using +// mbed OS Event Queues. These Constants are used to manage the Rx/Tx states. +// +#define READ_INIT 10 +#define READ_START 11 +#define READ_ACTIVE 12 +#define DATA_AVAILABLE 13 +#define TX_IDLE 20 +#define TX_STARTING 21 +#define TX_ACTIVE 22 +#define TX_COMPLETE 23 + +#if MBED_CONF_APP_WNC_DEBUG == true +#define debugOutput(...) WNC14A2AInterface::_dbOut(__VA_ARGS__) +#define debugDump_arry(...) WNC14A2AInterface::_dbDump_arry(__VA_ARGS__) +#else +#define debugOutput(...) {/* __VA_ARGS__ */} +#define debugDump_arry(...) {/* __VA_ARGS__ */} +#endif + +/* Constructor +* +* @brief May be invoked with or without the debug pointer. +* @note After the constructor has completed, call check +* m_errors to determine if any errors occured. Possible values: +* NSAPI_ERROR_UNSUPPORTED +* NSAPI_ERROR_DEVICE_ERROR +*/ +WNC14A2AInterface::WNC14A2AInterface(WNCDebug *dbg) : + m_wncpoweredup(0), + m_debug(0), + m_pwnc(NULL), + m_errors(NSAPI_ERROR_OK), + m_smsmoning(0), + _active_socket(0), + mdmUart(MBED_CONF_WNC14A2A_LIBRARY_WNC_TXD,MBED_CONF_WNC14A2A_LIBRARY_WNC_RXD,115200), + wnc_io(&mdmUart) +{ + _debugUart = dbg; + memset(_mac_address,0x00,sizeof(_mac_address)); + memset(_socTxS,0x00,sizeof(_socTxS)); + memset(_socRxS,0x00,sizeof(_socRxS)); + for( unsigned int i=0; i<WNC14A2A_SOCKET_COUNT; i++ ) { + _sockets[i].socket = i; + _sockets[i].addr = NULL; + _sockets[i].opened=false; + + _sockets[i].connected=false; + _sockets[i].proto=1; + _socRxS[i].m_rx_socket=i; + _socTxS[i].m_tx_socket=i; + } +} + +//! Standard destructor +WNC14A2AInterface::~WNC14A2AInterface() +{ + if( m_pwnc ) + delete m_pwnc; //free the existing WncControllerK64F object +} + +// - - - - - - - +// SMS Functions +// - - - - - - - + +char* WNC14A2AInterface::getSMSnbr( void ) +{ + char * ret=NULL; + string iccid_str; + static string msisdn_str; + + if( !m_pwnc ) { + m_errors=NSAPI_ERROR_DEVICE_ERROR; + return NULL; + } + CHK_WNCFE(( m_pwnc->getWncStatus() == FATAL_FLAG ), null); + + _pwnc_mutex.lock(); + if( !m_pwnc->getICCID(&iccid_str) ) { + _pwnc_mutex.unlock(); + return ret; + } + + if( m_pwnc->convertICCIDtoMSISDN(iccid_str, &msisdn_str) ) + ret = (char*)msisdn_str.c_str(); + _pwnc_mutex.unlock(); + return ret; +} + +void WNC14A2AInterface::sms_attach(void (*callback)(IOTSMS *)) +{ + debugOutput("ENTER/EXIT sms_attach()"); + _sms_cb = callback; +} + +void WNC14A2AInterface::sms_start(void) +{ + _pwnc_mutex.lock(); + m_pwnc->deleteSMSTextFromMem('*'); + _pwnc_mutex.unlock(); +} + +void WNC14A2AInterface::sms_listen(uint16_t pp) +{ + debugOutput("ENTER sms_listen(%d)",pp); + + if( m_smsmoning ) + m_smsmoning = false; + if( pp < 1) + pp = 30; + + debugOutput("setup sms_listen event queue"); + _smsThread.start(callback(&sms_queue,&EventQueue::dispatch_forever)); + + sms_start(); + sms_queue.call_every(pp*1000, mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::handle_sms_event)); + + m_smsmoning = true; + debugOutput("EXIT sms_listen()"); +} + +void WNC14A2AInterface::handle_sms_event() +{ + int msgs_available; + debugOutput("ENTER handle_sms_event()"); + + if ( _sms_cb && m_smsmoning ) { + _pwnc_mutex.lock(); + msgs_available = m_pwnc->readUnreadSMSText(&m_smsmsgs, true); + _pwnc_mutex.unlock(); + if( msgs_available ) { + debugOutput("Have %d unread texts present",m_smsmsgs.msgCount); + for( int i=0; i< m_smsmsgs.msgCount; i++ ) { + m_MsgText.number = m_smsmsgs.e[i].number; + m_MsgText.date = m_smsmsgs.e[i].date; + m_MsgText.time = m_smsmsgs.e[i].time; + m_MsgText.msg = m_smsmsgs.e[i].msg; + _sms_cb(&m_MsgText); + } + } + } + debugOutput("EXIT handle_sms_event"); +} + +int WNC14A2AInterface::getSMS(IOTSMS **pmsg) +{ + int msgs_available=0; + + debugOutput("ENTER getSMS()"); + if( !m_pwnc ) + m_errors=NSAPI_ERROR_DEVICE_ERROR; + else{ + CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); + _pwnc_mutex.lock(); + msgs_available = m_pwnc->readUnreadSMSText(&m_smsmsgs, true); + _pwnc_mutex.unlock(); + } + + if( msgs_available ) { + debugOutput("Have %d unread texts present",m_smsmsgs.msgCount); + for( int i=0; i< m_smsmsgs.msgCount; i++ ) { + m_MsgText_array[i].number = m_smsmsgs.e[i].number; + m_MsgText_array[i].date = m_smsmsgs.e[i].date; + m_MsgText_array[i].time = m_smsmsgs.e[i].time; + m_MsgText_array[i].msg = m_smsmsgs.e[i].msg; + pmsg[i] = (IOTSMS*)&m_MsgText_array[i]; + } + msgs_available = m_smsmsgs.msgCount; + } + debugOutput("EXIT getSMS"); + return msgs_available; +} + + +int WNC14A2AInterface::sendIOTSms(const string& number, const string& message) +{ + debugOutput("ENTER sendIOTSms(%s,%s)",number.c_str(), message.c_str()); + + if( !m_pwnc ) + return (m_errors=NSAPI_ERROR_DEVICE_ERROR); + CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); + + _pwnc_mutex.lock(); + int i = m_pwnc->sendSMSText((char*)number.c_str(), message.c_str()); + _pwnc_mutex.unlock(); + + debugOutput("EXIT sendIOTSms(%s,%s)",number.c_str(), message.c_str()); + return i; +} + + +// - - - - - - - - - - - +// WNC Control Functions +// - - - - - - - - - - - + +nsapi_error_t WNC14A2AInterface::connect() //can be called with no arguments or with arguments +{ + debugOutput("ENTER connect(void)"); + return connect(NULL,NULL,NULL); +} + +nsapi_error_t WNC14A2AInterface::connect(const char *apn, const char *username, const char *password) +{ + // + // GPIO Pins used to initialize the WNC parts on the Avnet WNC Shield + // + // on powerup, 0 = boot mode, 1 = normal boot + // 0=let modem sleep, 1=keep modem awake -- Note: pulled high on shield + // active high + // 0 = disabled (all signals high impedence, 1 = translation active + // WNC doesn't utilize RTS/CTS but the pin is connected + + static DigitalOut mdm_uart2_rx_boot_mode_sel(MBED_CONF_WNC14A2A_LIBRARY_WNC_RX_BOOT_SEL); + static DigitalOut mdm_power_on(MBED_CONF_WNC14A2A_LIBRARY_WNC_POWER_ON); + static DigitalOut mdm_wakeup_in(MBED_CONF_WNC14A2A_LIBRARY_WNC_WAKEUP); + static DigitalOut mdm_reset(MBED_CONF_WNC14A2A_LIBRARY_WNC_RESET); + static DigitalOut shield_3v3_1v8_sig_trans_ena(MBED_CONF_WNC14A2A_LIBRARY_WNC_LVLTRANSLATOR); + static DigitalOut mdm_uart1_cts(MBED_CONF_WNC14A2A_LIBRARY_WNC_CTS); + + //! associations for the controller class to use. Order of pins is critical. + static WncControllerK64F_fk::WncGpioPinListK64F wncPinList = { + &mdm_uart2_rx_boot_mode_sel, + &mdm_power_on, + &mdm_wakeup_in, + &mdm_reset, + &shield_3v3_1v8_sig_trans_ena, + &mdm_uart1_cts + }; + + debugOutput("ENTER connect(apn,user,pass)"); + + if( m_pwnc == NULL ) { + m_pwnc = new WncControllerK64F_fk::WncControllerK64F(&wncPinList, &wnc_io, _debugUart); + if( !m_pwnc ) { + debugOutput("FAILED to open WncControllerK64!"); + m_errors = NSAPI_ERROR_DEVICE_ERROR; + return NSAPI_ERROR_NO_MEMORY; + } + CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); + #if MBED_CONF_APP_WNC_DEBUG == true + m_pwnc->enableDebug( (MBED_CONF_APP_WNC_DEBUG_SETTING&1), (MBED_CONF_APP_WNC_DEBUG_SETTING&2) ); + #endif + } + + _eqThread.start(callback(&wnc_queue,&EventQueue::dispatch_forever)); + + if (!apn) + apn = "m2m.com.attz"; + + _pwnc_mutex.lock(); + if (!m_wncpoweredup) { + debugOutput("call powerWncOn(%s,40)",apn); + m_wncpoweredup=m_pwnc->powerWncOn(apn,40); + m_errors = m_wncpoweredup? 1:0; + } + else { //powerWncOn already called, set a new APN + debugOutput("set APN=%s",apn); + m_errors = m_pwnc->setApnName(apn)? 1:0; + } + + m_errors |= m_pwnc->getWncNetworkingStats(&myNetStats)? 2:0; + _pwnc_mutex.unlock(); + + debugOutput("EXIT connect (%02X)",m_errors); + return (!m_errors)? NSAPI_ERROR_NO_CONNECTION : NSAPI_ERROR_OK; +} + +const char* WNC14A2AInterface::getWNCRev(void) +{ + if( m_pwnc ) { + const char * str = m_pwnc->getFirmRev(); + return &str[12]; + } + else + return NULL; +} + + +const char *WNC14A2AInterface::get_ip_address() +{ + const char *ptr=NULL; + + if( !m_pwnc ) { + m_errors=NSAPI_ERROR_DEVICE_ERROR; + return ptr; + } + CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), null); + + _pwnc_mutex.lock(); + if ( m_pwnc->getWncNetworkingStats(&myNetStats) ) { + _pwnc_mutex.unlock(); + ptr = &myNetStats.ip[0]; + } + else{ + _pwnc_mutex.unlock(); + m_errors=NSAPI_ERROR_NO_CONNECTION; + } + return ptr; +} + +const char *WNC14A2AInterface::get_mac_address() +{ + string mac, str; + debugOutput("ENTER get_mac_address()"); + + if( m_pwnc ) { + CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), null); + _pwnc_mutex.lock(); + if( m_pwnc->getICCID(&str) ) { + _pwnc_mutex.unlock(); + mac = str.substr(3,20); + mac[2]=mac[5]=mac[8]=mac[11]=mac[14]=':'; + strncpy(_mac_address, mac.c_str(), mac.length()); + debugOutput("EXIT get_mac_address() - %s",_mac_address); + return _mac_address; + } + _pwnc_mutex.unlock(); + } + debugOutput("EXIT get_mac_address() - NULL"); + return NULL; +} + +NetworkStack *WNC14A2AInterface::get_stack() { + debugOutput("ENTER/EXIT get_stack()"); + return this; +} + +nsapi_error_t WNC14A2AInterface::disconnect() +{ + debugOutput("ENTER/EXIT disconnect()"); + return NSAPI_ERROR_OK; +} + +nsapi_error_t WNC14A2AInterface::set_credentials(const char *apn, const char *username, const char *password) +{ + + m_errors=NSAPI_ERROR_OK; + debugOutput("ENTER set_credentials()"); + + if( !m_pwnc ) + return (m_errors=NSAPI_ERROR_DEVICE_ERROR); + CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); + + if( !apn ) + return (m_errors=NSAPI_ERROR_PARAMETER); + + _pwnc_mutex.lock(); + if( !m_pwnc->setApnName(apn) ) + m_errors=NSAPI_ERROR_DEVICE_ERROR; + _pwnc_mutex.unlock(); + debugOutput("EXIT set_credentials()"); + return m_errors; +} + +bool WNC14A2AInterface::registered() +{ + debugOutput("ENTER registered()"); + m_errors=NSAPI_ERROR_OK; + + if( !m_pwnc ) { + return (m_errors=NSAPI_ERROR_DEVICE_ERROR); + } + CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); + + _pwnc_mutex.lock(); + if ( m_pwnc->getWncStatus() != WNC_GOOD ) + m_errors=NSAPI_ERROR_NO_CONNECTION; + _pwnc_mutex.unlock(); + + debugOutput("EXIT registered()"); + return (m_errors==NSAPI_ERROR_OK); +} + + +void WNC14A2AInterface::doDebug( int v ) +{ + #if MBED_CONF_APP_WNC_DEBUG == true + m_debug= v; + debugOutput("SET debug flag to 0x%02X",v); + #endif +} + +/** function to dump a user provided array. +* +* @author James Flynn +* @param data pointer to the data array to dump +* @param size number of bytes to dump +* @return void +* @date 1-Feb-2018 +*/ +void WNC14A2AInterface::_dbDump_arry( const uint8_t* data, unsigned int size ) +{ + #if MBED_CONF_APP_WNC_DEBUG == true + char buffer[256]; + unsigned int i, k; + + if( _debugUart != NULL && (m_debug & DBGMSG_ARRY) ) { + for (i=0; i<size; i+=16) { + sprintf(buffer,"[WNC Driver]:0x%04X: ",i); + _debugUart->puts(buffer); + for (k=0; k<16; k++) { + sprintf(buffer, "%02X ", data[i+k]); + _debugUart->puts(buffer); + } + _debugUart->puts(" -- "); + for (k=0; k<16; k++) { + sprintf(buffer, "%2c", isprint(data[i+k])? data[i+k]:'.'); + _debugUart->puts(buffer); + } + _debugUart->puts("\n\r"); + } + } + #endif +} + +void WNC14A2AInterface::_dbOut(const char *format, ...) +{ + #if MBED_CONF_APP_WNC_DEBUG == true + char buffer[256]; + + sprintf(buffer,"[WNC Driver]: "); + if( _debugUart != NULL && (m_debug & (DBGMSG_DRV|DBGMSG_EQ|DBGMSG_SMS)) ) { + va_list args; + va_start (args, format); + _debugUart->puts(buffer); + if( m_debug & DBGMSG_DRV ) + vsnprintf(buffer, sizeof(buffer), format, args); + if( m_debug & DBGMSG_EQ ) + vsnprintf(buffer, sizeof(buffer), format, args); + if( m_debug & DBGMSG_SMS ) + vsnprintf(buffer, sizeof(buffer), format, args); + _debugUart->puts(buffer); + _debugUart->putc('\n'); + va_end (args); + } + #endif +} + +// - - - - - - - - - - - - - - - +// WNC Socket Based operatioins +// - - - - - - - - - - - - - - - + +nsapi_error_t WNC14A2AInterface::gethostbyname(const char* name, SocketAddress *address, nsapi_version_t version) +{ + nsapi_error_t ret = NSAPI_ERROR_OK; + char ipAddrStr[25]; + + debugOutput("ENTER gethostbyname(); IP=%s; PORT=%d; URL=%s;", address->get_ip_address(), address->get_port(), name); + + if( !m_pwnc ) + return (m_errors=NSAPI_ERROR_DEVICE_ERROR); + CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); + + memset(ipAddrStr,0x00,sizeof(ipAddrStr)); + + //Execute DNS query. + _pwnc_mutex.lock(); + if( !m_pwnc->resolveUrl(_active_socket, name) ) + ret = m_errors = NSAPI_ERROR_DEVICE_ERROR; + + //Get IP address that the URL was resolved to + if( !m_pwnc->getIpAddr(_active_socket, ipAddrStr) ) + ret = m_errors = NSAPI_ERROR_DEVICE_ERROR; + _pwnc_mutex.unlock(); + + address->set_ip_address(ipAddrStr); + + debugOutput("EXIT gethostbyname(); IP=%s; PORT=%d; URL=%s;", address->get_ip_address(), address->get_port(), name); + return (m_errors = ret); +} + +int WNC14A2AInterface::socket_open(void **handle, nsapi_protocol_t proto) +{ + unsigned int i; + + debugOutput("ENTER socket_open()"); + + //find the next available socket... + for( i=0; i<WNC14A2A_SOCKET_COUNT; i++ ) + if( !_sockets[i].opened ) + break; + + if( i == WNC14A2A_SOCKET_COUNT ) { + m_errors=NSAPI_ERROR_NO_SOCKET; + return -1; + } + + _sockets[i].socket = i; //save index later + _sockets[i].opened = true; + _sockets[i].connected=false; + _sockets[i].proto = (proto==NSAPI_UDP)?0:1; + _sockets[i]._callback = NULL; + _sockets[i]._cb_data = NULL; + + _socRxS[i].m_rx_wnc_state = READ_START; + _socRxS[i].m_rx_disTO = false; + _socTxS[i].m_tx_wnc_state = TX_IDLE; + + *handle = &_sockets[i]; + + debugOutput("EXIT socket_open; Socket=%d, OPEN=%s, protocol =%s", + i, _sockets[i].opened?"YES":"NO", (!_sockets[i].proto)?"UDP":"TCP"); + + return (m_errors = NSAPI_ERROR_OK); +} + +int WNC14A2AInterface::socket_connect(void *handle, const SocketAddress &address) +{ + WNCSOCKET *wnc = (WNCSOCKET *)handle; + int err = 0; + + debugOutput("ENTER socket_connect(); Socket=%d; IP=%s; PORT=%d;", wnc->socket, address.get_ip_address(), address.get_port()); + + if (!wnc->opened ) + return (m_errors = NSAPI_ERROR_NO_SOCKET); + + wnc->addr = address; + + _pwnc_mutex.lock(); + if( wnc->url.empty() ) + err = !m_pwnc->openSocketIpAddr(wnc->socket, address.get_ip_address(), address.get_port(), wnc->proto, WNC14A2A_COMMUNICATION_TIMEOUT); + else + err = !m_pwnc->openSocketUrl(wnc->socket, wnc->url.c_str(), wnc->addr.get_port(), wnc->proto); + _pwnc_mutex.unlock(); + + if( !err ) { + wnc->connected = true; + _socRxS[wnc->socket].m_rx_wnc_state = READ_START; + _socTxS[wnc->socket].m_tx_wnc_state = TX_IDLE; + + if( wnc->_callback != NULL ) + wnc->_callback( wnc->_cb_data ); + } + + return err; +} + +int WNC14A2AInterface::socket_close(void *handle) +{ + WNCSOCKET *wnc = (WNCSOCKET*)handle; + RXEVENT *rxsock; + TXEVENT *txsock; + bool err = false; + + debugOutput("ENTER socket_close()"); + + rxsock = &_socRxS[wnc->socket]; + txsock = &_socTxS[wnc->socket]; + + txsock->m_tx_wnc_state = TX_IDLE; //reset TX state + if( rxsock->m_rx_wnc_state != READ_START ) { //reset RX state + rxsock->m_rx_disTO=false; + while( rxsock->m_rx_wnc_state != DATA_AVAILABLE ) + wait(1); //someone called close while a read was happening + } + + _pwnc_mutex.lock(); + if( !m_pwnc->closeSocket(wnc->socket) ) { + m_errors = NSAPI_ERROR_DEVICE_ERROR; + err = true; + } + _pwnc_mutex.unlock(); + + if( !err ) { + wnc->opened = false; //no longer in use + wnc->addr = NULL; //not open + wnc->connected= false; + wnc->proto = 1; //assume TCP for now + m_errors = NSAPI_ERROR_OK; + wnc->_cb_data = NULL; + wnc->_callback= NULL; + } + + debugOutput("EXIT socket_close()"); + return err; +} + + +void WNC14A2AInterface::socket_attach(void *handle, void (*callback)(void *), void *data) +{ + WNCSOCKET *wnc = (WNCSOCKET *)handle; + + debugOutput("ENTER/EXIT socket_attach()"); + wnc->_callback = callback; + wnc->_cb_data = data; +} + +int WNC14A2AInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size) +{ + WNCSOCKET *wnc = (WNCSOCKET *)handle; + + debugOutput("ENTER socket_sendto()"); + + if (!wnc->connected) { + int err = socket_connect(wnc, address); + if (err < 0) + return err; + } + wnc->addr = address; + + debugOutput("EXIT socket_sendto()"); + return socket_send(wnc, data, size); +} + +int WNC14A2AInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size) +{ + WNCSOCKET *wnc = (WNCSOCKET *)handle; + debugOutput("ENTER socket_recvfrom()"); + + if (!wnc->connected) { + debugOutput("need to open a WNC socket first"); + int err = socket_connect(wnc, *address); + if (err < 0) + return err; + } + + int ret = socket_recv(wnc, (char *)buffer, size); + if (ret >= 0 && address) + *address = wnc->addr; + debugOutput("EXIT socket_recvfrom()"); + return ret; +} + + +int inline WNC14A2AInterface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address) +{ + debugOutput("ENTER/EXIT socket_accept() -- not supported"); + m_errors = NSAPI_ERROR_UNSUPPORTED; + return -1; +} + +int inline WNC14A2AInterface::socket_bind(void *handle, const SocketAddress &address) +{ + WNCSOCKET *wnc = (WNCSOCKET *)handle; + + debugOutput("ENTER/EXIT socket_bind(), use address '%s', port %d", address.get_ip_address(),address.get_port()); + _socRxS[wnc->socket].m_rx_disTO=true; //for us, simply disable the Rx timeout to keep monitoring for data + return (m_errors = NSAPI_ERROR_OK); +} + + +int inline WNC14A2AInterface::socket_listen(void *handle, int backlog) +{ + debugOutput("ENTER/EXIT socket_listen() -- not supported"); + m_errors = NSAPI_ERROR_UNSUPPORTED; + return -1; +} + + +int WNC14A2AInterface::socket_send(void *handle, const void *data, unsigned size) +{ + WNCSOCKET *wnc = (WNCSOCKET *)handle; + TXEVENT *txsock; + + debugOutput("ENTER socket_send() send %d bytes",size); + txsock = &_socTxS[wnc->socket]; + + if( size < 1 || data == NULL ) // should never happen but have seen it + return 0; + + switch( txsock->m_tx_wnc_state ) { + case TX_IDLE: + txsock->m_tx_wnc_state = TX_STARTING; + debugDump_arry((const uint8_t*)data,size); + txsock->m_tx_dptr = (uint8_t*)data; + txsock->m_tx_orig_size = size; + txsock->m_tx_req_size = (uint32_t)size; + txsock->m_tx_total_sent= 0; + txsock->m_tx_callback = wnc->_callback; + txsock->m_tx_cb_data = wnc->_cb_data; + + if( txsock->m_tx_req_size > UART_BUFF_SIZE ) + txsock->m_tx_req_size= UART_BUFF_SIZE; + + if( !tx_event(txsock) ) { //if we didn't sent all the data at once, continue in background + txsock->m_tx_wnc_state = TX_ACTIVE; + wnc_queue.call_in(EQ_FREQ,mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::wnc_eq_event)); + return NSAPI_ERROR_WOULD_BLOCK; + } + // fall through + + case TX_COMPLETE: + debugOutput("EXIT socket_send(), sent %d bytes", txsock->m_tx_total_sent); + txsock->m_tx_wnc_state = TX_IDLE; + return txsock->m_tx_total_sent; + + case TX_ACTIVE: + case TX_STARTING: + return NSAPI_ERROR_WOULD_BLOCK; + + default: + debugOutput("EXIT socket_send(), NSAPI_ERROR_DEVICE_ERROR"); + return (m_errors = NSAPI_ERROR_DEVICE_ERROR); + } +} + +int WNC14A2AInterface::tx_event(TXEVENT *ptr) +{ + debugOutput("ENTER tx_event(), socket %d",ptr->m_tx_socket); + + _pwnc_mutex.lock(); + if( m_pwnc->write(ptr->m_tx_socket, ptr->m_tx_dptr, ptr->m_tx_req_size) ) + ptr->m_tx_total_sent += ptr->m_tx_req_size; + _pwnc_mutex.unlock(); + + if( ptr->m_tx_total_sent < ptr->m_tx_orig_size ) { + ptr->m_tx_dptr += ptr->m_tx_req_size; + ptr->m_tx_req_size = ptr->m_tx_orig_size-ptr->m_tx_total_sent; + + if( ptr->m_tx_req_size > UART_BUFF_SIZE) + ptr->m_tx_req_size= UART_BUFF_SIZE; + + debugOutput("EXIT tx_event(), send %d more bytes.",ptr->m_tx_req_size); + return 0; + } + debugOutput("EXIT tx_event, socket %d, data sent",ptr->m_tx_socket); + ptr->m_tx_wnc_state = TX_COMPLETE; + if( ptr->m_tx_callback != NULL ) + ptr->m_tx_callback( ptr->m_tx_cb_data ); + ptr->m_tx_cb_data = NULL; + ptr->m_tx_callback = NULL; + + return 1; +} + +int WNC14A2AInterface::socket_recv(void *handle, void *data, unsigned size) +{ + WNCSOCKET *wnc = (WNCSOCKET *)handle; + RXEVENT *rxsock; + + rxsock = &_socRxS[wnc->socket]; + debugOutput("ENTER socket_recv(), socket %d, request %d bytes",wnc->socket, size); + + if( size < 1 || data == NULL ) { // should never happen + return 0; + } + + switch( rxsock->m_rx_wnc_state ) { + case READ_START: //need to start a read sequence of events + rxsock->m_rx_wnc_state= READ_INIT; + rxsock->m_rx_dptr = (uint8_t*)data; + rxsock->m_rx_req_size = (uint32_t)size; + rxsock->m_rx_total_cnt= 0; + rxsock->m_rx_timer = 0; + rxsock->m_rx_return_cnt=0; + + if( rxsock->m_rx_req_size > WNC_BUFF_SIZE) + rxsock->m_rx_req_size= WNC_BUFF_SIZE; + + rxsock->m_rx_callback = wnc->_callback; + rxsock->m_rx_cb_data = wnc->_cb_data; + + if( !rx_event(rxsock) ){ + rxsock->m_rx_wnc_state = READ_ACTIVE; + wnc_queue.call_in(EQ_FREQ,mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::wnc_eq_event)); + return NSAPI_ERROR_WOULD_BLOCK; + } + // fall through + + case DATA_AVAILABLE: + debugOutput("EXIT socket_recv(),socket %d, return %d bytes",wnc->socket, rxsock->m_rx_return_cnt); + debugDump_arry((const uint8_t*)data,rxsock->m_rx_return_cnt); + rxsock->m_rx_wnc_state = READ_START; + return rxsock->m_rx_return_cnt; + + case READ_ACTIVE: + case READ_INIT: +//jmf rxsock->m_rx_timer = 0; //reset the time-out timer + return NSAPI_ERROR_WOULD_BLOCK; + + default: + debugOutput("EXIT socket_recv(), NSAPI_ERROR_DEVICE_ERROR"); + return (m_errors = NSAPI_ERROR_DEVICE_ERROR); + } +} + + +int WNC14A2AInterface::rx_event(RXEVENT *ptr) +{ + debugOutput("ENTER rx_event() for socket %d", ptr->m_rx_socket); + _pwnc_mutex.lock(); + int cnt = m_pwnc->read(ptr->m_rx_socket, ptr->m_rx_dptr, ptr->m_rx_req_size); + _pwnc_mutex.unlock(); + + if( cnt ) { //got data, return it to the caller + debugOutput("data received on socket %d, cnt=%d", ptr->m_rx_socket,cnt); + ptr->m_rx_wnc_state = DATA_AVAILABLE; + ptr->m_rx_return_cnt = cnt; + if( ptr->m_rx_callback != NULL ) + ptr->m_rx_callback( ptr->m_rx_cb_data ); + ptr->m_rx_cb_data = NULL; + ptr->m_rx_callback = NULL; + return 1; + } + if( ++ptr->m_rx_timer > (WNC14A2A_READ_TIMEOUTMS/EQ_FREQ) && !ptr->m_rx_disTO ) { //timed out waiting, return 0 to caller + debugOutput("EXIT rx_event(), rx data TIME-OUT!"); + ptr->m_rx_wnc_state = DATA_AVAILABLE; + ptr->m_rx_return_cnt = 0; + if( ptr->m_rx_callback != NULL ) + ptr->m_rx_callback( ptr->m_rx_cb_data ); + ptr->m_rx_cb_data = NULL; + ptr->m_rx_callback = NULL; + return 1; + } + + debugOutput("EXIT rx_event(), socket %d, sechedule for more data.",ptr->m_rx_socket); + return 0; +} + +void WNC14A2AInterface::wnc_eq_event() +{ + int done = 1; + bool goSlow = true; + + for( unsigned int i=0; i<WNC14A2A_SOCKET_COUNT; i++ ) { + if( _socRxS[i].m_rx_wnc_state == READ_ACTIVE || _socRxS[i].m_rx_disTO) { + done &= rx_event(&_socRxS[i]); + goSlow &= ( _socRxS[i].m_rx_timer > ((WNC14A2A_READ_TIMEOUTMS/EQ_FREQ)*(EQ_FREQ_SLOW/EQ_FREQ)) ); + + if( goSlow ) + _socRxS[i].m_rx_timer = (WNC14A2A_READ_TIMEOUTMS/EQ_FREQ)*(EQ_FREQ_SLOW/EQ_FREQ); + } + + if( _socTxS[i].m_tx_wnc_state == TX_ACTIVE ) { + goSlow = false; + debugOutput("CALL TX_event() for socket %d", i); + done &= tx_event(&_socTxS[i]); + } + } + + if( !done ) + wnc_queue.call_in((goSlow?EQ_FREQ_SLOW:EQ_FREQ),mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::wnc_eq_event)); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/WNC14A2AInterface/WNC14A2AInterface.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,508 @@ +/** +* copyright (c) 2017-2018, James Flynn +* 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. +*/ + +/** +* @file WNC14A2AInterface.h +* @brief Implements a standard NetworkInterface class for use with WNC M14A2A +* data module. +* +* @author James Flynn +* +* @date 1-Feb-2018 +* +*/ + +#ifndef WNC14A2A_INTERFACE_H +#define WNC14A2A_INTERFACE_H + +#include <stdint.h> + +#include "mbed.h" +#include "Callback.h" +#include "WNCDebug.h" +#include "WncControllerK64F/WncControllerK64F.h" + +#define WNC14A2A_SOCKET_COUNT WncController::MAX_NUM_WNC_SOCKETS + +// If target board does not support Arduino pins, define pins as Not Connected +#if defined(TARGET_FF_ARDUINO) +#if !defined(MBED_CONF_WNC14A2A_LIBRARY_WNC_RX_BOOT_SEL) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_RX_BOOT_SEL D1 +#endif +#if !defined(MBED_CONF_WNC14A2A_LIBRARY_WNC_POWER_ON) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_POWER_ON D2 +#endif +#if !defined(MBED_CONF_WNC14A2A_LIBRARY_WNC_WAKEUP) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_WAKEUP D6 +#endif +#if !defined(MBED_CONF_WNC14A2A_LIBRARY_WNC_RESET) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_RESET D8 +#endif +#if !defined(MBED_CONF_WNC14A2A_LIBRARY_WNC_LVLTRANSLATOR) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_LVLTRANSLATOR D9 +#endif +#if !defined(MBED_CONF_WNC14A2A_LIBRARY_WNC_CTS) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_CTS D10 +#endif +#if !defined(MBED_CONF_WNC14A2A_LIBRARY_WNC_RXD) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_RXD D11 +#endif +#if !defined(MBED_CONF_WNC14A2A_LIBRARY_WNC_TXD) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_TXD D12 +#endif +#else // !defined(TARGET_FF_ARDUINO) +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_RX_BOOT_SEL NC +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_POWER_ON NC +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_WAKEUP NC +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_RESET NC +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_LVLTRANSLATOR NC +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_CTS NC +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_RXD NC +#define MBED_CONF_WNC14A2A_LIBRARY_WNC_TXD NC +#endif // !defined(TARGET_FF_ARDUINO) + +typedef struct smsmsg_t { + string number; + string date; + string time; + string msg; + } IOTSMS; + +typedef struct socket_t { + int socket; //index of this socket + string url; + SocketAddress addr; //address info for this socket + bool opened; //is the socket opened + bool connected; //is the socket connected + int proto; //this is a TCP or UDP socket + void (*_callback)(void*); //callback used with attach + void *_cb_data; //callback data to be returned + } WNCSOCKET; + +typedef struct rx_event_t { + int m_rx_wnc_state; //state of the socket receive + int m_rx_socket; //which socket is being rcvd on + uint8_t *m_rx_dptr; //pointer to the users data buffer + uint32_t m_rx_req_size; //Requested number of bytes to receive + uint32_t m_rx_total_cnt; //Total number of bytes received + int m_rx_timer; //Rx Timeout Timer + int m_rx_disTO; //Flag to disable Timeout Timer + void (*m_rx_callback)(void*); //callback used with attach + void *m_rx_cb_data; //callback data to be returned + uint32_t m_rx_return_cnt; //number of bytes the Event Queue is returning + } RXEVENT; + +typedef struct tx_event_t { + // Transmit Interrupt simulation to enabled non-blocking operation + int m_tx_wnc_state; + int m_tx_socket; + uint8_t *m_tx_dptr; + unsigned m_tx_orig_size; + uint32_t m_tx_req_size; + uint32_t m_tx_total_sent; + void (*m_tx_callback)(void*); + void *m_tx_cb_data; + } TXEVENT; + +#define WNC_DEBUG 0 //1=enable the WNC startup debug output + //0=disable the WNC startup debug output +#define STOP_ON_FE 1 //1=hang forever if a fatal error occurs + //0=simply return failed response for all socket calls +#define DISPLAY_FE 1 //1 to display the fatal error when it occurs + //0 to NOT display the fatal error +#define RESETON_FE 0 //1 to cause the MCU to reset on fatal error + //0 to NOT reset the MCU + +#define APN_DEFAULT "m2m.com.attz" + +/** Error Handling macros & data +* @brief The macros CHK_WNCFE is used to check if a fatal error has occured. If it has +* then execute the action specified: fail, void, null, resume +* +* CHK_WNCFE( condition-to-check, fail|void|null|resume ) +* +* 'fail' if you want FATAL_WNC_ERROR to be called. +* 'void' if you want to execute a void return +* 'null' if you want to execute a null return +* 'resume' if you simply want to resume program execution +* +* There are several settings that control how FATAL_WNC_ERROR behaves: +* 1) RESETON_FE determines if the system will reset or hang. +* 2) DISPLAY_FE determine if an error message is generated or not +* +* The DISPLAY_FE setting determines if a failure message is displayed. +* If set to 1, user sees this messageo: +* +* WNC FAILED @ source-file-name:source-file-line-number +* +* if not set, nothing is displayed. +*/ + +#define FATAL_FLAG WncController::WNC_NO_RESPONSE +#define WNC_GOOD WncController::WNC_ON + +#define RETfail return -1 +#define RETvoid return +#define RETnull return NULL +#define RETresume + +#define DORET(x) RET##x + +#define TOSTR(x) #x +#define INTSTR(x) TOSTR(x) +#define FATAL_STR (char*)(__FILE__ ":" INTSTR(__LINE__)) + +#if RESETON_FE == 1 //reset on fatal error +#define MCURESET ((*((volatile unsigned long *)0xE000ED0CU))=(unsigned long)((0x5fa<<16) | 0x04L)) +#define RSTMSG "RESET MCU! " +#else +#define MCURESET +#define RSTMSG "" +#endif + +#if DISPLAY_FE == 1 //display fatal error message +#define PFE {if(_debugUart)_debugUart->printf((char*)RSTMSG "\r\n>>WNC FAILED @ %s\r\n", FATAL_STR);} +#else +#define PFE +#endif + +#if STOP_ON_FE == 1 //halt cpu on fatal error +#define FATAL_WNC_ERROR(v) {_fatal_err_loc=FATAL_STR;PFE;MCURESET;while(1);} +#else +#define FATAL_WNC_ERROR(v) {_fatal_err_loc=FATAL_STR;PFE;DORET(v);} +#endif + +#define CHK_WNCFE(x,y) if( x ){FATAL_WNC_ERROR(y);} + +#define FIRMWARE_REV(x) (((WNC14A2AInterface*)x)->getWNCRev()) +#define DBGMSG_DRV 0x04 +#define DBGMSG_EQ 0x08 +#define DBGMSG_SMS 0x10 +#define DBGMSG_ARRY 0x20 + +#define MAX_SMS_MSGS 3 + +using namespace WncController_fk; + +/** WNC14A2AInterface class + * Implementation of the NetworkInterface for WNC14A2A + */ +class WNC14A2AInterface : public NetworkStack, public NetworkInterface +{ +public: + + /** WNC14A2AInterface Constructor. + * @param optionally include a pointer to WNCDEBUG object for + * debug information to be displayed. + */ + WNC14A2AInterface(WNCDebug *_dbgUart = NULL); + virtual ~WNC14A2AInterface(); + + /** Set the cellular network credentials + * + * @param apn Optional, APN of network + * @param user Optional, username --not used-- + * @param pass Optional, password --not used-- + * @return nsapi_error_t + */ + virtual nsapi_error_t set_credentials(const char *apn = 0, + const char *username = 0, const char *password = 0); + + /** Connect to the network + * + * @param apn Optional, APN of network + * @param user Optional, username --not used-- + * @param pass Optional, password --not used-- + * @return nsapi_error_t + */ + virtual nsapi_error_t connect(const char *apn, + const char *username = 0, const char *password = 0); + + /** Connect to the network (no parameters) + * + * @return nsapi_error_t + */ + virtual nsapi_error_t connect(); + + /** disconnect from the network + * + * provided for completness, but function does nothing becase + * WNC part can not disconnect from network once connected. + * + * @return nsapi_error_t + */ + virtual nsapi_error_t disconnect(); + + /** Get the IP address of WNC device. From NetworkStack Class + * + * @return IP address string or null + */ + virtual const char *get_ip_address(); + + /** Get the network assigned IP address. + * + * @return IP address or null + */ + const char *get_my_ip_address(); + + /** Get the MAC address of the WNC device. + * + * @return MAC address of the interface + */ + virtual const char *get_mac_address(); + + /** Attach a callback function for when a SMS is recevied + * + * @param function pointer to call + */ + void sms_attach(void (*callback)(IOTSMS *)); + + /** Set the level of Debug output + * + * @param bit field + * basic AT command info= 0x01 + * more AT command info = 0x02 + * mbed driver info = 0x04 + * dump buffers = 0x08 + * all debug = 0x0f + */ + void doDebug(int v); + + /** Return the WNC reported Firmware Revision + * + * @param none. + */ + const char* getWNCRev(void); + + /** Query registered state of WNC + * + * @return true if registerd, false if not + */ + bool registered(); + + /** Start the SMS monitoring service + */ + void sms_start(void); + + /** start listening for incomming SMS messages + * + * @param time in msec to check + */ + void sms_listen(uint16_t=1000); // Configure device to listen for text messages + + /** retrieve a SMS message + * + * @param pointer to an array of IOTSMS messages + */ + int getSMS(IOTSMS **msg); + + /** send a SMS message + * + * @param a string containing number to send message to + * @param a string containing message to send + * @return true on success, 0 on failure + */ + int sendIOTSms(const string&, const string&); + + /** return this devices SMS number + * + * @brief The IOTSMS number used, isn't phone number, it is device ICCID. + * + * @return this devices IOTSMS number + */ + char* getSMSnbr(); + + +protected: + + /** Get Host IP by name. + * + * @return nsapi_error_t + */ + virtual nsapi_error_t gethostbyname(const char* name, SocketAddress *address, nsapi_version_t version); + + + /** return a pointer to the NetworkStack object + * + * @return The underlying NetworkStack object + */ + virtual NetworkStack *get_stack(); + + /** 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 + */ + virtual int socket_close(void *handle); + + /** Bind a server socket to a specific port. + * + * @brief Bind the socket to a specific port + * @param handle Socket handle + * @param address address to listen for + * @return 0; + */ + virtual int socket_bind(void *handle, const SocketAddress &address); + + /** Start listening for incoming connections. + * + * @brief NOT SUPPORTED + * @param handle Socket handle + * @param backlog Number of pending connections that can be queued up at any + * one time [Default: 1] + * @return NSAPI_ERROR_UNSUPPORTED; + * @note This function causes the receive time-out to be ignored resulting in continuous + * monitoring of received data. This is non-standard behaviour but it is how the + * mbed-cloud servcies use it... + */ + virtual int socket_listen(void *handle, int backlog); + + /** Accept a new connection. + * + * @brief NOT SUPPORTED + * @return NSAPI_ERROR_UNSUPPORTED; + */ + virtual int socket_accept(nsapi_socket_t server, + nsapi_socket_t *handle, SocketAddress *address=0); + + /** Connects this socket to the server. + * + * @param handle Socket handle + * @param address SocketAddress + * @return 0 on success, negative on failure + */ + virtual int socket_connect(void *handle, const SocketAddress &address); + + /** Send data to the remote host. + * + * @param handle Socket handle + * @param data buffer to send + * @param size length of buffer + * @return Number of bytes written or negative on failure + * + * @note This call is blocking. + */ + virtual int socket_send(void *handle, const void *data, unsigned size); + + /** Receive data from the remote host. + * + * @param handle Socket handle + * @param data buffer to store the recived data + * @param size bytes to receive + * @return received bytes received, negative on failure + * + * @note This call is not-blocking + */ + virtual int socket_recv(void *handle, void *data, unsigned size); + + /** Send a packet to a remote endpoint. + * + * @param handle Socket handle + * @param address SocketAddress + * @param data data to send + * @param size number of bytes to send + * @return the number of bytes sent or negative on failure + * + * @note This call is blocking. + */ + virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size); + + /** Receive packet remote endpoint + * + * @param handle Socket handle + * @param address SocketAddress + * @param buffer buffer to store data to + * @param size number of bytes to receive + * @return the number bytes received or negative on failure + * + * @note This call is not-blocking. + */ + 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); + + /** get the status of internal errors + * + * @brief Called after any WNC14A2A operation to determine error specifics + * @param none. + */ + uint16_t wnc14a2a_chk_error(void) { return m_errors; } + +private: + + //! WncController Class for interacting with the 14A2a hardware + friend class WncControllerK64F; + + bool m_wncpoweredup; //track if WNC has been power-up + unsigned m_debug; + + WncIpStats myNetStats; //maintaint the network statistics + WncControllerK64F_fk::WncControllerK64F *m_pwnc; //pointer to the WncController instance + + WNCDebug *_debugUart; // Serial object for parser to communicate with radio + char *_fatal_err_loc; // holds string containing location of fatal error + nsapi_error_t m_errors; + + bool m_smsmoning; // Track if the SMS monitoring thread is running + EventQueue sms_queue; // Queue used to schedule for SMS checks + void (*_sms_cb)(IOTSMS *); // Callback when text message is received. User must define this as + // a static function because I'm not handling an object offset + IOTSMS m_MsgText, m_MsgText_array[MAX_SMS_MSGS]; // Used to pass SMS message to the user + struct WncController::WncSmsList m_smsmsgs; //use the WncSmsList structure to hold messages + + EventQueue wnc_queue; // Queue used to schedule for receiving data + void handle_sms_event(); // SMS tx/rx handler + void wnc_eq_event(); // Simulated ISR + int rx_event(RXEVENT *); // receive data handler + int tx_event(TXEVENT *); // tx data handler + + char _mac_address[NSAPI_MAC_SIZE]; // local Mac + void _dbOut(const char *format, ...); + void _dbDump_arry( const uint8_t* data, unsigned int size ); + + WNCSOCKET _sockets[WNC14A2A_SOCKET_COUNT]; //WNC supports 8 open sockets but driver only supports 1 currently + TXEVENT _socTxS[WNC14A2A_SOCKET_COUNT]; + RXEVENT _socRxS[WNC14A2A_SOCKET_COUNT]; + Thread _smsThread, _eqThread; //Event Queue thread for SMS and Rx/Tx data + Mutex _pwnc_mutex; + int _active_socket; + + UARTSerial mdmUart; + WncIO wnc_io; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/WNC14A2AInterface/WNCDebug.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,99 @@ +/** +* copyright (c) 2017-2018, James Flynn +* 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. +*/ + +/** +* @file WNCDebug.h +* @brief A debug class that coordinates the output of debug messages to +* either stdio or a serial port based on instantiation. +* +* @author James Flynn +* +* @date 1-Feb-2018 +* +*/ + +#ifndef __WNCDEBUG__ +#define __WNCDEBUG__ +#include <stdio.h> +#include "WNCIO.h" + +/** WNCDebug class +* Used to write debug data to the user designated IO. Currently +* The class expects either a stdio element (defaults to stderr) or +* a pointer to a WncIO object. +*/ + +class WNCDebug +{ +public: + //! Create class with either stdio or a pointer to a uart + WNCDebug( FILE * fd = stderr ): m_puart(NULL) {m_stdiofp=fd;}; + WNCDebug( WncIO * uart): m_stdiofp(NULL) {m_puart=uart;}; + ~WNCDebug() {}; + + //! standard printf() functionallity + int printf( char * fmt, ...) { + char buffer[256]; + int ret=0; + va_list args; + va_start (args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + prt.lock(); + if( m_stdiofp ) + ret=fputs(buffer,m_stdiofp); + else + ret=m_puart->puts(buffer); + prt.unlock(); + va_end (args); + return ret; + } + + //! standard putc() functionallity + int putc( int c ) { + int ret=0; + prt.lock(); + if( m_stdiofp ) + ret=fputc(c, m_stdiofp); + else + ret=m_puart->putc(c); + prt.unlock(); + return ret; + } + + //! standard puts() functionallity + int puts( const char * str ) { + int ret=0; + prt.lock(); + if( m_stdiofp ) + ret=fputs(str,m_stdiofp); + else + ret=m_puart->puts(str); + prt.unlock(); + return ret; + } + +private: + std::FILE *m_stdiofp; + WncIO *m_puart; + Mutex prt; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/WNC14A2AInterface/WNCIO.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,102 @@ +/** +* copyright (c) 2017-2018, James Flynn +* 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. +*/ + +/** +* @file WNCIO.h +* @brief A class that WNCInterface uses for input/output +* +* @author James Flynn +* +* @date 1-Feb-2018 +* +*/ + +#ifndef __WNCIO__ +#define __WNCIO__ +#include <stdio.h> +#include "mbed.h" + +/** WncIO class +* Used to read/write the WNC UART using FILE I/O. +*/ + +class WncIO +{ +public: + //! Create class with either stdio or a pointer to a uart + WncIO( UARTSerial * uart): m_puart(uart) {;} + ~WncIO() {}; + + //! standard printf() functionallity + int printf( char * fmt, ...) { + char buffer[256]; + int ret=0; + va_list args; + va_start (args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + prt.lock(); + ret=m_puart->write(buffer,strlen(buffer)); + prt.unlock(); + va_end (args); + return ret; + } + + //! standard putc() functionallity + int putc( int c ) { + int ret=0; + prt.lock(); + ret=m_puart->write((const void*)&c,1); + prt.unlock(); + return ret; + } + + //! standard puts() functionallity + int puts( const char * str ) { + int ret=0; + prt.lock(); + ret=m_puart->write(str,strlen(str)); + prt.unlock(); + return ret; + } + + //! return true when data is available, false otherwise + bool readable( void ) { + return m_puart->readable(); + } + + //! get the next character available from the uart + int getc( void ) { + char c; + m_puart->read( &c, 1 ); + return c; + } + + //! set the uart baud rate + void baud( int baud ) { + m_puart->set_baud(baud); + } + +private: + UARTSerial *m_puart; + Mutex prt; +}; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/WNC14A2AInterface/WncControllerK64F/WncController/WncController.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,2152 @@ +/* + Copyright (c) 2016 Fred Kellerman + + 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 WncController.cpp + @purpose Controls WNC 14A2A Cellular Modem + @version 1.0 + @date July 2016 + @author Fred Kellerman + + + An Example of usage: + + WncControllerK64F mdm(&wncPinList, &mdmUart, &debugUart); + + mdm.enableDebug(true, true); + + if (false == mdm.powerWncOn("m2m.com.attz", 60)) { + while(1); + } + + // ICCID and MSISDN + string iccid; string msisdn; + if (mdm.getICCID(&iccid) == true) { + if (mdm.convertICCIDtoMSISDN(iccid, &msisdn) == true) { + // Send an SMS message (must use 15-digit MISDN number!) + mdm.sendSMSText(msisdn.c_str(), "Hello from WNC Kit -> from WNC"); + } + } + + // Get an IP address setup for the socket #1 (0 indexed)) + if (true == mdm.resolveUrl(0, "www.att.com")) + { + // Report server IP + if (true == mdm.getIpAddr(0, ipAddrStr)) { + debugUart.puts("Server IP: "); + debugUart.puts(ipAddrStr); + debugUart.puts("\r\n"); + } + + // Open Socket #1, TCP=true resolved IP on port 80: + if (true == mdm.openSocket(0, 80, true)) { + // Write some data + const uint8_t * dataStr = "GET /index.html HTTP/1.0\r\nFrom: someuser@someuser.com\r\nUser-Agent: HTTPTool/1.0\r\n\r\n"; + if (true == mdm.write(0, dataStr, strlen((const char *)dataStr))) + { + const uint8_t * myBuf; + mdm.setReadRetries(0, 20); + uint32_t n = mdm.read(0, &myBuf); + if (n > 0) + debugUart.printf("Read %d chars: %s\r\n", n, myBuf); + else + debugUart.puts("No read data!\r\n"); + } + } + } + +*/ + + +#include <cstdlib> +#include <cctype> +#include <string.h> +#include "WncController.h" + +namespace WncController_fk { + +///////////////////////////////////////////////////// +// Static initializers +///////////////////////////////////////////////////// + +const char * const WncController::INVALID_IP_STR = ""; + + +/** + * C++ version 0.4 char* style "itoa": + * Written by Lukás Chmela + * Released under GPLv3. + */ +static char* itoa(int64_t value, char* result, int base) +{ + // check that the base is valid + if ( base < 2 || base > 36 ) { + *result = '\0'; + return result; + } + + char* ptr = result, *ptr1 = result, tmp_char; + int64_t tmp_value; + + do { + tmp_value = value; + value /= base; + *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + (tmp_value - value * base)]; + } while ( value ); + + // Apply negative sign + if ( tmp_value < 0 ) + *ptr++ = '-'; + + *ptr-- = '\0'; + + while ( ptr1 < ptr ) { + tmp_char = *ptr; + *ptr-- = *ptr1; + *ptr1++ = tmp_char; + } + + return result; +} + +const char * WncController::_to_string(int64_t value) +{ + static char str[21]; // room for signed 64-bit + null + itoa(value, str, 10); + return (str); +} + +const char * WncController::_to_hex_string(uint8_t value) +{ + static char str[3]; // room for 8-bit + null + itoa(value, str, 16); + return (str); +} + +WncController::WncController(void) : + m_sState(WNC_OFF), + m_sCmdTimeoutMs(WNC_CMD_TIMEOUT_MS), + m_sApnStr("NULL"), + m_sPowerUpTimeoutSecs(MAX_POWERUP_TIMEOUT), + m_sDebugEnabled(false), + m_sMoreDebugEnabled(false), + m_sCheckNetStatus(false), // Turn on internet status check between every command + m_sReadyForSMS(false) +{ + static const WncController::WncSocketInfo_s defaultSockStruct = { 0, false, "192.168.0.1", 80, 0, 25, true, 30 }; + + for(unsigned i=0; i<MAX_NUM_WNC_SOCKETS; i++) + m_sSock[i] = defaultSockStruct; +} + +WncController::~WncController(void) {}; + +const char* WncController::getFirmRev(void) +{ + return m_FirmwareRevision.c_str(); +} + +void WncController::enableDebug(bool on, bool moreDebugOn) +{ + m_sDebugEnabled = on; + m_sMoreDebugEnabled = moreDebugOn; +} + +WncController::WncState_e WncController::getWncStatus(void) +{ + return (m_sState); +} + +int16_t WncController::getDbmRssi(void) +{ + int16_t rssi, ber; + if (at_getrssiber_wnc(&rssi, &ber) == true) + return (rssi); + else + return (99); +} + +int16_t WncController::get3gBer(void) +{ + int16_t rssi, ber; + if (at_getrssiber_wnc(&rssi, &ber) == true) + return (ber); + else + return (99); +} + +bool WncController::powerWncOn(const char * const apn, uint8_t powerUpTimeoutSecs) +{ + dbgPuts("Waiting for WNC to Initialize..."); + m_sPowerUpTimeoutSecs = powerUpTimeoutSecs; + m_sState = WNC_ON_NO_CELL_LINK; // Turn soft on to allow "AT" for init to be sent! + if (initWncModem(powerUpTimeoutSecs) == true) { + // Set the Apn + setApnName(apn); + if (false == softwareInitMdm()) { + dbgPuts("Software init failed!"); + m_sState = WNC_OFF; + } + } + else { + dbgPuts("Power up failed!"); + m_sState = WNC_OFF; + } + + return ((m_sState == WNC_ON) || (m_sState == WNC_ON_NO_CELL_LINK)); +} + +size_t WncController::sendCustomCmd(const char * cmd, char * resp, size_t sizeRespBuf, int ms_timeout) +{ + string * respStr; + + if (sizeRespBuf > 0) { + at_send_wnc_cmd(cmd, &respStr, ms_timeout); + strncpy(resp, respStr->c_str(), sizeRespBuf); + if (respStr->size() > sizeRespBuf) + dbgPuts("sendCustomCmd truncated!"); + + return (respStr->size()); + } + + dbgPuts("sendCustomCmd: would have overrun!"); + + return (0); +} + +bool WncController::pingUrl(const char * url) +{ + string ipAddr; + + if (true == at_dnsresolve_wnc(url, &ipAddr)) + return (pingIp(ipAddr.c_str())); + else + dbgPuts("pingUrl DNS resolve: failed!"); + + return (false); +} + +bool WncController::pingIp(const char * ip) +{ + if (true == at_ping_wnc(ip)) + return (true); + else + dbgPuts("pingIp: failed!"); + + return (false); +} + +bool WncController::getWncNetworkingStats(WncIpStats * s) +{ + return (at_get_wnc_net_stats(s)); +} + +bool WncController::getIpAddr(uint16_t numSock, char myIpAddr[MAX_LEN_IP_STR]) +{ + if (numSock < MAX_NUM_WNC_SOCKETS) { + strncpy(myIpAddr, m_sSock[numSock].myIpAddressStr.c_str(), MAX_LEN_IP_STR); + myIpAddr[MAX_LEN_IP_STR - 1] = '\0'; + return (true); + } + else { + myIpAddr[0] = '\0'; + return (false); + } +} + +bool WncController::setApnName(const char * const apnStr) +{ + if (at_setapn_wnc(apnStr) == true) + { + m_sApnStr = apnStr; + return (true); + } + else + return (false); +} + +bool WncController::resolveUrl(uint16_t numSock, const char * url) +{ + bool cmdRes; + + if (numSock < MAX_NUM_WNC_SOCKETS) { + if (strlen(url) > 0) { + cmdRes = at_dnsresolve_wnc(url, &m_sSock[numSock].myIpAddressStr); + if (cmdRes == false) + dbgPuts("Cannot resolve URL!"); + return (cmdRes); + } + else + dbgPuts("Invalid URL"); + } + else + dbgPuts("Invalid Sock num!"); + + return (false); +} + +bool WncController::setIpAddr(uint16_t numSock, const char * ipStr) +{ + if (numSock < MAX_NUM_WNC_SOCKETS) { + m_sSock[numSock].myIpAddressStr = ipStr; + return (true); + } + else { + dbgPuts("Bad socket num!"); + return (false); + } +} + +void WncController::setWncCmdTimeout(uint16_t toMs) +{ + m_sCmdTimeoutMs = toMs; +} + +bool WncController::openSocketUrl(uint16_t numSock, const char * url, uint16_t port, bool tcp, uint16_t timeOutSec) +{ + if (resolveUrl(numSock, url) == true) + return (openSocket(numSock, port, tcp, timeOutSec)); + + return (false); +} + +bool WncController::openSocketIpAddr(uint16_t numSock, const char * ipAddr, uint16_t port, bool tcp, uint16_t timeOutSec) +{ + if (setIpAddr(numSock, ipAddr) == true) + return (openSocket(numSock, port, tcp, timeOutSec)); + + return (false); +} + +bool WncController::openSocket(uint16_t numSock, uint16_t port, bool tcp, uint16_t timeOutSec) +{ + if (numSock < MAX_NUM_WNC_SOCKETS) { + // IPV4 ip addr sanity check! + size_t lenIpStr = m_sSock[numSock].myIpAddressStr.size(); + if (lenIpStr < 7 || lenIpStr > 15) { + dbgPuts("Invalid IP Address!"); + return (false); + } + + // Already open ? Must close if want to re-open with new settings. + if (m_sSock[numSock].open == true) { + dbgPuts("Socket already open, close then re-open!"); + if (true == at_sockclose_wnc(m_sSock[numSock].numWncSock)) + m_sSock[numSock].open = false; + else + return (false); + } + + m_sSock[numSock].myPort = port; + m_sSock[numSock].isTcp = tcp; + m_sSock[numSock].timeOutSec = timeOutSec; + + int16_t numWncSock = at_sockopen_wnc(m_sSock[numSock].myIpAddressStr.c_str(), port, numSock, tcp, timeOutSec); + m_sSock[numSock].numWncSock = numWncSock; + if (numWncSock > 0 && numWncSock <= (uint16_t)MAX_NUM_WNC_SOCKETS) + m_sSock[numSock].open = true; + else { + m_sSock[numSock].open = false; + dbgPuts("Socket open fail!!!!"); + + // If the modem is not responding don't bother it. + if (WNC_NO_RESPONSE != getWncStatus()) { + // Work-around. If the sock open fails it needs to be told + // to close. If 6 sock opens happen with a fail, it further + // crashes the WNC. Not sure why the sock won't open. + at_sockclose_wnc(m_sSock[numSock].numWncSock); + } + } + } + else { + dbgPuts("Bad socket num or IP!"); + return (false); + } + + return (m_sSock[numSock].open); +} + +bool WncController::sockWrite(const uint8_t * const s, uint16_t n, uint16_t numSock, bool isTcp) +{ + bool result = true; + + AtCmdErr_e cmdRes = at_sockwrite_wnc(s, n, m_sSock[numSock].numWncSock, isTcp); + if (cmdRes != WNC_AT_CMD_OK) { + if ((cmdRes == WNC_AT_CMD_ERREXT) || (cmdRes == WNC_AT_CMD_ERRCME)) + { + // This may throw away any data that hasn't been written out of the WNC + // but at this point with the way the WNC currently works we have + // no choice. + closeOpenSocket(numSock); + } + result = false; + } + + return (result); +} + +bool WncController::write(uint16_t numSock, const uint8_t * s, uint32_t n) +{ + bool result; + + if (numSock < MAX_NUM_WNC_SOCKETS) { + if (m_sSock[numSock].open == true) { + if (n <= MAX_WNC_WRITE_BYTES) { + result = sockWrite(s, n, numSock, m_sSock[numSock].isTcp); + } + else { + uint16_t rem = n % MAX_WNC_WRITE_BYTES; + while (n >= MAX_WNC_WRITE_BYTES) { + n -= MAX_WNC_WRITE_BYTES; + result = sockWrite(s, MAX_WNC_WRITE_BYTES, numSock, m_sSock[numSock].isTcp); + if (result == false) { + n = 0; + rem = 0; + dbgPuts("Sock write fail!"); + } + else + s += MAX_WNC_WRITE_BYTES; + } + if (rem > 0) + result = sockWrite(s, rem, numSock, m_sSock[numSock].isTcp); + } + } + else { + dbgPuts("Socket is closed for write!"); + result = false; + } + } + else { + dbgPuts("Bad socket num!"); + result = false; + } + + return (result); +} + +size_t WncController::read(uint16_t numSock, const uint8_t ** readBuf) +{ + static string theBuf; + string readStr; + + theBuf.erase(); // Clean-up from last time + + if (numSock < MAX_NUM_WNC_SOCKETS) { + if (m_sSock[numSock].open == true) { + uint8_t i = m_sSock[numSock].readRetries; + uint16_t to = m_sSock[numSock].readRetryWaitMs; + bool foundData = false; + do { + AtCmdErr_e cmdRes; + cmdRes = at_sockread_wnc(&readStr, m_sSock[numSock].numWncSock, m_sSock[numSock].isTcp); + if (WNC_AT_CMD_OK == cmdRes) { + // This will let this loop read until the socket data is + // empty. If no data, then wait the retry amount of time. + if (readStr.size() > 0) { + theBuf += readStr; + foundData = true; + i = 1; + } + else { + // Once data is found start returning it asap + if (foundData == false) + waitMs(to); + } + } + else { + theBuf += readStr; // Append what if any we got before it errored. + dbgPuts("Sockread failed!"); + if (WNC_NO_RESPONSE == getWncStatus()) { + i = 0; + } + else if ((cmdRes == WNC_AT_CMD_ERREXT) || (cmdRes == WNC_AT_CMD_ERRCME)) + { + // This may throw away any data that hasn't been read out of the WNC + // but at this point with the way the WNC currently works we have + // no choice. + closeOpenSocket(numSock); + i = 0; + } + else + waitMs(to); + } + } while (i-- > 0); + } + else { + dbgPuts("Socket is closed for read"); + } + } + else { + dbgPuts("Bad socket num!"); + } + + *readBuf = (const uint8_t *)theBuf.c_str(); + + return (theBuf.size()); +} + +size_t WncController::read(uint16_t numSock, uint8_t * readBuf, uint32_t maxReadBufLen) +{ + uint32_t numCopied = 0; + + if (numSock < MAX_NUM_WNC_SOCKETS) { + if (m_sSock[numSock].open == true) { + uint8_t i = m_sSock[numSock].readRetries; + uint16_t to = m_sSock[numSock].readRetryWaitMs; + bool foundData = false; + uint16_t numRead; + do { + AtCmdErr_e cmdRes; + if (maxReadBufLen < MAX_WNC_READ_BYTES) + cmdRes = at_sockread_wnc(readBuf, &numRead, maxReadBufLen, m_sSock[numSock].numWncSock, m_sSock[numSock].isTcp); + else + cmdRes = at_sockread_wnc(readBuf, &numRead, MAX_WNC_READ_BYTES, m_sSock[numSock].numWncSock, m_sSock[numSock].isTcp); + + if (WNC_AT_CMD_OK == cmdRes) { + // This will let this loop read until the socket data is + // empty. If no data, then wait the retry amount of time. + if (numRead > 0) { + foundData = true; + i = 1; + if (numRead <= maxReadBufLen) { + maxReadBufLen -= numRead; + numCopied += numRead; + readBuf += numRead; + } + else { + i = 0; // No more room for data! + dbgPutsNoTime("No more room for read data!"); + } + } + else { + // Once data is found start returning it asap + if (foundData == false) + waitMs(to); + } + } + else { + dbgPuts("Sockread failed!"); + if (WNC_NO_RESPONSE == getWncStatus()) { + i = 0; + } + else if ((cmdRes == WNC_AT_CMD_ERREXT) || (cmdRes == WNC_AT_CMD_ERRCME)) + { + // This may throw away any data that hasn't been read out of the WNC + // but at this point with the way the WNC currently works we have + // no choice. + closeOpenSocket(numSock); + i = 0; + } + else + waitMs(to); + } + } while ((i-- > 0) && (maxReadBufLen > 0)); + } + else { + dbgPuts("Socket is closed for read"); + } + } + else { + dbgPuts("Bad socket num!"); + } + + return (numCopied); +} + +void WncController::setReadRetries(uint16_t numSock, uint16_t retries) +{ + if (numSock < MAX_NUM_WNC_SOCKETS) + m_sSock[numSock].readRetries = retries; + else + dbgPuts("Bad socket num!"); +} + +void WncController::setReadRetryWait(uint16_t numSock, uint16_t readRetryWaitMs) +{ + if (numSock < MAX_NUM_WNC_SOCKETS) + m_sSock[numSock].readRetryWaitMs = readRetryWaitMs; + else + dbgPuts("Bad socket num!"); +} + +bool WncController::closeSocket(uint16_t numSock) +{ + if (numSock < MAX_NUM_WNC_SOCKETS) { + + if (false == at_sockclose_wnc(m_sSock[numSock].numWncSock)) + dbgPuts("Sock close may not have closed!"); + + // Even with an error the socket could have closed, + // can't tell for sure so just soft close it for now. + m_sSock[numSock].open = false; + } + else { + dbgPuts("Bad socket num!"); + } + + return (m_sSock[numSock].open == false); +} + +size_t WncController::mdmGetline(string * buff, int timeout_ms) +{ + char chin = '\0'; + char chin_last; + size_t len = 0; + + startTimerB(); + while ((len <= MAX_LEN_WNC_CMD_RESPONSE) && (getTimerTicksB_mS() < timeout_ms)) { + if (charReady()) { + chin_last = chin; + chin = getc(); + if (isprint(chin)) { + *buff += chin; + len++; // Bound the copy length to something reaonable just in case + continue; + } + else if ((('\r' == chin_last) && ('\n' == chin)) || (('\n' == chin_last) && ('\r' == chin))) { + break; + } + } + } + stopTimerB(); + + if (len > MAX_LEN_WNC_CMD_RESPONSE) + dbgPuts("Max cmd length reply exceeded!"); + + return (len); +} + +bool WncController::softwareInitMdm(void) +{ + static bool reportStatus = true; + unsigned i; + + if (checkCellLink() == true) { + if (reportStatus == false) { + dbgPuts("Re-connected to cellular network!"); + reportStatus = true; + } + + // WNC has SIM and registered on network so + // soft initialize the WNC. + for (i = 0; i < WNC_SOFT_INIT_RETRY_COUNT; i++) + if (at_init_wnc() == true) + break; + + // If it did not respond try a hardware init + if (i == WNC_SOFT_INIT_RETRY_COUNT) + { + at_reinitialize_mdm(); + return (at_init_wnc(true)); // Hard reset occurred so make it go through the software init(); + } + else + return (true); + } + else + { + if (reportStatus == true) { + dbgPuts("Not connected to cellular network!"); + reportStatus = false; + } + return (false); + } +} + +WncController::AtCmdErr_e WncController::sendWncCmd(const char * const s, string ** r, int ms_timeout) +{ + if (checkCellLink() == false) { + static string noRespStr; + + // Save some run-time! + if (m_sDebugEnabled) + { + dbgPuts("FAIL send cmd: ", false); + if (m_sMoreDebugEnabled && m_sDebugEnabled) { + dbgPutsNoTime(s); + } + else { + size_t n = strlen(s); + if (n <= WNC_TRUNC_DEBUG_LENGTH) { + dbgPutsNoTime(s); + } + else { + string truncStr(s,WNC_TRUNC_DEBUG_LENGTH/2); + truncStr += ".."; + truncStr += &s[n-(WNC_TRUNC_DEBUG_LENGTH/2)]; + dbgPutsNoTime(truncStr.c_str()); + } + } + } + + noRespStr.erase(); + *r = &noRespStr; + + return (WNC_AT_CMD_NO_CELL_LINK); + } + + if (m_sCheckNetStatus) + { + if (m_sMoreDebugEnabled) + dbgPuts("[---------- Network Status -------------"); + string * pRespStr; + at_send_wnc_cmd("AT@SOCKDIAL?", &pRespStr, m_sCmdTimeoutMs); + if (m_sMoreDebugEnabled) + dbgPuts("---------------------------------------]"); + } + + // If WNC ready, send user command + return (at_send_wnc_cmd(s, r, ms_timeout)); +} + +WncController::AtCmdErr_e WncController::at_send_wnc_cmd(const char * s, string ** r, int ms_timeout) +{ + // Save some run-time! + if (m_sDebugEnabled) + { + if (m_sMoreDebugEnabled) { + dbgPuts("TX: ", false); dbgPutsNoTime(s); + } + else { + if (m_sDebugEnabled) { // Save some run-time! + size_t n = strlen(s); + if (n <= WNC_TRUNC_DEBUG_LENGTH) { + dbgPuts("TX: ", false); dbgPutsNoTime(s); + } + else { + string truncStr(s,WNC_TRUNC_DEBUG_LENGTH/2); + truncStr += ".."; + truncStr += &s[n - (WNC_TRUNC_DEBUG_LENGTH/2)]; + dbgPuts("TX: ", false); dbgPutsNoTime(truncStr.c_str()); + } + } + } + } + + AtCmdErr_e atResult = mdmSendAtCmdRsp(s, ms_timeout, &m_sWncStr); + *r = &m_sWncStr; // Return a pointer to the static string + + if (atResult != WNC_AT_CMD_TIMEOUT) { + // If a prior command timed out but a new one works then + // change the state back to ON. We don't know here in this + // method if the Cell Link is good so assume it is. When a command + // that depends on the cell link is made it will update the state. + if (m_sState == WNC_NO_RESPONSE) + m_sState = WNC_ON; + + // Save some run-time! + if (m_sDebugEnabled) + { + dbgPuts("RX: ", false); + if (m_sMoreDebugEnabled) { + dbgPutsNoTime(m_sWncStr.c_str()); + } + else { + if (m_sWncStr.size() <= WNC_TRUNC_DEBUG_LENGTH) { + dbgPutsNoTime(m_sWncStr.c_str()); + } + else { + string truncStr = m_sWncStr.substr(0,WNC_TRUNC_DEBUG_LENGTH/2) + ".."; + truncStr += m_sWncStr.substr(m_sWncStr.size() - (WNC_TRUNC_DEBUG_LENGTH/2), WNC_TRUNC_DEBUG_LENGTH/2); + dbgPutsNoTime(truncStr.c_str()); + } + } + } + } + else { + m_sState = WNC_NO_RESPONSE; + dbgPuts("AT Cmd TIMEOUT!"); + dbgPuts("RX: ", false); dbgPutsNoTime(m_sWncStr.c_str()); + } + + return (atResult); +} + +void WncController::closeOpenSocket(uint16_t numSock) +{ + // Try to open and close the socket + do { + dbgPuts("Try to close and re-open socket"); + if (false == at_sockclose_wnc(m_sSock[numSock].numWncSock)) { + if (WNC_NO_RESPONSE == getWncStatus()) { + dbgPuts("No response for closeOpenSocket1"); + return ; + } + } + + int numWncSock = at_sockopen_wnc(m_sSock[numSock].myIpAddressStr.c_str(), m_sSock[numSock].myPort, numSock, m_sSock[numSock].isTcp, m_sSock[numSock].timeOutSec); + m_sSock[numSock].numWncSock = numWncSock; + if (numWncSock > 0 && numWncSock <= (int)MAX_NUM_WNC_SOCKETS) + m_sSock[numSock].open = true; + else { + m_sSock[numSock].open = false; + dbgPuts("Failed to re-open socket!"); + } + + if (WNC_NO_RESPONSE == getWncStatus()) { + dbgPuts("No response for closeOpenSocket2"); + return ; + } + } while (m_sSock[numSock].open == false); +} + +bool WncController::getICCID(string * iccid) +{ + if (at_geticcid_wnc(iccid) == false) { + dbgPuts("getICCID error!"); + return (false); + } + + return (true); +} + +bool WncController::at_geticcid_wnc(string * iccid) +{ + string * respStr; + + iccid->erase(); + + AtCmdErr_e r = at_send_wnc_cmd("AT%CCID", &respStr, m_sCmdTimeoutMs); + + if (r != WNC_AT_CMD_OK || respStr->size() == 0) + return (false); + + // New Firmware versions respond to the %CCID command with "%CCID:" + // but old version respond with "AT%CCID", so check to see which we have + size_t pos = respStr->find(":"); + if (pos == string::npos) + pos = respStr->find("AT%CCID"); + else + pos = respStr->find("%CCID"); + + if (pos == string::npos) + return (false); + + pos += 7; // Advanced to the number + + size_t posOK = respStr->rfind("OK"); + if (posOK == string::npos) + return (false); + + *iccid = respStr->substr(pos, posOK - pos); + + return (true); +} + +bool WncController::convertICCIDtoMSISDN(const string & iccid, string * msisdn) +{ + msisdn->erase(); + + if (iccid.size() != 20 && iccid.size() != 19) { + dbgPuts("Invalid ICCID length!"); + return (false); + } + + *msisdn = "882350"; + + if (iccid.size() == 20) + *msisdn += iccid.substr(10,iccid.size() - 11); + else + *msisdn += iccid.substr(10,iccid.size() - 10); + + return (true); +} + +bool WncController::sendSMSText(const char * const phoneNum, const char * const text) +{ + if (at_sendSMStext_wnc(phoneNum, text) == true) + return (true); + else { + dbgPuts("sendSMSText: Failed!"); + return (false); + } +} + +bool WncController::readSMSLog(struct WncSmsList * log) +{ + string * logStr; + uint16_t i; + + if (at_readSMSlog_wnc(&logStr) == false) { + dbgPuts("readSMSLog: Failed!"); + return (false); + } + + // Clean slate + log->msgCount = 0; + + if (logStr->size() == 0) + return (false); + + // Pick out the stuff from the string and convert to struct + string s; + size_t pos2; + size_t pos = logStr->find("+CMGL:"); + + for(i=0; i<MAX_WNC_SMS_MSG_SLOTS; i++) { + // Start with a clean slate, let parsing fill out later. + log->e[i].unread = false; + log->e[i].incoming = false; + log->e[i].unsent = false; + log->e[i].pduMode = false; + log->e[i].msgReceipt = false; + + log->e[i].idx = logStr->at(pos + 7); + if (pos == string::npos) + return (false); + pos2 = logStr->find(",\"", pos); + if (pos2 == string::npos) { + // If the WNC acts wrong and receives a PDU mode + // SMS there will not be any quotes in the response, + // just take the whole reply and make it the message body for + // now, mark it as an unread message, set the pdu flag! + log->e[log->msgCount].unread = true; + log->e[log->msgCount].pduMode = true; + log->msgCount++; + + pos2 = logStr->find("+CMGL", pos + 5); + if (pos2 == string::npos) { + pos2 = logStr->find("OK", pos + 5); + if (pos2 == string::npos) { + dbgPuts("Strange SMS Log Ending!"); + return (false); + } + i = MAX_WNC_SMS_MSG_SLOTS; + } + log->e[log->msgCount].msg = logStr->substr(0, pos2 - pos); + pos = pos2; // for loop starts off expecting pos to point to next log msg + continue; + } + pos += 2; // Advance to the text we want + pos2 = logStr->find("\",", pos); + if ((pos2 == string::npos) || (pos >= pos2)) + return (false); + + // Setup attributes + s = logStr->substr(pos, pos2 - pos); + if (s.find("REC READ") != string::npos) + log->e[i].incoming = true; + if (s.find("REC UNREAD") != string::npos) { + log->e[i].unread = true; + log->e[i].incoming = true; + } + if (s.find("STO UNSENT") != string::npos) + log->e[i].unsent = true; + if (logStr->find(",,") == string::npos) + log->e[i].msgReceipt = true; + + // Tele number + pos2 = logStr->find(",\"", pos2); + if (pos2 == string::npos) + return (false); + pos2 += 2; // Advance to next field + pos = logStr->find("\",", pos2); + if ((pos == string::npos) || (pos2 > pos)) + return (false); + if (pos == pos2) + log->e[i].number.erase(); + else + log->e[i].number = logStr->substr(pos2, pos - pos2); + + // Date + pos = logStr->find(",\"", pos); + if (pos == string::npos) + return (false); + pos += 2; // Beginning of date field + pos2 = logStr->find(",", pos); // End of timestamp field + if ((pos2 == string::npos) || (pos > pos2)) + return (false); + if (pos == pos2) + log->e[i].date.erase(); + else + log->e[i].date = logStr->substr(pos, pos2 - pos); + + // Timestamp + pos = logStr->find("\",", pos2); // End of timestamp + if (pos == string::npos) + return (false); + pos2 += 1; // Beginning of time field + if (pos < pos2) + return (false); + if (pos == pos2) + log->e[i].time.erase(); + else + log->e[i].time = logStr->substr(pos2, pos - pos2); + + // Message field + + // We don't know how many messages we have so the next search + // could end with +CMGL or OK. + pos += 2; // Advanced to message text + pos2 = logStr->find("+CMGL", pos); + if (pos2 == string::npos) { + pos2 = logStr->find("OK", pos); + if (pos2 == string::npos) { + dbgPuts("Strange SMS Log Ending!"); + return (false); + } + i = MAX_WNC_SMS_MSG_SLOTS; // break + } + if (pos > pos2) + return (false); + if (pos == pos2) + log->e[log->msgCount].msg.erase(); + else + log->e[log->msgCount].msg = logStr->substr(pos, pos2 - pos); + + log->msgCount++; // Message complete + } + + return (true); +} + +bool WncController::readUnreadSMSText(struct WncSmsList * w, bool deleteRead) +{ + struct WncController::WncSmsList tmp; + + if (readSMSLog(&tmp) == false) + return (false); + + w->msgCount = 0; + for(uint16_t i = 0; i < tmp.msgCount; i++) { + if (tmp.e[i].unread == true) { + w->e[w->msgCount] = tmp.e[i]; + w->msgCount++; + if (deleteRead == true) { + // Clean up message that was copied out and read + deleteSMSTextFromMem(w->e[i].idx); + } + } + } + + return (w->msgCount > 0); +} + +size_t WncController::getSignalQuality(const char ** log) +{ + size_t n; + + n = at_getSignalQuality_wnc(log); + if (n == 0) + dbgPuts("readSMSText: Failed!"); + + return (n); +} + +size_t WncController::at_getSignalQuality_wnc(const char ** log) +{ + string * pRespStr; + static string logStr; + + logStr.erase(); + + if (at_send_wnc_cmd("AT%MEAS=\"0\"", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + logStr = *pRespStr; + logStr += "\r\n"; + } + else + dbgPuts("AT%MEAS=0: failed!"); + + if (at_send_wnc_cmd("AT%MEAS=\"1\"", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + logStr += *pRespStr; + logStr += "\r\n"; + } + else + dbgPuts("AT%MEAS=1: failed!"); + + if (at_send_wnc_cmd("AT%MEAS=\"2\"", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + logStr += *pRespStr; + logStr += "\r\n"; + } + else + dbgPuts("AT%MEAS=2: failed!"); + + if (at_send_wnc_cmd("AT%MEAS=\"3\"", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + logStr += *pRespStr; + logStr += "\r\n"; + } + else + dbgPuts("AT%MEAS=3: failed!"); + + if (at_send_wnc_cmd("AT%MEAS=\"4\"", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + logStr += *pRespStr; + logStr += "\r\n"; + } + else + dbgPuts("AT%MEAS=4: failed!"); + + if (at_send_wnc_cmd("AT%MEAS=\"5\"", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + logStr += *pRespStr; + logStr += "\r\n"; + } + else + dbgPuts("AT%MEAS=5: failed!"); + + if (at_send_wnc_cmd("AT%MEAS=\"8\"", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + logStr += *pRespStr; + logStr += "\r\n"; + } + else + dbgPuts("AT%MEAS=8: failed!"); + + if (at_send_wnc_cmd("AT%MEAS=\"98\"", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + logStr += *pRespStr; + logStr += "\r\n"; + } + else + dbgPuts("AT%MEAS=98: failed!"); + + *log = logStr.c_str(); + + return (logStr.size()); +} + +bool WncController::getTimeDate(struct WncDateTime * tod) +{ + if (at_gettimedate_wnc(tod) == true) + return (true); + else { + dbgPuts("Get time date failed!"); + return (false); + } +} + +bool WncController::at_ping_wnc(const char * ip) +{ + string * pRespStr; + string cmdStr = "AT@PINGREQ=\""; + cmdStr += ip; + cmdStr += "\""; + return (at_send_wnc_cmd(cmdStr.c_str(), &pRespStr, WNC_PING_CMD_TIMEOUT_MS) == WNC_AT_CMD_OK); +} + +bool WncController::at_gettimedate_wnc(struct WncDateTime * tod) +{ + string * pRespStr; + char * pEnd; + + if (at_send_wnc_cmd("AT+CCLK?", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) { + if (pRespStr->size() > 0) { + size_t pos1 = pRespStr->find("+CCLK:"); + if (pos1 != string::npos) { + pEnd = (char *)pRespStr->c_str() + pos1 + 8; + tod->year = strtol(pEnd, &pEnd, 10); + tod->month = strtol(pEnd+1, &pEnd, 10); + tod->day = strtol(pEnd+1, &pEnd, 10); + tod->hour = strtol(pEnd+1, &pEnd, 10); + tod->min = strtol(pEnd+1, &pEnd, 10); + tod->sec = strtol(pEnd+1, &pEnd, 10); + return (true); + } + } + } + + return (false); +} + +bool WncController::at_get_wnc_net_stats(WncIpStats * s) +{ + string * pRespStr; + AtCmdErr_e cmdRes = at_send_wnc_cmd("AT+CGCONTRDP=1", &pRespStr, m_sCmdTimeoutMs); + + if (WNC_AT_CMD_OK == cmdRes) { + if (pRespStr->size() > 0) { + memset((void*)s, '\0', sizeof(*s)); // Clean-up + string ss; + size_t pe; + size_t ps = pRespStr->rfind("\""); + if (ps != string::npos) { + ps += 2; // Skip the , after the " + pe = ps; + + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + + ss = pRespStr->substr(ps, pe - 1 - ps); + strncpy(s->ip, ss.c_str(), MAX_LEN_IP_STR); + s->ip[MAX_LEN_IP_STR - 1] = '\0'; + ps = pe; + + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(",", pe); + + ss = pRespStr->substr(ps, pe - ps); + strncpy(s->mask, ss.c_str(), MAX_LEN_IP_STR); + s->mask[MAX_LEN_IP_STR - 1] = '\0'; + ps = pe + 1; + + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(",", pe); + + ss = pRespStr->substr(ps, pe - ps); + strncpy(s->gateway, ss.c_str(), MAX_LEN_IP_STR); + s->gateway[MAX_LEN_IP_STR - 1] = '\0'; + ps = pe + 1; + + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(",", pe); + + + ss = pRespStr->substr(ps, pe - ps); + strncpy(s->dnsPrimary, ss.c_str(), MAX_LEN_IP_STR); + s->dnsPrimary[MAX_LEN_IP_STR - 1] = '\0'; + ps = pe + 1; + + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(".", pe); + if (pe == string::npos) + return (false); + else + pe += 1; + pe = pRespStr->find(",", pe); + + + ss = pRespStr->substr(ps, pe - ps); + strncpy(s->dnsSecondary, ss.c_str(), MAX_LEN_IP_STR); + s->dnsSecondary[MAX_LEN_IP_STR - 1] = '\0'; + + dbgPuts("~~~~~~~~~~ WNC IP Stats ~~~~~~~~~~~~"); + dbgPuts("ip: ", false); dbgPutsNoTime(s->ip); + dbgPuts("mask: ", false); dbgPutsNoTime(s->mask); + dbgPuts("gateway: ", false); dbgPutsNoTime(s->gateway); + dbgPuts("dns pri: ", false); dbgPutsNoTime(s->dnsPrimary); + dbgPuts("dns sec: ", false); dbgPutsNoTime(s->dnsSecondary); + dbgPuts("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + + return (true); + } + } + } + + return (false); +} + +bool WncController::deleteSMSTextFromMem(char msgIdx) +{ + const char * err = "deleteSMSTextFromMem: Failed!"; + + switch (msgIdx) + { + case '*': + at_deleteSMSTextFromMem_wnc('1'); + at_deleteSMSTextFromMem_wnc('2'); + at_deleteSMSTextFromMem_wnc('3'); + return (true); // WNC may error if slot empty, just ignore! + + case '1': + case '2': + case '3': + if (true == at_deleteSMSTextFromMem_wnc(msgIdx)) + return (true); + else { + dbgPuts(err); + return (false); + } + + default: + dbgPuts(err); + return (false); + } +} + +bool WncController::sendSMSTextFromMem(char msgIdx) +{ + const char * err = "deleteSMSTextFromMem: Failed!"; + + switch (msgIdx) + { + case '*': + at_sendSMStextMem_wnc('1'); + at_sendSMStextMem_wnc('2'); + at_sendSMStextMem_wnc('3'); + return (true); // WNC may error if slot is empty, just ignore! + + case '1': + case '2': + case '3': + if (at_sendSMStextMem_wnc(msgIdx) == true) + return (true); + else { + dbgPuts(err); + return (false); + } + + default: + dbgPuts(err); + return (false); + } +} + +bool WncController::at_deleteSMSTextFromMem_wnc(char n) +{ + string cmdStr, respStr; + // Message is stored in WNC, now send it! + cmdStr = "AT+CMGD="; + cmdStr += n; + cmdStr += "\r\n"; + dbgPuts("TX: ", false); dbgPutsNoTime(cmdStr.c_str(), false); + AtCmdErr_e r = mdmSendAtCmdRsp(cmdStr.c_str(), m_sCmdTimeoutMs, &respStr); + dbgPuts("RX: ", false); dbgPutsNoTime(respStr.c_str()); + return (r == WNC_AT_CMD_OK); +} + +bool WncController::at_sendSMStextMem_wnc(char n) +{ + string cmdStr, respStr; + // Message is stored in WNC, now send it! + cmdStr = "AT+CMSS="; + cmdStr += n; + cmdStr += "\r\n"; + dbgPuts("TX: ", false); dbgPutsNoTime(cmdStr.c_str(), false); + AtCmdErr_e r = mdmSendAtCmdRsp(cmdStr.c_str(), m_sCmdTimeoutMs, &respStr); + dbgPuts("RX: ", false); dbgPutsNoTime(respStr.c_str()); + return (r == WNC_AT_CMD_OK); +} + +bool WncController::at_sendSMStext_wnc(const char * const phoneNum, const char * const text) +{ + string respStr; + string * pRespStr; + size_t l = strlen(text); + + if (l <= MAX_WNC_SMS_LENGTH) + { + // Check to see if the SMS service is available + checkCellLink(); + if (m_sReadyForSMS == true) { + at_send_wnc_cmd("AT+CMGF=1", &pRespStr, m_sCmdTimeoutMs); + string cmdStr("AT+CMGS=\""); + cmdStr += phoneNum; + cmdStr += "\""; + dbgPuts("TX: ", false); dbgPutsNoTime(cmdStr.c_str()); + cmdStr += "\x0d"; // x0d = <ENTER> + // Send raw command with short timeout (the timeout will fail cause the WNC is not supposed to reply yet! + // And we want a delay before sending the actual text part of the string! + mdmSendAtCmdRsp(cmdStr.c_str(), 300, &respStr, false); // False turns off auto-addition of CR+LF (the WNC wants nothing here) + dbgPuts("RX: ", false); dbgPutsNoTime(respStr.c_str()); + if ((respStr.size() > 0) && (respStr.find("ERROR") == string::npos)) { + // Part 2 of the text, this is the actual text part: + cmdStr = text; + dbgPuts("TX: ", false); dbgPutsNoTime(cmdStr.c_str()); + cmdStr += "\x1A"; // <CTRL>-Z is what tells the WNC the message is complete to send! + AtCmdErr_e r = mdmSendAtCmdRsp(cmdStr.c_str(), 10000, &respStr); + dbgPuts("RX: ", false); dbgPutsNoTime(respStr.c_str()); + if (respStr.size() == 0) + return (false); + else + return (r == WNC_AT_CMD_OK); + } + } + } + + return (false); +} + +bool WncController::saveSMSText(const char * const phoneNum, const char * const text, char * msgIdx) +{ + if (at_saveSMStext_wnc(phoneNum, text, msgIdx) == true) + return (true); + else { + dbgPuts("saveSMSTextToMem: failed!\r\n"); + return (false); + } +} + +bool WncController::at_saveSMStext_wnc(const char * const phoneNum, const char * const text, char * msgIdx) +{ + string respStr; + size_t l = strlen(text); + + if (l <= MAX_WNC_SMS_LENGTH) + { + // Check to see if the SMS service is available + checkCellLink(); + if (m_sReadyForSMS == true) { + string cmdStr("AT+CMGW=\""); + cmdStr += phoneNum; + cmdStr += "\""; + dbgPuts("TX: ", false); dbgPutsNoTime(cmdStr.c_str()); + cmdStr += "\x0d"; // x0d = <ENTER> + // Send raw command with short timeout (the timeout will fail cause the WNC is not supposed to reply yet! + // And we want a delay before sending the actual text part of the string! + mdmSendAtCmdRsp(cmdStr.c_str(), 300, &respStr, false); // False turns off auto-addition of CR+LF (the WNC wants nothing here) + dbgPuts("RX: ", false); dbgPutsNoTime(respStr.c_str()); + if ((respStr.size() > 0) && (respStr.find("ERROR") == string::npos)) { + // Part 2 of the text, this is the actual text part: + cmdStr = text; + dbgPuts("TX: ", false); dbgPutsNoTime(cmdStr.c_str()); + cmdStr += "\x1A"; // <CTRL>-Z is what tells the WNC the message is complete to save! + mdmSendAtCmdRsp(cmdStr.c_str(), 10000, &respStr); + dbgPuts("RX: ", false); dbgPutsNoTime(respStr.c_str()); + if (respStr.size() > 0) { + // respStr will have the SMS index + size_t pos1 = respStr.find("+CMGW: "); + size_t pos2 = respStr.rfind("OK"); + if (pos1 != string::npos && pos2 != string::npos) { + *msgIdx = *string(respStr.substr(pos1+7, 1)).c_str(); + return (true); + } + else { + *msgIdx = '!'; + } + } + } + } + } + + return (false); +} + +bool WncController::at_readSMSlog_wnc(string ** log) +{ + return (at_send_wnc_cmd("AT+CMGL", log, m_sCmdTimeoutMs) == WNC_AT_CMD_OK); +} + +size_t WncController::at_readSMStext_wnc(const char n, const char ** log) +{ + static string smsReadTxtStr; + string * pRespStr; + string cmdStr; + + smsReadTxtStr.erase(); + cmdStr = "AT+CMGR"; + cmdStr += '1'; + if (at_send_wnc_cmd("AT+CMGR", &pRespStr, m_sCmdTimeoutMs) == WNC_AT_CMD_OK) + *log = pRespStr->c_str(); + else + *log = "\0"; + + return (pRespStr->size()); +} + +bool WncController::at_at_wnc(void) +{ + string * pRespStr; + return (WNC_AT_CMD_OK == at_send_wnc_cmd("AT", &pRespStr, WNC_QUICK_CMD_TIMEOUT_MS)); // Heartbeat? +} + +bool WncController::at_init_wnc(bool hardReset) +{ + string * pRespStr; + AtCmdErr_e cmdRes; + + if (hardReset == true) + dbgPuts("Hard Soft Reset!"); + + dbgPuts("Start AT init of WNC:"); + + // Kick it twice to perhaps remove cued responses from an incomplete + // power cycle. + at_send_wnc_cmd("AT", &pRespStr, WNC_QUICK_CMD_TIMEOUT_MS); + at_send_wnc_cmd("AT", &pRespStr, WNC_QUICK_CMD_TIMEOUT_MS); + + // Dump the firmware revision on the debug log: + at_send_wnc_cmd("AT+GMR", &pRespStr, m_sCmdTimeoutMs); + + m_FirmwareRevision = pRespStr->c_str(); + + // Quick commands below do not need to check cellular connectivity + at_send_wnc_cmd("ATE0", &pRespStr, WNC_QUICK_CMD_TIMEOUT_MS); // Echo Off + at_send_wnc_cmd("AT+CMEE=2", &pRespStr, m_sCmdTimeoutMs); // 2 - verbose error, 1 - numeric error, 0 - just ERROR + + // Setup 3 memory slots in the WNC SIM for SMS usage. + at_send_wnc_cmd("AT+CMGF=1", &pRespStr, m_sCmdTimeoutMs); + at_send_wnc_cmd("AT+CPMS=\"SM\",\"SM\",\"SM\"", &pRespStr, m_sCmdTimeoutMs); + + cmdRes = at_send_wnc_cmd("AT", &pRespStr, WNC_QUICK_CMD_TIMEOUT_MS); // Heartbeat? + + // If the simple commands are not working, no chance of more complex. + // I have seen re-trying commands make it worse. + if (cmdRes != WNC_AT_CMD_OK) + return (false); + + // Disable unsolicited RRCSTATE responses. These are supposed to be off + // by default but have been found to be active. + // This problem introduced in: NQ_MPSS_IMA3_v10.58.174043 LTE-M firmware + cmdRes = at_send_wnc_cmd("AT%NOTIFYEV=\"ALL\",0", &pRespStr, m_sCmdTimeoutMs); + if (cmdRes != WNC_AT_CMD_OK) + return (false); + + cmdRes = at_send_wnc_cmd("AT@INTERNET=1", &pRespStr, m_sCmdTimeoutMs); + if (cmdRes != WNC_AT_CMD_OK) + return (false); + + cmdRes = at_send_wnc_cmd("AT@SOCKDIAL=1", &pRespStr, m_sCmdTimeoutMs); + if (cmdRes != WNC_AT_CMD_OK) + return (false); + + dbgPuts("SUCCESS: AT init of WNC!"); + + return (true); +} + +int16_t WncController::at_sockopen_wnc(const char * const ip, uint16_t port, uint16_t numSock, bool tcp, uint16_t timeOutSec) +{ + string * pRespStr; + string cmd_str("AT@SOCKCREAT="); + AtCmdErr_e res; + + if (tcp) cmd_str += "1"; // TCP + else cmd_str += "2"; // else UDP + + cmd_str += ",0"; + res = sendWncCmd(cmd_str.c_str(), &pRespStr, m_sCmdTimeoutMs); + if (res == WNC_AT_CMD_OK && pRespStr->size() > 0) + { + size_t pos1 = pRespStr->find("T:"); + size_t pos2 = pRespStr->rfind("OK"); + if ((pos1 != string::npos) && (pos2 != string::npos)) { + size_t numLen = pos2 - (pos1 + 2); + string sockStr = pRespStr->substr(pos1 + 2, numLen); + cmd_str = "AT@SOCKCONN="; + cmd_str += sockStr; + cmd_str += ",\""; + cmd_str += ip; + cmd_str += "\","; + cmd_str += _to_string(port); + cmd_str += ","; + if (timeOutSec < 30) + timeOutSec = 30; + else if (timeOutSec > 360) + timeOutSec = 360; + cmd_str += _to_string(timeOutSec); + res = sendWncCmd(cmd_str.c_str(), &pRespStr, 1000 * timeOutSec + 1000); + if (m_sMoreDebugEnabled) { + at_send_wnc_cmd("AT@SOCKCREAT?", &pRespStr, m_sCmdTimeoutMs); + at_send_wnc_cmd("AT@SOCKCONN?", &pRespStr, m_sCmdTimeoutMs); + } + return (strtol(sockStr.c_str(), NULL, 10)); + } + else { + dbgPuts("Invalid sockcreat response!"); + return (0); + } + } + else + return (0); +} + +bool WncController::at_sockclose_wnc(uint16_t numSock) +{ + string * pRespStr; + string cmd_str("AT@SOCKCLOSE="); + + cmd_str += _to_string(numSock); + + // Don't check the cell status to close the socket + AtCmdErr_e res = at_send_wnc_cmd(cmd_str.c_str(), &pRespStr, m_sCmdTimeoutMs); + + if ((res != WNC_AT_CMD_TIMEOUT) && (res != WNC_AT_CMD_OK)) { + for (unsigned i = 0; i < WNC_SOCK_CLOSE_RETRY_CNT; i++) { + res = at_send_wnc_cmd(cmd_str.c_str(), &pRespStr, m_sCmdTimeoutMs); + if ((res == WNC_AT_CMD_TIMEOUT) || (res == WNC_AT_CMD_OK)) + break; + } + } + + return (res == WNC_AT_CMD_OK); +} + +bool WncController::at_dnsresolve_wnc(const char * s, string * ipStr) +{ + string * pRespStr; + string str(s); + AtCmdErr_e r; + + ipStr->erase(); // Clear out string until resolved! + str = "AT@DNSRESVDON=\"" + str; + str += "\""; + r = sendWncCmd(str.c_str(), &pRespStr, WNC_DNS_RESOLVE_WAIT_MS); + if (r == WNC_AT_CMD_OK && pRespStr->size() > 0) { + size_t pos_start = pRespStr->find("ON:\""); + size_t pos_end = pRespStr->find("\"", (pos_start + 4)); + if ((pos_start != string::npos) && (pos_end != string::npos)) { + pos_start += 4; + pos_end -= 1; + + if (pos_end > pos_start) { + // Make a copy for use later (the source string is re-used) + *ipStr = pRespStr->substr(pos_start, pos_end - pos_start + 1); + return (true); + } + } + } + + *ipStr = INVALID_IP_STR; + + return (false); +} + +bool WncController::waitForPowerOnModemToRespond(uint8_t timeoutSecs) +{ + // Now, give the modem x seconds to start responding by + // sending simple 'AT' commands to modem once per second. + if (timeoutSecs > 0) { + do { + timeoutSecs--; + dbgPutsNoTime("\rWaiting ", false); dbgPutsNoTime(_to_string(timeoutSecs), false); + dbgPutsNoTime(" ", false); + AtCmdErr_e rc = mdmSendAtCmdRsp("AT", 500, &m_sWncStr); + if (rc == WNC_AT_CMD_OK) { + dbgPutsNoTime(""); // CR LF + return true; //timer.read(); + } + waitMs(500); + } + while (timeoutSecs > 0); + dbgPutsNoTime(""); // CR LF + } + + return (false); +} + +WncController::AtCmdErr_e WncController::at_sockwrite_wnc(const uint8_t * s, uint16_t n, uint16_t numSock, bool isTcp) +{ + AtCmdErr_e result; + + if ((n > 0) && (n <= MAX_WNC_WRITE_BYTES)) { + string * pRespStr; + const char * num2str; + string cmd_str; + + if (isTcp == true) + cmd_str="AT@SOCKWRITE="; + else + cmd_str="AT@SOCKWRITE="; // "AT@SOCKSEND="; + + cmd_str += _to_string(numSock); + cmd_str += ","; + cmd_str += _to_string(n); + cmd_str += ",\""; + while(n > 0) { + n--; + num2str = _to_hex_string(*s++); + // Always 2-digit ascii hex: + if (num2str[1] == '\0') + cmd_str += '0'; + cmd_str += num2str; + } + cmd_str += "\""; + result = sendWncCmd(cmd_str.c_str(), &pRespStr, m_sCmdTimeoutMs); + } + else { + dbgPuts("sockwrite Err, string len bad!"); + result = WNC_AT_CMD_ERR; + } + + return (result); +} + +WncController::AtCmdErr_e WncController::at_sockread_wnc(string * pS, uint16_t numSock, bool isTcp) +{ + AtCmdErr_e result = WNC_AT_CMD_OK; + + string * pRespStr; + string cmd_str; + size_t pos_start=0, pos_end=0; + int i; + + pS->erase(); // Start with a fresh string + + if (isTcp == true) + cmd_str="AT@SOCKREAD="; + else + cmd_str="AT@SOCKREAD="; // "AT@SOCKRECV="; + + cmd_str += _to_string(numSock); + cmd_str += ","; + cmd_str += _to_string(MAX_WNC_READ_BYTES); + + // Experimental: read should not need to check cell net status + result = at_send_wnc_cmd(cmd_str.c_str(), &pRespStr, m_sCmdTimeoutMs); + if (result == WNC_AT_CMD_OK) { + if (pRespStr->size() > 0) { + pos_start = pRespStr->find("\""); + pos_end = pRespStr->rfind("\""); + // Make sure search finds what it's looking for! + if (pos_start != string::npos && pos_end != string::npos) { + pos_start++; + i = pos_end - pos_start; // Num hex chars, 2 per byte + } + else + i = 0; + } + else + i = 0; + + if ((i < 0) || ((i % 2) == 1)) + dbgPuts("Invalid READ string!"); + + if (i > 2*MAX_WNC_READ_BYTES) { + i = 2*MAX_WNC_READ_BYTES; + dbgPuts("DANGER WNC read data does not match length!"); + } + + // If data, convert the hex string into byte values + while (i > 0) { + i -= 2; + *pS += (uint8_t)strtol(pRespStr->substr(pos_start, 2).c_str(), NULL, 16); + pos_start += 2; + } + } + + return (result); +} + +WncController::AtCmdErr_e WncController::at_sockread_wnc(uint8_t * pS, uint16_t * numRead, uint16_t n, uint16_t numSock, bool isTcp) +{ + AtCmdErr_e result = WNC_AT_CMD_OK; + *numRead = 0; + + if ((n > 0) && (n <= MAX_WNC_READ_BYTES)) { + string * pRespStr; + string cmd_str; + size_t pos_start=0, pos_end=0; + int i; + + if (isTcp == true) + cmd_str="AT@SOCKREAD="; + else + cmd_str="AT@SOCKREAD="; // "AT@SOCKRECV="; + + cmd_str += _to_string(numSock); + cmd_str += ","; + cmd_str += _to_string(n); + + // Experimental: read should not need to check cell net status + result = at_send_wnc_cmd(cmd_str.c_str(), &pRespStr, m_sCmdTimeoutMs); + if (result == WNC_AT_CMD_OK) { + if (pRespStr->size() > 0) { + pos_start = pRespStr->find("\""); + pos_end = pRespStr->rfind("\""); + // Make sure search finds what it's looking for! + if (pos_start != string::npos && pos_end != string::npos) { + pos_start++; + i = pos_end - pos_start; // Num hex chars, 2 per byte + } + else + i = 0; + } + else + i = 0; + + if ((i < 0) || ((i % 2) == 1)) + dbgPuts("Invalid READ string!"); + + if (i > 2*n) { + // Bound the ill formated WNC read string! + i = 2*n; + dbgPuts("TRUNCATING read data!"); + } + + // If data, convert the hex string into byte values + i /= 2; + *numRead = i; + while (i > 0) { + i--; + *pS++ = (uint8_t)strtol(pRespStr->substr(pos_start, 2).c_str(), NULL, 16); + pos_start += 2; + } + } + } + else { + dbgPuts("sockread Err, to many to read!"); + result = WNC_AT_CMD_ERR; + } + + return (result); +} + +bool WncController::at_reinitialize_mdm(void) +{ + // Atempt to re-register +// string * pRespStr; +// dbgPuts("Force re-register!"); +// at_send_wnc_cmd("AT+CFUN=0,0", &pRespStr, m_sCmdTimeoutMs); +// waitMs(31000); +// at_send_wnc_cmd("AT+CFUN=1,0", &pRespStr, m_sCmdTimeoutMs); +// waitMs(31000); + + // Initialize the modem + dbgPuts("Modem RE-initializing with SOFT Reset..."); + + string * pRespStr; + at_send_wnc_cmd("AT@DMREBOOT", &pRespStr, m_sCmdTimeoutMs); + waitMs(5000); + + // Now, give the modem time to start responding by + // sending simple 'AT' commands to the modem once per second. + int timeoutSecs = WNC_REINIT_MAX_TIME_MS; + do { + dbgPuts("\rWaiting ", false); dbgPutsNoTime(_to_string(timeoutSecs), false); + AtCmdErr_e rc = mdmSendAtCmdRsp("AT", 500, &m_sWncStr); + if (rc == WNC_AT_CMD_OK) { + dbgPutsNoTime(""); // CR LF + break; + } + waitMs(500); + timeoutSecs--; + } + while (timeoutSecs > 0); + + if (timeoutSecs <= 0) + dbgPuts("\r\nModem RE-init FAILED!"); + else + dbgPuts("\r\nModem RE-init complete!"); + + return (timeoutSecs > 0); +} + +WncController::AtCmdErr_e WncController::mdmSendAtCmdRsp(const char *cmd, int timeout_ms, string * rsp, bool crLf) +{ + rsp->erase(); // Clean up from possible prior cmd response + + // Don't bother the WNC if user hasn't turned it on. + if (m_sState == WNC_OFF) + return (WNC_AT_CMD_WNC_NOT_ON); + + size_t n = strlen(cmd); + + // Wait per WNC advise + waitMs(WNC_WAIT_FOR_AT_CMD_MS); + + if (cmd && n > 0) { + sendCmd(cmd, crLf); +// sendCmd(cmd, n, 1000, crLf); // 3rd arg is micro seconds between chars sent + } + + startTimerA(); + while (getTimerTicksA_mS() < timeout_ms) { + n = mdmGetline(rsp, timeout_ms - getTimerTicksA_mS()); + + if (n == 0) + continue; + + if (rsp->rfind("OK") != string::npos) { + stopTimerA(); + return (WNC_AT_CMD_OK); + } + + if (rsp->rfind("+CME ERROR") != string::npos) { + stopTimerA(); + return (WNC_AT_CMD_ERRCME); + } + + if (rsp->rfind("@EXTERR") != string::npos) { + stopTimerA(); + return (WNC_AT_CMD_ERREXT); + } + + if (rsp->rfind("ERROR") != string::npos) { + stopTimerA(); + return (WNC_AT_CMD_ERR); + } + } + stopTimerA(); + + return (WNC_AT_CMD_TIMEOUT); +} + +bool WncController::at_setapn_wnc(const char * const apnStr) +{ + string * pRespStr; + + string cmd_str("AT%PDNSET=1,"); + cmd_str += apnStr; + cmd_str += ",IP"; + if (WNC_AT_CMD_OK == at_send_wnc_cmd(cmd_str.c_str(), &pRespStr, WNC_APNSET_TIMEOUT_MS)) // Set APN, cmd seems to take a little longer sometimes + return (true); + else + return (false); +} + +bool WncController::at_getrssiber_wnc(int16_t * dBm, int16_t * ber) +{ + string * pRespStr; + AtCmdErr_e cmdRes; + cmdRes = at_send_wnc_cmd("AT+CSQ", &pRespStr, m_sCmdTimeoutMs); // Check RSSI,BER + if (cmdRes != WNC_AT_CMD_OK) + return (false); + + if (pRespStr->size() == 0) { + dbgPuts("Strange RSSI result!"); + return (false); + } + else { + size_t pos1 = pRespStr->find("SQ:"); + size_t pos2 = pRespStr->rfind(","); + // Sanity check + if ((pos1 != string::npos) && (pos2 != string::npos) && (pos2 > pos1)) { + string subStr = pRespStr->substr(pos1 + 4, pos2 - pos1 ); + int rawRssi = atoi(subStr.c_str()); + + // Convert WNC RSSI into dBm range: + // 0 - -113 dBm + // 1 - -111 dBm + // 2..30 - -109 to -53 dBm + // 31 - -51dBm or > + // 99 - not known or not detectable + if (rawRssi == 99) + *dBm = -199; + else if (rawRssi == 0) + *dBm = -113; + else if (rawRssi == 1) + *dBm = -111; + else if (rawRssi == 31) + *dBm = -51; + else if (rawRssi >= 2 && rawRssi <= 30) + *dBm = -113 + 2 * rawRssi; + else { + dbgPuts("Invalid RSSI!"); + return (false); + } + // Parse out BER: 0..7 as RXQUAL values in the table 3GPP TS 45.008 subclause 8.2.4 + // 99 - unknown or undetectable + subStr = pRespStr->substr(pos2 + 1, pRespStr->length() - (pos2 + 1)); + *ber = atoi(subStr.c_str()); + } + else { + dbgPuts("Strange RSSI result2!"); + return (false); + } + } + + return (true); +} + +bool WncController::checkCellLink(void) +{ + string * pRespStr; + size_t pos; + int regSts; + int cmdRes1, cmdRes2; + + if (m_sState == WNC_OFF) + return (false); + + m_sState = WNC_ON_NO_CELL_LINK; + + if (m_sMoreDebugEnabled) + dbgPuts("<-------- Begin Cell Status ------------"); + + cmdRes1 = at_send_wnc_cmd("AT+CSQ", &pRespStr, m_sCmdTimeoutMs); // Check RSSI,BER + + // If no response, don't bother with more commands + if (cmdRes1 != WNC_AT_CMD_TIMEOUT) + cmdRes2 = at_send_wnc_cmd("AT+CPIN?", &pRespStr, m_sCmdTimeoutMs); // Check if SIM locked + else { + if (m_sMoreDebugEnabled) + dbgPuts("------------ WNC No Response! --------->"); + + return (false); + } + + if ((cmdRes1 != WNC_AT_CMD_OK) || (cmdRes2 != WNC_AT_CMD_OK) || (pRespStr->size() == 0)) + { + if (m_sMoreDebugEnabled) + { + if ((cmdRes1 == WNC_AT_CMD_TIMEOUT) || (cmdRes2 == WNC_AT_CMD_TIMEOUT)) + dbgPuts("------------ WNC No Response! --------->"); + else + dbgPuts("------------ WNC Cmd Error! ----------->"); + } + + // If by a miracle it responds to the 2nd after the 1st, keep going + if ((cmdRes2 == WNC_AT_CMD_TIMEOUT) || (pRespStr->size() == 0)) + return (false); + } + + // If SIM Card not ready don't bother with commands! + if (pRespStr->find("CPIN: READY") == string::npos) + { + if (m_sMoreDebugEnabled) + dbgPuts("------------ WNC SIM Problem! --------->"); + + return (false); + } + + // SIM card OK, now check for signal and cellular network registration + cmdRes1 = at_send_wnc_cmd("AT+CREG?", &pRespStr, m_sCmdTimeoutMs); // Check if registered on network + if (cmdRes1 != WNC_AT_CMD_OK || pRespStr->size() == 0) + { + if (m_sMoreDebugEnabled) + dbgPuts("------------ WNC +CREG? Fail! --------->"); + + return (false); + } + else + { + pos = pRespStr->find("CREG: "); + if (pos != string::npos) + { + // The registration is the 2nd arg in the comma separated list + *pRespStr = pRespStr->substr(pos+8, 1); + regSts = atoi(pRespStr->c_str()); + switch (regSts) { + case 1: + case 5: + case 6: + case 7: + m_sReadyForSMS = true; + break; + default: + m_sReadyForSMS = false; + dbgPuts("SMS Service Down!"); + } + + // 1 - registered home, 5 - registered roaming + if ((regSts != 1) && (regSts != 5)) + { + if (m_sMoreDebugEnabled) + dbgPuts("------ WNC Cell Link Down for Data! --->"); + + return (false); + } + } + + if (m_sMoreDebugEnabled) + dbgPuts("------------ WNC Ready ---------------->"); + } + + // If we made it this far and the WNC did respond, keep the ON state + if (m_sState != WNC_NO_RESPONSE) + m_sState = WNC_ON; + + return (true); +} + +int WncController::dbgPutsNoTime(const char * s, bool crlf) +{ + if (m_sDebugEnabled == true) { + int r = dbgWriteChars(s); + if (crlf == true) + return (dbgWriteChars("\r\n")); + else + return (r); + } + else + return 0; +}; + +int WncController::dbgPuts(const char * s, bool crlf) +{ + dbgPutsNoTime("[*] ", false); + dbgPutsNoTime(_to_string(getLogTimerTicks()), false); + dbgPutsNoTime(" ", false); + + int r = dbgPutsNoTime(s, false); + + if (crlf == true) + return (dbgPutsNoTime("", true)); + else + return (r); +}; + +void WncController::sendCmd(const char * cmd, bool crLf) +{ + puts(cmd); + if (crLf == true) + puts("\r\n"); +} + +void WncController::sendCmd(const char * cmd, unsigned n, unsigned wait_uS, bool crLf) +{ + while (n--) { + putc(*cmd++); + waitUs(wait_uS); + }; + if (crLf == true) { + putc('\r'); + waitUs(wait_uS); + putc('\n'); + waitUs(wait_uS); + } +} + +}; // End namespace WncController_fk +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/WNC14A2AInterface/WncControllerK64F/WncController/WncController.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,635 @@ +/** + Copyright (c) 2016 Fred Kellerman + + 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 WncController.h + @purpose Controls WNC Cellular Modem + @version 1.0 + @date July 2016 + @author Fred Kellerman + + Notes: This code originates from the following mbed repository: + + https://developer.mbed.org/teams/Avnet/code/WncControllerLibrary/ +*/ + + +#ifndef __WNCCONTROLLER_H_ +#define __WNCCONTROLLER_H_ + +#include <string> +#include <stdint.h> + +namespace WncController_fk { + +using namespace std; + +/** @defgroup API The WncControllerLibrary API */ +/** @defgroup MISC Misc WncControllerLibrary functions */ +/** @defgroup INTERNALS WncControllerLibrary Internals */ + +static const uint8_t MAX_LEN_IP_STR = 16; // Length includes room for the extra NULL + +/** \brief Contains info fields for the WNC Internet Attributes */ +struct WncIpStats +{ + string wncMAC; + char ip[MAX_LEN_IP_STR]; + char mask[MAX_LEN_IP_STR]; + char gateway[MAX_LEN_IP_STR]; + char dnsPrimary[MAX_LEN_IP_STR]; + char dnsSecondary[MAX_LEN_IP_STR]; +}; + + +/** + * @author Fred Kellerman + * @see API + * + * <b>WncController</b> This mbed C++ class is for controlling the WNC + * Cellular modem via the serial AT command interface. This was + * developed with respect to version 1.3 of the WNC authored + * unpublished spec. This class is only designed to have 1 instantiation, + * it is also not multi-thread safe. There are no OS specific + * entities being used, there are pure virtual methods that an + * inheriting class must fulfill. That inheriting class will have + * OS and platform specific entities. See WncControllerK64F for an + * example for the NXP K64F Freedom board. + */ +class WncController +{ +public: + + static const unsigned MAX_NUM_WNC_SOCKETS = 5; // Max number of simultaneous sockets that the WNC supports + static const unsigned MAX_POWERUP_TIMEOUT = 60; // How long the powerUp method will try to turn on the WNC Shield + // (this is the default if the user does not over-ride on power-up + + /** Tracks mode of the WNC Shield hardware */ + enum WncState_e { + WNC_OFF = 0, + WNC_ON, // This is intended to mean all systems go, including cell link up but socket may not be open + WNC_ON_NO_CELL_LINK, + WNC_NO_RESPONSE + }; + + /** + * + * Constructor for WncController class, sets up internals. + * @ingroup API + * @return none. + */ + WncController(void); + virtual ~WncController()=0; + + /** + * + * Used internally but also make public for a user of the Class to + * interrogate state as well. + * @ingroup API + * @return the current state of the Wnc hardware. + */ + WncState_e getWncStatus(void); + + /** + * + * Allows a user to set the WNC modem to use the given Cellular APN + * @ingroup API + * @param apnStr - a null terminated c-string + * @return true if the APN set was succesful, else false + */ + bool setApnName(const char * const apnStr); + + /** + * + * Queries the WNC modem for the current RX RSSI in units of coded dBm + * @ingroup API + * @return 0 â -113 dBm or less + * 1 â -111 dBm + * 2...30 â -109 dBm to â53 dBm + * 31 â -51 dBm or greater + * 99 â not known or not detectable + */ + int16_t getDbmRssi(void); + + /** + * + * Queries the WNC modem for the current Bit Error Rate + * @ingroup API + * @return 0...7 â as RXQUAL values in the table in 3GPP TS 45.008 + * subclause 8.2.4 + * 99 â not known or not detectable + */ + int16_t get3gBer(void); + + /** + * + * Powers up the WNC modem + * @ingroup API + * @param apn - the apn c-string to set the WNC modem to use + * @param powerUpTimeoutSecs - the amount of time to wait for the WNC modem to turn on + * @return true if powerup was a success, else false. + */ + bool powerWncOn(const char * const apn, uint8_t powerUpTimeoutSecs = MAX_POWERUP_TIMEOUT); + + /** + * + * Returns the NAT Self, gateway, masks and dns IP + * @ingroup API + * @param s - a pointer to a struct that will contain the IP info. + * @return true if success, else false. + */ + bool getWncNetworkingStats(WncIpStats * s); + + /** + * + * Takes a text URL and converts it internally to an IP address for the + * socket number given. + * @ingroup API + * @param numSock - The number of the socket to lookup the IP address for. + * @param url - a c-string text URL + * @return true if success, else false. + */ + bool resolveUrl(uint16_t numSock, const char * url); + + /** + * + * If you know the IP address you can set the socket up to use it rather + * than using a text URL. + * @ingroup API + * @param numSock - The number of the socket to use the IP address for. + * @param ipStr - a c-string text IP addrese like: 192.168.0.1 + * @return true if success, else false. + */ + bool setIpAddr(uint16_t numSock, const char * ipStr); + + /** + * + * Opens a socket for the given number, port and IP protocol. Before + * using open, you must use either resolveUrl() or setIpAddr(). + * @ingroup API + * @param numSock - The number of the socket to open. + * @param port - the IP port to open + * @param tcp - set true for TCP, false for UDP + * @param timeoutSec - the amount of time in seconds to wait for the open to complete + * @return true if success, else false. + */ + bool openSocket(uint16_t numSock, uint16_t port, bool tcp, uint16_t timeOutSec = 30); + + /** + * + * Opens a socket for the given text URL, number, port and IP protocol. + * @ingroup API + * @param numSock - The number of the socket to open. + * @param url - a c-string text URL, the one to open a socket for. + * @param port - the IP port to open. + * @param tcp - set true for TCP, false for UDP. + * @param timeoutSec - the amount of time in seconds to wait for the open to complete. + * @return true if success, else false. + */ + bool openSocketUrl(uint16_t numSock, const char * url, uint16_t port, bool tcp, uint16_t timeOutSec = 30); + + /** + * + * Opens a socket for the given text IP address, number, port and IP protocol. + * @ingroup API + * @param numSock - The number of the socket to open. + * @param ipAddr - a c-string text IP address like: "192.168.0.1". + * @param port - the IP port to open. + * @param tcp - set true for TCP, false for UDP. + * @param timeoutSec - the amount of time in seconds to wait for the open to complete. + * @return true if success, else false. + */ + bool openSocketIpAddr(uint16_t numSock, const char * ipAddr, uint16_t port, bool tcp, uint16_t timeOutSec = 30); + + + /** + * + * Write data bytes to a Socket, the Socket must already be open. + * @ingroup API + * @param numSock - The number of the socket to open. + * @parma s - an array of bytes to write to the socket. + * @param n - the number of bytes to write. + * @return true if success, else false. + */ + bool write(uint16_t numSock, const uint8_t * s, uint32_t n); + + /** + * + * Poll to read available data bytes from an already open Socket. This method + * will retry reads to what setReadRetries() sets it to and the delay in between + * retries that is set with setReadRetryWait() + * @ingroup API + * @param numSock - The number of the socket to open. + * @parma readBuf - a pointer to where read will put the data. + * @param maxReadBufLen - The number of bytes readBuf has room for. + * @return the number of bytes actually read into readBuf. 0 is a valid value if no data is available. + */ + size_t read(uint16_t numSock, uint8_t * readBuf, uint32_t maxReadBufLen); + + /** + * + * Poll to read available data bytes from an already open Socket. This method + * will retry reads to what setReadRetries() sets it to and the delay in between + * retries that is set with setReadRetryWait() + * @ingroup API + * @param numSock - The number of the socket to open. + * @parma readBuf - a pointer to pointer that will be set to point to an internal byte buffer that contains any read data. + * @return the number of bytes actually read into the pointer that readBuf points to. 0 is a valid value if no data is available. + */ + size_t read(uint16_t numSock, const uint8_t ** readBuf); + + /** + * + * Set the number of retries that the read methods will use. If a read returns 0 data this setting will have the read + * re-read to see if new data is available. + * @ingroup API + * @param numSock - The number of the socket to open. + * @parma retries - the number of retries to perform. + * @return none. + */ + void setReadRetries(uint16_t numSock, uint16_t retries); + + /** + * + * Set the time between retires that the read methods will use. If a read returns 0 data this setting will have the read + * re-read and use this amount of delay in between the re-reads. + * @ingroup API + * @param numSock - The number of the socket to open. + * @parma waitMs - the amount of time in mS to wait between retries. + * @return none. + */ + void setReadRetryWait(uint16_t numSock, uint16_t waitMs); + + /** + * + * Closes an already open Socket. + * @ingroup API + * @param numSock - The number of the socket to open. + * @return true if success else false. + */ + bool closeSocket(uint16_t numSock); + + /** + * + * Sets the amount of time to wait between the raw AT commands that are sent to the WNC modem. + * Generally you don't want to use this but it is here just in case. + * @ingroup API + * @param toMs - num mS to wait between the AT cmds. + * @return none. + */ + void setWncCmdTimeout(uint16_t toMs); + + /** + * + * Gets the IP address of the given socket number. + * @ingroup API + * @param numSock - The number of the socket to open. + * @param myIpAddr - a c-string that contains the socket's IP address. + * @return true if success else false. + */ + bool getIpAddr(uint16_t numSock, char myIpAddr[MAX_LEN_IP_STR]); + + /** + * + * Enables debug output from this class. + * @ingroup API + * @param on - true enables debug output, false disables + * @param moreDebugOn - true enables verbose debug, false truncates debug output. + * @return none. + */ + void enableDebug(bool on, bool moreDebugOn); + + /** + * + * Reports the WNC Firmware Revision info. + * @ingroup API + * @param none. + * @return char * + */ + const char* getFirmRev(void); + + /////////////////////////////////////////// + // SMS messaging + /////////////////////////////////////////// + + static const uint16_t MAX_WNC_SMS_MSG_SLOTS = 3; // How many SMS messages the WNC can store and receive at a time. + static const uint16_t MAX_WNC_SMS_LENGTH = 160; // The maximum length of a 7-bit SMS message the WNC can send and receive. + + /** Struct for SMS messages */ + struct WncSmsInfo + { + // Content + char idx; + string number; + string date; + string time; + string msg; + + // Attributes + bool incoming; + bool unsent; + bool unread; + bool pduMode; + bool msgReceipt; + }; + + /** Struct to contain a list of SMS message structs */ + struct WncSmsList + { + uint8_t msgCount; + WncSmsInfo e[MAX_WNC_SMS_MSG_SLOTS]; + }; + + /** + * + * Sends an SMS text message to someone. + * @ingroup API + * @param phoneNum - c-string 15 digit MSISDN number or ATT Jasper number (standard phone number not supported because ATT IoT SMS does not support it). + * @param text - the c-string text to send to someone. + * @return true if success else false. + */ + bool sendSMSText(const char * const phoneNum, const char * const text); + + /** + * + * Incoming messages are stored in a log in the WNC modem, this will read that + * log. + * @ingroup API + * @param log - the log contents if reading it was successful. + * @return true if success else false. + */ + bool readSMSLog(struct WncSmsList * log); + + /** + * + * Incoming messages are stored in a log in the WNC modem, this will read out + * messages that are unread and also then mark them read. + * @ingroup API + * @param w - a list of SMS messages that unread messages will be put into. + * @param deleteRead - if a message is read and this is set true the message will be deleted from the WNC modem log. + * If it is false the message will remain in the internal log but be marked as read. + * @return true if success else false. + */ + bool readUnreadSMSText(struct WncSmsList * w, bool deleteRead = true); + + /** + * + * Saves a text message into internal SIM card memory of the WNC modem. + * There are only 3 slots available this is for unread, read and saved. + * @ingroup API + * @param phoneNum - c-string 15 digit MSISDN number or ATT Jasper number (standard phone number not supported because ATT IoT SMS does not support it). + * @param text - the c-string text to send to someone. + * @param msgIdx - the slot position to save the message: '1', '2', '3' + * @return true if success else false. + */ + bool saveSMSText(const char * const phoneNum, const char * const text, char * msgIdx); + + /** + * + * Sends a prior stored a text message from internal SIM card memory of the WNC modem. + * If no messages are stored the behaviour of this method is undefined. + * @ingroup API + * @param msgIdx - the slot position to save the message: '1', '2', '3' + * @return true if success else false. + */ + bool sendSMSTextFromMem(char msgIdx); + + /** + * + * Deletes a prior stored a text message from internal SIM card memory of the WNC modem. + * If no messages are stored the behaviour of this method is undefined. + * @ingroup API + * @param msgIdx - the slot position to save the message: '1', '2', '3' or '*' deletes them all. + * @return true if success else false. + */ + bool deleteSMSTextFromMem(char msgIdx); + + /** + * + * Retreives the SIM card ICCID number. + * @ingroup API + * @param iccid - a pointer to C++ string that contains the retrieved number. + * @return true if success else false. + */ + bool getICCID(string * iccid); + + /** + * + * Converts an ICCID number into a MSISDN number. The ATT SMS system for IoT only allows use of the 15-digit MSISDN number. + * @ingroup API + * @param iccid - the number to convert. + * @param msisdn - points to a C++ string that has the converted number. + * @return true if success else false. + */ + bool convertICCIDtoMSISDN(const string & iccid, string * msisdn); + + /////////////////////////////////////////// + // Neighborhood Cell Info + /////////////////////////////////////////// + + /** + * + * Fetches the signal quality log from the WNC modem. + * @ingroup API + * @param log - a pointer to an internal buffer who's contents contain the signal quality metrics. + * @return The number of chars in the log. + */ + size_t getSignalQuality(const char ** log); + + /** A struct for the WNC modem Date and Time */ + struct WncDateTime + { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + }; + + /** + * + * Fetches the cell tower's time and date. The time is accurate when read + * but significant delays exist between the time it is read and returned. + * @ingroup API + * @param tod - User supplies a pointer to a tod struct and this method fills it in. + * @return true if success else false. + */ + bool getTimeDate(struct WncDateTime * tod); + + /** + * + * ICMP Pings a URL, the results are only output to the debug log for now! + * @ingroup API + * @param url - a c-string whose URL is to be pinged. + * @return true if success else false. + */ + bool pingUrl(const char * url); + + /** + * + * ICMP Pings an IP, the results are only output to the debug log for now! + * @ingroup API + * @param ip - a c-string whose IP is to be pinged. + * @return true if success else false. + */ + bool pingIp(const char * ip); + + /** + * + * Allows a user to send a raw AT command to the WNC modem. + * @ingroup API + * @param cmd - the c-string cmd to send like: "AT" + * @param resp - a pointer to the c-string cmd's response. + * @param sizeRespBuf - how large the command response buffer is, sets the max response length. + * @param ms_timeout - how long to wait for the WNC to respond to your command. + * @return the number of characters in the response from the WNC modem. + */ + size_t sendCustomCmd(const char * cmd, char * resp, size_t sizeRespBuf, int ms_timeout); + +protected: + + // Debug output methods + int dbgPutsNoTime(const char * s, bool crlf = true); + int dbgPuts(const char * s, bool crlf = true); + const char * _to_string(int64_t value); + const char * _to_hex_string(uint8_t value); + + // Sends commands to WNC via + enum AtCmdErr_e { + WNC_AT_CMD_OK, + WNC_AT_CMD_ERR, + WNC_AT_CMD_ERREXT, + WNC_AT_CMD_ERRCME, + WNC_AT_CMD_INVALID_RESPONSE, + WNC_AT_CMD_TIMEOUT, + WNC_AT_CMD_NO_CELL_LINK, + WNC_AT_CMD_WNC_NOT_ON + }; + + bool waitForPowerOnModemToRespond(uint8_t powerUpTimeoutSecs); + AtCmdErr_e sendWncCmd(const char * const s, string ** r, int ms_timeout); + + // Users must define these functionalities in the inheriting class: + // General I/O and timing: + virtual int putc(char c) = 0; + virtual int puts(const char * s) = 0; + virtual char getc(void) = 0; + virtual int charReady(void) = 0; + virtual int dbgWriteChar(char b) = 0; + virtual int dbgWriteChars(const char *b) = 0; + virtual void waitMs(int t) = 0; + virtual void waitUs(int t) = 0; + virtual bool initWncModem(uint8_t powerUpTimeoutSecs) = 0; + + // Isolate OS timers + virtual int getLogTimerTicks(void) = 0; + virtual void startTimerA(void) = 0; + virtual void stopTimerA(void) = 0; + virtual int getTimerTicksA_mS(void) = 0; + virtual void startTimerB(void) = 0; + virtual void stopTimerB(void) = 0; + virtual int getTimerTicksB_mS(void) = 0; + +private: + + bool softwareInitMdm(void); + bool checkCellLink(void); + AtCmdErr_e mdmSendAtCmdRsp(const char * cmd, int timeout_ms, string * rsp, bool crLf = true); + size_t mdmGetline(string * buff, int timeout_ms); + bool at_at_wnc(void); + bool at_init_wnc(bool hardReset = false); + int16_t at_sockopen_wnc(const char * const ip, uint16_t port, uint16_t numSock, bool tcp, uint16_t timeOutSec); + bool at_sockclose_wnc(uint16_t numSock); + bool at_dnsresolve_wnc(const char * s, string * ipStr); + AtCmdErr_e at_sockwrite_wnc(const uint8_t * s, uint16_t n, uint16_t numSock, bool isTcp); + AtCmdErr_e at_sockread_wnc(uint8_t * pS, uint16_t * numRead, uint16_t n, uint16_t numSock, bool isTcp); + AtCmdErr_e at_sockread_wnc(string * pS, uint16_t numSock, bool isTcp); + bool at_reinitialize_mdm(void); + AtCmdErr_e at_send_wnc_cmd(const char * s, string ** r, int ms_timeout); + bool at_setapn_wnc(const char * const apnStr); + bool at_sendSMStext_wnc(const char * const phoneNum, const char * const text); + bool at_get_wnc_net_stats(WncIpStats * s); + bool at_readSMSlog_wnc(string ** log); + size_t at_readSMStext_wnc(const char ** log); + size_t at_readSMStext_wnc(const char n, const char ** log); + bool at_getrssiber_wnc(int16_t * dBm, int16_t * ber3g); + void closeOpenSocket(uint16_t numSock); + bool sockWrite(const uint8_t * const s, uint16_t n, uint16_t numSock, bool isTcp); + bool at_sendSMStextMem_wnc(char n); + bool at_deleteSMSTextFromMem_wnc(char n); + bool at_saveSMStext_wnc(const char * const phoneNum, const char * const text, char * msgIdx); + size_t at_getSignalQuality_wnc(const char ** log); + bool at_gettimedate_wnc(struct WncDateTime * tod); + bool at_ping_wnc(const char * ip); + bool at_geticcid_wnc(string * iccid); + + // Utility methods + void sendCmd(const char * cmd, bool crLf); + void sendCmd(const char * cmd, unsigned n, unsigned wait_uS, bool crLf); + inline void rx_char_wait(void) { + // waitUs(1000); + } + + // Important constants + static const uint16_t MAX_WNC_READ_BYTES = 1500; // This bounds the largest amount of data that the WNC read from a socket will return + static const uint16_t MAX_WNC_WRITE_BYTES = MAX_WNC_READ_BYTES; // This is the largest amount of data that the WNC can write per sockwrite. + static const uint16_t MAX_LEN_WNC_CMD_RESPONSE = (MAX_WNC_READ_BYTES * 2 + 100); // Max number of text characters in a WNC AT response *2 because bytes are converted into 2 hex-digits +100 for other AT@ chars. + static const uint16_t WNC_AUTO_POLL_MS = 250; // Sets default (may be overriden with method) poll interval (currently not used, future possible feature. + static const uint16_t WNC_CMD_TIMEOUT_MS = 40000; // Sets default (may be overriden) time that the software waits for an AT response from the WNC. + static const uint16_t WNC_QUICK_CMD_TIMEOUT_MS = 2000; // Used for simple commands that should immediately respond such as "AT", cmds that are quicker than WNC_CMD_TIMEOUT_MS. + static const uint16_t WNC_WAIT_FOR_AT_CMD_MS = 0; // Wait this much between multiple in a row AT commands to the WNC. + static const uint16_t WNC_SOFT_INIT_RETRY_COUNT = 10; // How many times the WNC will be tried to revive if it stops responding. + static const uint16_t WNC_DNS_RESOLVE_WAIT_MS = 60000; // How much time to wait for the WNC to respond to a DNS resolve/lookup. + static const uint16_t WNC_TRUNC_DEBUG_LENGTH = 80; // Always make this an even number, how many chars for the debug output before shortening the debug ouput, this is used when moreDebug = false. + static const uint16_t WNC_APNSET_TIMEOUT_MS = 60000; // How long to wait for the WNC to respond to setting the APN string. + static const uint16_t WNC_PING_CMD_TIMEOUT_MS = 60000; // Amount of time to wait for the WNC to respond to AT@PINGREQ (with cmd default params for timeout, does not change WNC cmd's timeout) + static const int WNC_REINIT_MAX_TIME_MS = 60000; // How long to wait for the WNC to reset after it was already up and running after power-up. + static const uint16_t WNC_SOCK_CLOSE_RETRY_CNT = 3; // How many times to try to close the socket if the WNC gives an error. + static const char * const INVALID_IP_STR; // Just a string set to an IP address when DNS resolve fails. + + struct WncSocketInfo_s { + int16_t numWncSock; + bool open; + string myIpAddressStr; + uint16_t myPort; + uint8_t readRetries; + uint16_t readRetryWaitMs; + bool isTcp; + uint16_t timeOutSec; + }; + + WncSocketInfo_s m_sSock[MAX_NUM_WNC_SOCKETS]; + WncState_e m_sState; + uint16_t m_sCmdTimeoutMs; + string m_sApnStr; + string m_sWncStr; + string m_FirmwareRevision; + uint8_t m_sPowerUpTimeoutSecs; + bool m_sDebugEnabled; + bool m_sMoreDebugEnabled; + bool m_sCheckNetStatus; + bool m_sReadyForSMS; +}; + +}; // End namespace WncController_fk + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/WNC14A2AInterface/WncControllerK64F/WncControllerK64F.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,206 @@ +/* + Copyright (c) 2016 Fred Kellerman + + 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 WncControllerK64F.cpp + @purpose Contains K64F and mbed specifics to control the WNC modem using the WncController base class. + @version 1.0 + @date July 2016 + @author Fred Kellerman +*/ + +#include "WncControllerK64F.h" + +using namespace WncControllerK64F_fk; + +WncControllerK64F::WncControllerK64F(struct WncGpioPinListK64F * pPins, WncIO * wnc_uart, WNCDebug * debug_uart) +{ + m_logTimer.start(); // Start the log timer now! + m_pDbgUart = debug_uart; + m_pWncUart = wnc_uart; + m_gpioPinList = *pPins; +} + +bool WncControllerK64F::enterWncTerminalMode(WncIO * pUart, bool echoOn) +{ + if (pUart == NULL) + return (false); // Need a uart! + + string * resp; + AtCmdErr_e r = sendWncCmd("AT", &resp, 500); + if (r == WNC_AT_CMD_TIMEOUT) + return (false); + + pUart->puts("\r\nEntering WNC Terminal Mode - press <CTRL>-Q to exit!\r\n"); + + while (1) { + if (pUart->readable()) { + char c = pUart->getc(); + if (c == '\x11') { + pUart->puts("\r\nExiting WNC Terminal Mode!\r\n"); + // Cleanup in case user doesn't finish command: + sendWncCmd("AT", &resp, 300); + // Above AT may fail but should get WNC back in sync + return (sendWncCmd("AT", &resp, 500) == WNC_AT_CMD_OK); + } + if (echoOn == true) { + pUart->putc(c); + } + m_pWncUart->putc(c); + } + if (m_pWncUart->readable()) + pUart->putc(m_pWncUart->getc()); + } +} + +int WncControllerK64F::putc(char c) +{ + return (m_pWncUart->putc(c)); +} + +int WncControllerK64F::puts(const char * s) +{ + return (m_pWncUart->puts(s)); +} + +char WncControllerK64F::getc(void) +{ + return (m_pWncUart->getc()); +} + +int WncControllerK64F::charReady(void) +{ + return (m_pWncUart->readable()); +} + +int WncControllerK64F::dbgWriteChar(char b) +{ + if (m_pDbgUart != NULL) + return (m_pDbgUart->putc(b)); + else + return (0); +} + +int WncControllerK64F::dbgWriteChars(const char * b) +{ + if (m_pDbgUart != NULL) + return (m_pDbgUart->puts(b)); + else + return (0); +} + +bool WncControllerK64F::initWncModem(uint8_t powerUpTimeoutSecs) +{ + // Hard reset the modem (doesn't go through + // the signal level translator) + *m_gpioPinList.mdm_reset = 0; + + // disable signal level translator (necessary + // for the modem to boot properly). All signals + // except mdm_reset go through the level translator + // and have internal pull-up/down in the module. While + // the level translator is disabled, these pins will + // be in the correct state. + *m_gpioPinList.shield_3v3_1v8_sig_trans_ena = 0; + + // While the level translator is disabled and ouptut pins + // are tristated, make sure the inputs are in the same state + // as the WNC Module pins so that when the level translator is + // enabled, there are no differences. + *m_gpioPinList.mdm_uart2_rx_boot_mode_sel = 1; // UART2_RX should be high + *m_gpioPinList.mdm_power_on = 0; // powr_on should be low + *m_gpioPinList.mdm_wakeup_in = 1; // wake-up should be high + *m_gpioPinList.mdm_uart1_cts = 0; // indicate that it is ok to send + + // Now, wait for the WNC Module to perform its initial boot correctly + waitMs(1000); + + // The WNC module initializes comms at 115200 8N1 so set it up + m_pWncUart->baud(115200); + + //Now, enable the level translator, the input pins should now be the + //same as how the M14A module is driving them with internal pull ups/downs. + //When enabled, there will be no changes in these 4 pins... + *m_gpioPinList.shield_3v3_1v8_sig_trans_ena = 1; + + bool res = waitForPowerOnModemToRespond(powerUpTimeoutSecs); + + // Toggle wakeup to prevent future dropped 'A' of "AT", this was + // suggested by ATT. + if (res == true) { + dbgPuts("\r\nToggling Wakeup..."); + waitMs(20); + *m_gpioPinList.mdm_wakeup_in = 0; + waitMs(2000); + *m_gpioPinList.mdm_wakeup_in = 1; + waitMs(20); + dbgPuts("Toggling complete."); + } + + return (res); +} + +void WncControllerK64F::waitMs(int t) +{ + wait_ms(t); +} + +void WncControllerK64F::waitUs(int t) +{ + wait_ms(t); +} + +int WncControllerK64F::getLogTimerTicks(void) +{ + return (m_logTimer.read_us()); +} + +void WncControllerK64F::startTimerA(void) +{ + m_timerA.start(); + m_timerA.reset(); +} + +void WncControllerK64F::stopTimerA(void) +{ + m_timerA.stop(); +} + +int WncControllerK64F::getTimerTicksA_mS(void) +{ + return (m_timerA.read_ms()); +} + +void WncControllerK64F::startTimerB(void) +{ + m_timerB.start(); + m_timerB.reset(); +} + +void WncControllerK64F::stopTimerB(void) +{ + m_timerB.stop(); +} + +int WncControllerK64F::getTimerTicksB_mS(void) +{ + return (m_timerB.read_ms()); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/WNC14A2AInterface/WncControllerK64F/WncControllerK64F.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,131 @@ +/* + Copyright (c) 2016 Fred Kellerman + + 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 WncControllerK64F.h + @purpose Contains K64F and mbed specifics to control the WNC modem using the WncController base class. + @version 1.0 + @date July 2016 + @author Fred Kellerman +*/ + +#ifndef __WNCCONTROLLERK64F_H_ +#define __WNCCONTROLLERK64F_H_ + +#include <string> +#include <stdint.h> +#include "mbed.h" +#include "WNCDebug.h" +#include "WNCIO.h" +#include "WncController.h" + +namespace WncControllerK64F_fk { + +using namespace WncController_fk; +using namespace std; + +/** List of K64F pins that are used to control and setup the ATT IoT Kit WNC Shield */ +struct WncGpioPinListK64F { + ///////////////////////////////////////////////////// + // NXP GPIO Pins that are used to initialize the WNC Shield + ///////////////////////////////////////////////////// + DigitalOut * mdm_uart2_rx_boot_mode_sel; // on powerup, 0 = boot mode, 1 = normal boot + DigitalOut * mdm_power_on; // 0 = turn modem on, 1 = turn modem off (should be held high for >5 seconds to cycle modem) + DigitalOut * mdm_wakeup_in; // 0 = let modem sleep, 1 = keep modem awake -- Note: pulled high on shield + DigitalOut * mdm_reset; // active high + DigitalOut * shield_3v3_1v8_sig_trans_ena; // 0 = disabled (all signals high impedence, 1 = translation active + DigitalOut * mdm_uart1_cts; +}; + + +/** + * @author Fred Kellerman + * @see API + * + * <b>WncControllerK64F</b> This mbed C++ class is for controlling the WNC + * Cellular modem from the NXP K64F Freedom board. It uses the control code + * from it's base class WncController to handle the WNC Modem AT cmds. This + * class fulfills various pure virtual methods of the base class. The point of + * this class is to have the platform specific code in it thus isolating the + * control code logic from any particular platform or OS. + */ +class WncControllerK64F : public WncController +{ +public: + + /** + * + * Sets up the resources to control the WNC modem shield. + * @ingroup API + * @param pPins - pointer to a list of K64F pins that are used to setup and control the ATT IoT Kit's WNC Shield. + * @param wnc_uart - a pointer to the serial uart that is used to communicate with the WNC modem. + * @param debug_uart - a pointer to a serial uart for the debug output to go out of, if NULL debug will not be output. + */ + WncControllerK64F(struct WncGpioPinListK64F * pPins, WncIO * wnc_uart, WNCDebug * debug_uart = NULL); + + /** + * + * Activates a mode where the user can send text to and from the K64F + * debug Serial port directly to the WNC. The mode is entered via this + * call. The mode is exited when the user types CTRL-Q. While in this + * mode all text to and from the WNC is consumed by the debug Serial port. + * No other methods in the class will receive any of the WNC output. + * @ingroup API + * @param pUart - a pointer to a uart to use to collect the user input and put the output from the WNC. + * @param echoOn - set to true to echo what is input back to the output of pUart. + */ + bool enterWncTerminalMode(WncIO *pUart, bool echoOn); + +private: + + // Disallow copy + WncControllerK64F operator=(WncControllerK64F lhs); + + // Users must define these functionalities: + virtual int putc(char c); + virtual int puts(const char * s); + virtual char getc(void); + virtual int charReady(void); + virtual int dbgWriteChar(char b); + virtual int dbgWriteChars(const char *b); + virtual bool initWncModem(uint8_t powerUpTimeoutSecs); + virtual void waitMs(int t); + virtual void waitUs(int t); + + virtual int getLogTimerTicks(void); + virtual void startTimerA(void); + virtual void stopTimerA(void); + virtual int getTimerTicksA_mS(void); + virtual void startTimerB(void); + virtual void stopTimerB(void); + virtual int getTimerTicksB_mS(void); + + WNCDebug * m_pDbgUart; + WncIO * m_pWncUart; + WncGpioPinListK64F m_gpioPinList; + Timer m_logTimer; + Timer m_timerA; + Timer m_timerB; +}; + +}; // End namespace WncController_fk + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect/wnc14a2a-driver/mbed_lib.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,13 @@ +{ + "name": "wnc14a2a-library", + "config": { + "wnc-debug": { + "help" : "enable or disable WNC debug messages.", + "value": "false" + }, + "wnc-debug_setting": { + "help" : "bit value 1 and/or 2 enable WncController debug output, bit value 4 enables mbed driver debug output.", + "value": "4" + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-http.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/teams/sandbox/code/mbed-http/#9a04ed79d67e
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#0fdfcf7350896a9c0b57c4a18237677abfe25f1a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_app.json Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,25 @@ +{ + "config": { + "network-interface":{ + "help": "options are ETHERNET, WIFI_ESP8266, WIFI_IDW0XX1, WIFI_ODIN, WIFI_RTW, WIFI_WIZFI310, WIFI_ISM43362, MESH_LOWPAN_ND, MESH_THREAD, CELLULAR_ONBOARD", + "value": "WIFI_IDW0XX1" + }, + "wifi-ssid": { + "value": "\"WiFi\"" + }, + "wifi-password": { + "value": "\"WiFiPassword\"" + } + }, + "target_overrides": { + "*": { + "platform.stdio-baud-rate": 115200, + "platform.stdio-convert-newlines": true, + "idw0xx1.expansion-board": "IDW01M1", + "drivers.uart-serial-txbuf-size": 512, + "drivers.uart-serial-rxbuf-size": 512 + } + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main-http-socket-reuse.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,90 @@ +#include "select-demo.h" + +#if DEMO == DEMO_HTTP_SOCKET_REUSE + +#include "mbed.h" +#include "easy-connect.h" +#include "http_request.h" + +Serial pc(USBTX, USBRX); + +void dump_response(HttpResponse* res) { + printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str()); + + printf("Headers:\n"); + for (size_t ix = 0; ix < res->get_headers_length(); ix++) { + printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str()); + } + printf("\nBody (%d bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str()); +} + +int main() { + pc.baud(115200); + // Connect to the network (see mbed_app.json for the connectivity method used) + NetworkInterface *network = easy_connect(true); + if (!network) { + printf("Cannot connect to the network, see serial output"); + return 1; + } + + // Create a TCP socket + printf("\n----- Setting up TCP connection -----\n"); + + TCPSocket* socket = new TCPSocket(); + nsapi_error_t open_result = socket->open(network); + if (open_result != 0) { + printf("Opening TCPSocket failed... %d\n", open_result); + return 1; + } + + nsapi_error_t connect_result = socket->connect("httpbin.org", 80); + if (connect_result != 0) { + printf("Connecting over TCPSocket failed... %d\n", connect_result); + return 1; + } + + printf("Connected over TCP to httpbin.org:80\n"); + + // Do a GET request to httpbin.org + { + HttpRequest* get_req = new HttpRequest(socket, HTTP_GET, "http://httpbin.org/status/418"); + + // By default the body is automatically parsed and stored in a string, this is memory heavy. + // To receive chunked response, pass in a callback as third parameter to 'send'. + HttpResponse* get_res = get_req->send(); + if (!get_res) { + printf("HttpRequest failed (error code %d)\n", get_req->get_error()); + return 1; + } + + printf("\n----- HTTP GET response -----\n"); + dump_response(get_res); + + delete get_req; + } + + // POST request to httpbin.org + { + HttpRequest* post_req = new HttpRequest(socket, HTTP_POST, "http://httpbin.org/post"); + post_req->set_header("Content-Type", "application/json"); + + const char body[] = "{\"hello\":\"world\"}"; + + HttpResponse* post_res = post_req->send(body, strlen(body)); + if (!post_res) { + printf("HttpRequest failed (error code %d)\n", post_req->get_error()); + return 1; + } + + printf("\n----- HTTP POST response -----\n"); + dump_response(post_res); + + delete post_req; + } + + delete socket; + + Thread::wait(osWaitForever); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main-http.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,70 @@ +#include "select-demo.h" + +#if DEMO == DEMO_HTTP + +#include "mbed.h" +#include "easy-connect.h" +#include "http_request.h" + +Serial pc(USBTX, USBRX); + +void dump_response(HttpResponse* res) { + printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str()); + + printf("Headers:\n"); + for (size_t ix = 0; ix < res->get_headers_length(); ix++) { + printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str()); + } + printf("\nBody (%d bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str()); +} + +int main() { + pc.baud(115200); + // Connect to the network (see mbed_app.json for the connectivity method used) + NetworkInterface *network = easy_connect(true); + if (!network) { + printf("Cannot connect to the network, see serial output"); + return 1; + } + + // Do a GET request to httpbin.org + { + // By default the body is automatically parsed and stored in a buffer, this is memory heavy. + // To receive chunked response, pass in a callback as last parameter to the constructor. + HttpRequest* get_req = new HttpRequest(network, HTTP_GET, "http://httpbin.org/status/418"); + + HttpResponse* get_res = get_req->send(); + if (!get_res) { + printf("HttpRequest failed (error code %d)\n", get_req->get_error()); + return 1; + } + + printf("\n----- HTTP GET response -----\n"); + dump_response(get_res); + + delete get_req; + } + + // POST request to httpbin.org + { + HttpRequest* post_req = new HttpRequest(network, HTTP_POST, "http://httpbin.org/post"); + post_req->set_header("Content-Type", "application/json"); + + const char body[] = "{\"hello\":\"world\"}"; + + HttpResponse* post_res = post_req->send(body, strlen(body)); + if (!post_res) { + printf("HttpRequest failed (error code %d)\n", post_req->get_error()); + return 1; + } + + printf("\n----- HTTP POST response -----\n"); + dump_response(post_res); + + delete post_req; + } + + Thread::wait(osWaitForever); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main-https-socket-reuse.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,117 @@ +#include "select-demo.h" + +/** + * This demo shows how to re-use sockets, so the TLS handshake only has to happen once + */ + +#if DEMO == DEMO_HTTPS_SOCKET_REUSE + +#include "mbed.h" +#include "easy-connect.h" +#include "https_request.h" + +Serial pc(USBTX, USBRX); + +/* List of trusted root CA certificates + * currently one: Let's Encrypt, the CA for httpbin.org + * + * To add more root certificates, just concatenate them. + */ +const char SSL_CA_PEM[] = "-----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-----\n"; + +void dump_response(HttpResponse* res) { + mbedtls_printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str()); + + mbedtls_printf("Headers:\n"); + for (size_t ix = 0; ix < res->get_headers_length(); ix++) { + mbedtls_printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str()); + } + mbedtls_printf("\nBody (%d bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str()); +} + +int main() { + pc.baud(115200); + + NetworkInterface* network = easy_connect(true); + if (!network) { + return 1; + } + + // Create a TLS socket (which holds a TCPSocket) + printf("\n----- Setting up TLS connection -----\n"); + + TLSSocket* socket = new TLSSocket(network, "httpbin.org", 443, SSL_CA_PEM); + socket->set_debug(true); + if (socket->connect() != 0) { + printf("TLS Connect failed %d\n", socket->error()); + return 1; + } + + // GET request to httpbin.org + { + HttpsRequest* get_req = new HttpsRequest(socket, HTTP_GET, "https://httpbin.org/status/418"); + get_req->set_debug(true); + + HttpResponse* get_res = get_req->send(); + if (!get_res) { + printf("HttpRequest failed (error code %d)\n", get_req->get_error()); + return 1; + } + printf("\n----- HTTPS GET response -----\n"); + dump_response(get_res); + + delete get_req; + } + + // POST request to httpbin.org + { + HttpsRequest* post_req = new HttpsRequest(socket, HTTP_POST, "https://httpbin.org/post"); + post_req->set_debug(true); + post_req->set_header("Content-Type", "application/json"); + + const char body[] = "{\"hello\":\"world\"}"; + + HttpResponse* post_res = post_req->send(body, strlen(body)); + if (!post_res) { + printf("HttpRequest failed (error code %d)\n", post_req->get_error()); + return 1; + } + + printf("\n----- HTTPS POST response -----\n"); + dump_response(post_res); + + delete post_req; + } + + delete socket; + + Thread::wait(osWaitForever); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main-https.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,126 @@ +#include "select-demo.h" + +#if DEMO == DEMO_HTTPS + +#include "mbed.h" +#include "easy-connect.h" +#include "https_request.h" + +Serial pc(USBTX, USBRX); + +/* List of trusted root CA certificates + * currently two: GlobalSign, the CA for developer.mbed.org and Let's Encrypt, the CA for httpbin.org + * + * To add more root certificates, just concatenate them. + */ +const char SSL_CA_PEM[] = "-----BEGIN CERTIFICATE-----\n" + "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\n" + "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\n" + "b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\n" + "MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\n" + "YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\n" + "aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\n" + "jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\n" + "xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\n" + "1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\n" + "snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\n" + "U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\n" + "9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\n" + "BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\n" + "AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\n" + "yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\n" + "38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\n" + "AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\n" + "DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\n" + "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\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-----\n"; + +void dump_response(HttpResponse* res) { + mbedtls_printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str()); + + mbedtls_printf("Headers:\n"); + for (size_t ix = 0; ix < res->get_headers_length(); ix++) { + mbedtls_printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str()); + } + mbedtls_printf("\nBody (%d bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str()); +} + +int main() { + pc.baud(115200); + + NetworkInterface* network = easy_connect(true); + if (!network) { + return 1; + } + + // GET request to developer.mbed.org + { + printf("\n----- HTTPS GET request -----\n"); + + HttpsRequest* get_req = new HttpsRequest(network, SSL_CA_PEM, HTTP_GET, "https://developer.mbed.org/media/uploads/mbed_official/hello.txt"); + get_req->set_debug(true); + + HttpResponse* get_res = get_req->send(); + if (!get_res) { + printf("HttpRequest failed (error code %d)\n", get_req->get_error()); + return 1; + } + printf("\n----- HTTPS GET response -----\n"); + dump_response(get_res); + + delete get_req; + } + + // POST request to httpbin.org + { + printf("\n----- HTTPS POST request -----\n"); + + HttpsRequest* post_req = new HttpsRequest(network, SSL_CA_PEM, HTTP_POST, "https://httpbin.org/post"); + post_req->set_debug(true); + post_req->set_header("Content-Type", "application/json"); + + const char body[] = "{\"hello\":\"world\"}"; + + HttpResponse* post_res = post_req->send(body, strlen(body)); + if (!post_res) { + printf("HttpRequest failed (error code %d)\n", post_req->get_error()); + return 1; + } + + printf("\n----- HTTPS POST response -----\n"); + dump_response(post_res); + + delete post_req; + } + + Thread::wait(osWaitForever); +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main-x.cpp Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,388 @@ + + +#include "select-demo.h" + +/* ===================================================================== + Copyright © 2016, Avnet (R) + Contributors: + * James M Flynn, www.em.avnet.com + + 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 main.cpp / WNC14A2AInterface_HTTP_exampel + @version 1.0 + @date Dec 2016 +======================================================================== */ + +#if DEMO == DEMO_HTTPx + +#include "easy-connect.h" +#include "http_request.h" +#include "https_request.h" + +#define STREAM_CNT 10 //when we test streaming, this is how many times to stream the string +#define STR_SIZE 150*(STREAM_CNT+1) //use a fixed size string buffer based on the streaming data count + +#define TOSTR(x) #x +#define INTSTR(x) TOSTR(x) + +// +// We do the same thing for both http and https, so create a macro to eaze the typing... +// + + +/* List of trusted root CA certificates + * currently one: Let's Encrypt, the CA for httpbin.org + * + * To add more root certificates, just concatenate them. + */ +const char SSL_CA_PEM[] = "-----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-----\n"; + +// +// This example is setup to use MBED OS (5.2). It sets up a thread to call the different tests +// so the default stack size can be varied. TLS is stack intensive and needs additional stack +// to work effeciently. +// + +// +// The two test functions do the same set of tests, the first one uses standard HTTP methods while +// the second test uses HTTPS. +// + +void https_test_thread(void); //Thread that runs the two tests +void test_http(NetworkInterface *net); //function makes standard HTTP calls +void test_https(NetworkInterface *net); //function makes standard HTTPS calls + +Thread http_test(osPriorityNormal, 4*1024, NULL); + +int main() { + + printf("Test HTTP and HTTPS interface\n"); + http_test.start(https_test_thread); + wait(5); + http_test.join(); + printf(" - - - - - - - ALL DONE - - - - - - - \n"); +} + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// this is the Thread that calls each of the two tests. +// +void https_test_thread(void) { + + NetworkInterface *network = easy_connect(true); + + printf(" software.\n"); + if (!network) { + printf("Unable to connect to network!\n"); + return; + } + printf("My IP Address is: %s \n\n", network->get_ip_address()); + + test_http(network); + test_https(network); + + network->disconnect(); +} + + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Utility function to print out responses +// +void dump_response(HttpResponse* res) +{ + printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str()); + + printf("Headers:\n"); + for (size_t ix = 0; ix < res->get_headers_length(); ix++) { + printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str()); + } + printf("\nBody (%d bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str()); +} + +void stream_callback(const char *data, size_t len) +{ + printf("Chunk Received:\n"); + for( size_t x=0; x<len; x++ ) + printf("%c",data[x]); + printf("\n"); +} + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// test the HTTP client class +// +void test_http(NetworkInterface *net) +{ + TCPSocket *socket = new TCPSocket(); + + printf(">>>>>>>>>>>><<<<<<<<<<<<\n"); + printf(">>> TEST HTTPClient <<<\n"); + printf(">>>>>>>>>>>><<<<<<<<<<<<\n\n"); + + nsapi_error_t open_result = socket->open(net); + if (open_result != 0) { + printf("Opening TCPSocket failed... %d\n", open_result); + return; + } + + nsapi_error_t connect_result = socket->connect("developer.mbed.org", 80); + if (connect_result != 0) { + printf("Connecting over TCPSocket failed... %d\n", connect_result); + return; + } + else + printf("Connected over TCP to developer.mbed.org\n\n"); + + printf(" >>>First, lets get a page from http://developer.mbed.org\n"); + { + HttpRequest* get_req = new HttpRequest(socket,HTTP_GET,"https://os.mbed.com/media/uploads/mbed_official/hello.txt"); + HttpResponse* get_res = get_req->send(); + if (!get_res) { + printf("HttpRequest failed (error code %d)\n", get_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_response(get_res); + delete get_req; + } + delete socket; + + socket = new TCPSocket(); + + open_result = socket->open(net); + if (open_result != 0) { + printf("Opening TCPSocket failed... %d\n", open_result); + return; + } + + connect_result = socket->connect("httpbin.org", 80); + if (connect_result != 0) { + printf("Connecting over TCPSocket http://httpbin.org... %d\n", connect_result); + return; + } + else + printf("Connected over TCP to httpbin.org\n\n"); + + printf("\n\n >>>Post data... **\n"); + { + HttpRequest* post_req = new HttpRequest(socket, HTTP_POST, "http://httpbin.org/post"); + post_req->set_header("Content-Type", "application/json"); + const char body[] = "{\"hello\":\"world\"}," + "{\"test\":\"1234\"}"; + + HttpResponse* post_res = post_req->send(body, strlen(body)); + if (!post_res) { + printf("HttpRequest failed (error code %d)\n", post_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_response(post_res); + delete post_req; + } + + printf("\n\n >>>Put data... \n"); + { + HttpRequest* put_req = new HttpRequest(socket, HTTP_PUT, "http://httpbin.org/put"); + put_req->set_header("Content-Type", "application/json"); + + const char body[] = "This is a PUT test!"; + + HttpResponse* put_res = put_req->send(body, strlen(body)); + if (!put_res) { + printf("HttpRequest failed (error code %d)\n", put_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_response(put_res); + delete put_req; + } + + printf("\n\n >>>Delete data... \n"); + { + HttpRequest* del_req = new HttpRequest(socket, HTTP_DELETE, "http://httpbin.org/delete"); + del_req->set_header("Content-Type", "application/json"); + + HttpResponse* del_res = del_req->send(); + if (!del_res) { + printf("HttpRequest failed (error code %d)\n", del_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_response(del_res); + delete del_req; + } + + printf("\n\n >>>HTTP:stream, send http://httpbin.org/stream/" INTSTR(STREAM_CNT) "... \n"); + { + HttpRequest* stream_req = new HttpRequest(socket, HTTP_GET, "http://httpbin.org/stream/" INTSTR(STREAM_CNT), + stream_callback ); + stream_req->send(); + delete stream_req; + } + + printf("\n\n >>>HTTP:Status...\n"); + { + HttpRequest* get_req = new HttpRequest(socket,HTTP_GET,"http://httpbin.org/get?show_env=1"); + HttpResponse* get_res = get_req->send(); + if (!get_res) { + printf("HttpRequest failed (error code %d)\n", get_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_response(get_res); + delete get_req; + } + delete socket; +} + + +void dump_httpsresponse(HttpResponse* res) +{ + mbedtls_printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str()); + + mbedtls_printf("Headers:\n"); + for (size_t ix = 0; ix < res->get_headers_length(); ix++) { + mbedtls_printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str()); + } + mbedtls_printf("\nBody (%d bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str()); +} + +void stream_httpscallback(const char *data, size_t len) +{ + printf("Chunk Received:\n"); + for( size_t x=0; x<len; x++ ) + printf("%c",data[x]); + printf("\n"); +} + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// test the HTTPS client class +// +void test_https(NetworkInterface *net) +{ + + printf(">>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<\n"); + printf(">>> TEST HTTPS - set up TLS connection <<<\n"); + printf(">>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<\n\n"); + + TLSSocket* socket = new TLSSocket(net, "httpbin.org", 443, SSL_CA_PEM); + socket->set_debug(true); + if (socket->connect() != 0) { + printf("TLS Connect failed %d\n", socket->error()); + return; + } + + printf("\n\n >>>Post data... **\n"); + { + HttpsRequest* post_req = new HttpsRequest(socket, HTTP_POST, "http://httpbin.org/post"); + post_req->set_header("Content-Type", "application/json"); + const char body[] = "{\"hello\":\"world\"}," + "{\"test\":\"1234\"}"; + + HttpResponse* post_res = post_req->send(body, strlen(body)); + if (!post_res) { + printf("HttpsRequest failed (error code %d)\n", post_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_httpsresponse(post_res); + delete post_req; + } + + printf("\n\n >>>Put data... \n"); + { + HttpsRequest* put_req = new HttpsRequest(socket, HTTP_PUT, "http://httpbin.org/put"); + put_req->set_header("Content-Type", "application/json"); + + const char body[] = "This is a PUT test!"; + + HttpResponse* put_res = put_req->send(body, strlen(body)); + if (!put_res) { + printf("HttpsRequest failed (error code %d)\n", put_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_httpsresponse(put_res); + delete put_req; + } + + printf("\n\n >>>Delete data... \n"); + { + HttpsRequest* del_req = new HttpsRequest(socket, HTTP_DELETE, "http://httpbin.org/delete"); + del_req->set_header("Content-Type", "application/json"); + + HttpResponse* del_res = del_req->send(); + if (!del_res) { + printf("HttpsRequest failed (error code %d)\n", del_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_httpsresponse(del_res); + delete del_req; + } + + printf("\n\n >>>HTTPS:stream, send http://httpbin.org/stream/" INTSTR(STREAM_CNT)"... \n"); + { + HttpsRequest* stream_req = new HttpsRequest(socket, HTTP_GET, "http://httpbin.org/stream/" INTSTR(STREAM_CNT), + stream_httpscallback ); + stream_req->send(); + delete stream_req; + } + + printf("\n\n >>>HTTPS:Status...\n"); + { + HttpsRequest* get_req = new HttpsRequest(socket,HTTP_GET,"http://httpbin.org/get?show_env=1"); + HttpResponse* get_res = get_req->send(); + if (!get_res) { + printf("HttpsRequest failed (error code %d)\n", get_req->get_error()); + return; + } + + printf("\n----- RESPONSE: -----\n"); + dump_httpsresponse(get_res); + delete get_req; + } + delete socket; +} + +#endif // DEMO
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/select-demo.h Wed Sep 05 14:28:24 2018 +0000 @@ -0,0 +1,12 @@ +#ifndef _SELECT_METHOD_H_ +#define _SELECT_METHOD_H_ + +#define DEMO_HTTP 1 +#define DEMO_HTTP_SOCKET_REUSE 2 +#define DEMO_HTTPS 3 +#define DEMO_HTTPS_SOCKET_REUSE 4 +#define DEMO_HTTPx 5 + +#define DEMO DEMO_HTTPx +#endif // _SELECT_METHOD_H_ +