├── doc ├── dw1000_user_manual_2.09.pdf └── README.md ├── .gitignore ├── .travis.yml ├── dw1000.gpr ├── ci ├── build.sh └── proof.sh ├── tests ├── dw1000_unit_tests.gpr ├── dw1000-system_time-suite.ads ├── test_dw1000.adb ├── dw1000-system_time-tests.ads └── dw1000-system_time-suite.adb ├── LICENSE ├── src ├── dw1000.ads ├── dw1000-generic_wo_register_driver.adb ├── dw1000-generic_rw_register_driver.adb ├── dw1000-generic_wo_register_driver.ads ├── dw1000-generic_ro_register_driver.ads ├── dw1000-system_time.adb ├── dw1000-generic_rw_register_driver.ads ├── dw1000-generic_ro_register_driver.adb ├── dw1000-constants.ads ├── dw1000-ranging.ads ├── dw1000-ranging-single_sided.ads ├── dw1000-types.ads ├── dw1000-ranging-double_sided.ads ├── dw1000-ranging-single_sided.adb ├── dw1000-register_driver.ads ├── dw1000-register_driver.adb ├── dw1000-bsp.ads ├── dw1000-ranging-double_sided.adb ├── dw1000-reception_quality.ads └── dw1000-reception_quality.adb ├── examples ├── transmit │ ├── transmit_example.gpr │ └── transmit_example.adb ├── echo │ ├── echo_example.gpr │ └── echo_example.adb └── receive │ ├── receive_example.gpr │ └── receive_example.adb ├── bsp-examples ├── evb1000 │ ├── decadriver_config.ads │ ├── stm32.ads │ ├── stm32-nvic.ads │ ├── stm32-exti.ads │ ├── dw1000-bsp.adb │ └── tx_power.ads └── dwm1001 │ ├── decadriver_config.ads │ ├── nrf52.ads │ ├── tx_power.ads │ └── nrf52-spi.ads └── README.md /doc/dw1000_user_manual_2.09.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/damaki/DW1000/HEAD/doc/dw1000_user_manual_2.09.pdf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /tests/obj 2 | /obj 3 | /examples/transmit/build 4 | /examples/receive/build 5 | /examples/echo/build 6 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | This directory contains some reference documentation for the DW1000 chip, 2 | such as the user manual provided by DecaWave. 3 | 4 | If you're looking for documentation for how to use this driver, then check 5 | out [the Wiki](https://github.com/damaki/DW1000/wiki). 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | services: 4 | - docker 5 | 6 | branches: 7 | only: 8 | master 9 | 10 | env: 11 | - SCRIPT=ci/build.sh CONTAINER=damaki/gnat-arm-elf:gpl.2019 12 | - SCRIPT=ci/proof.sh CONTAINER=damaki/gnat-arm-elf:gpl.2019.spark 13 | 14 | git: 15 | submodules: false 16 | 17 | script: 18 | - docker run -v $PWD:/app -w /app $CONTAINER /bin/sh -c "$SCRIPT" -------------------------------------------------------------------------------- /dw1000.gpr: -------------------------------------------------------------------------------- 1 | project Dw1000 is 2 | 3 | for Object_Dir use "obj"; 4 | for Source_Dirs use ("src", "bsp-examples/dwm1001"); 5 | for Target use "arm-eabi"; 6 | for Runtime ("ada") use "ravenscar-full-nrf52832"; 7 | 8 | package Prove is 9 | for Switches use ("--level=2"); 10 | end Prove; 11 | 12 | package Ide is 13 | for Documentation_Dir use "doc"; 14 | end Ide; 15 | 16 | package Compiler is 17 | for Default_Switches ("ada") use ("-gnatweaB"); 18 | end Compiler; 19 | 20 | end Dw1000; 21 | 22 | -------------------------------------------------------------------------------- /ci/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Dependencies 4 | apt update 5 | apt upgrade -y 6 | apt install -y --no-install-recommends python 7 | 8 | # Install the ravenscar_full_nrf52832 BSP from bb-runtimes 9 | git clone https://github.com/AdaCore/bb-runtimes.git 10 | cd bb-runtimes 11 | python ./build_rts.py --output=temp --bsps-only nrf52832 12 | gprbuild -P temp/BSPs/ravenscar_full_nrf52832.gpr -j0 -f 13 | gprinstall -P temp/BSPs/ravenscar_full_nrf52832.gpr -p -f 14 | cd .. 15 | 16 | # Build all .gpr files in the examples directory 17 | gprbuild -p -P examples/transmit/transmit_example.gpr -j0 -f -XBSP=DWM1001 18 | gprbuild -p -P examples/receive/receive_example.gpr -j0 -f -XBSP=DWM1001 19 | gprbuild -p -P examples/echo/echo_example.gpr -j0 -f -XBSP=DWM1001 -------------------------------------------------------------------------------- /ci/proof.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Dependencies 4 | apt update 5 | apt upgrade -y 6 | apt install -y --no-install-recommends python 7 | 8 | # Install the ravenscar_full_nrf52832 BSP from bb-runtimes 9 | git clone https://github.com/AdaCore/bb-runtimes.git 10 | cd bb-runtimes 11 | python ./build_rts.py --output=temp --bsps-only nrf52832 12 | gprbuild -P temp/BSPs/ravenscar_full_nrf52832.gpr -j0 -f 13 | gprinstall -P temp/BSPs/ravenscar_full_nrf52832.gpr -p -f 14 | cd .. 15 | 16 | # Prove all .gpr files in the examples directory 17 | gnatprove -P examples/transmit/transmit_example.gpr --mode=all --level=2 -j0 --checks-as-errors -XBSP=DWM1001 18 | gnatprove -P examples/receive/receive_example.gpr --mode=all --level=2 -j0 --checks-as-errors -XBSP=DWM1001 19 | gnatprove -P examples/echo/echo_example.gpr --mode=all --level=2 -j0 --checks-as-errors -XBSP=DWM1001 -------------------------------------------------------------------------------- /tests/dw1000_unit_tests.gpr: -------------------------------------------------------------------------------- 1 | with "aunit"; 2 | 3 | project Dw1000_Unit_Tests is 4 | 5 | for Object_Dir use "obj"; 6 | for Exec_Dir use "obj"; 7 | for Source_Dirs use (".", "../src"); 8 | for Main use ("test_dw1000.adb"); 9 | 10 | package Compiler is 11 | for Default_Switches ("ada") use ("-gnata", "-g", "-ffunction-sections", "-fdata-sections", "-funroll-loops", "-gnatn"); 12 | for Switches ("dw1000-system_time-tests.adb") use ("-gnata", "-g", "-ffunction-sections", "-fdata-sections", "-funroll-loops", "-gnatn", "-O2"); 13 | for Switches ("dw1000-system_time.adb") use ("-gnata", "-g", "-ffunction-sections", "-fdata-sections", "-funroll-loops", "-gnatn", "-O2"); 14 | end Compiler; 15 | 16 | package Linker is 17 | for Default_Switches ("ada") use ("-g", "-Wl,--gc-sections"); 18 | end Linker; 19 | 20 | package Binder is 21 | for Default_Switches ("ada") use ("-E"); 22 | end Binder; 23 | 24 | package Builder is 25 | for Default_Switches ("ada") use ("-j4"); 26 | end Builder; 27 | 28 | end Dw1000_Unit_Tests; 29 | 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Daniel King 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/dw1000.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | package DW1000 24 | is 25 | pragma Pure; 26 | 27 | end DW1000; 28 | -------------------------------------------------------------------------------- /tests/dw1000-system_time-suite.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | with AUnit.Test_Suites; use AUnit.Test_Suites; 23 | 24 | package DW1000.System_Time.Suite 25 | is 26 | 27 | function Suite return Access_Test_Suite; 28 | 29 | end DW1000.System_Time.Suite; 30 | -------------------------------------------------------------------------------- /examples/transmit/transmit_example.gpr: -------------------------------------------------------------------------------- 1 | project Transmit_Example is 2 | 3 | for Object_Dir use "build"; 4 | for Main use ("transmit_example.adb"); 5 | for Target use "arm-eabi"; 6 | type BSP_Type is 7 | ("EVB1000", "DWM1001"); 8 | BSP : BSP_Type := external ("BSP", "DWM1001"); 9 | 10 | package Ide is 11 | for Program_Host use "localhost:2331"; 12 | for Communication_Protocol use "extended-remote"; 13 | end Ide; 14 | 15 | package Builder is 16 | case BSP is 17 | when "EVB1000" => 18 | for Default_Switches ("ada") use ("--RTS=ravenscar-full-evb1000", "-j4", "-g"); 19 | 20 | when "DWM1001" => 21 | for Default_Switches ("ada") use ("--RTS=ravenscar-full-nrf52832", "-j4", "-g"); 22 | end case; 23 | end Builder; 24 | 25 | package Compiler is 26 | for Default_Switches ("ada") use ("-gnatn", "-ffunction-sections", "-fdata-sections", "-gnatp", "-g", "-gnat12", "-gnatwc.cefghijklmoqrtvwxyz", "-gnaty3aAbcdefhiklL7M100nrSstu"); 27 | end Compiler; 28 | 29 | package Linker is 30 | for Default_Switches ("ada") use ("-g", "-Wl,--gc-sections"); 31 | end Linker; 32 | 33 | case BSP is 34 | 35 | when "EVB1000" => 36 | for Runtime ("ada") use "ravenscar-full-evb1000"; 37 | for Source_Dirs use (".", "../../src", "../../bsp-examples/evb1000"); 38 | 39 | when "DWM1001" => 40 | for Runtime ("ada") use "ravenscar-full-nrf52832"; 41 | for Source_Dirs use (".", "../../src", "../../bsp-examples/dwm1001"); 42 | end case; 43 | 44 | end Transmit_Example; 45 | 46 | -------------------------------------------------------------------------------- /examples/echo/echo_example.gpr: -------------------------------------------------------------------------------- 1 | project Echo_Example is 2 | 3 | for Object_Dir use "build"; 4 | for Main use ("echo_example.adb"); 5 | type Bsp_Type is 6 | ("DWM1001", "EVB1000"); 7 | Bsp : Bsp_Type := external ("BSP", "DWM1001"); 8 | 9 | case Bsp is 10 | 11 | when "DWM1001" => 12 | for Source_Dirs use (".", "../../src", "../../bsp-examples/dwm1001"); 13 | for Target use "arm-eabi"; 14 | for Runtime ("ada") use "ravenscar-full-nrf52832"; 15 | 16 | when "EVB1000" => 17 | for Source_Dirs use (".", "../../src", "../../bsp-examples/evb1000"); 18 | for Target use "arm-eabi"; 19 | for Runtime ("ada") use "ravenscar-full-nrf52832"; 20 | end case; 21 | 22 | package Ide is 23 | for Program_Host use "localhost:4242"; 24 | for Communication_Protocol use "extended-remote"; 25 | end Ide; 26 | 27 | package Builder is 28 | 29 | case Bsp is 30 | 31 | when "DWM1001" => 32 | for Default_Switches ("ada") use ("--RTS=ravenscar-full-nrf52832", "-j0", "-g"); 33 | 34 | when "EVB1000" => 35 | for Default_Switches ("ada") use ("--RTS=ravenscar-full-evb1000", "-j0", "-g"); 36 | end case; 37 | end Builder; 38 | 39 | package Compiler is 40 | for Default_Switches ("ada") use ("-gnatn", "-ffunction-sections", "-fdata-sections", "-gnatp", "-g", "-gnat12", "-gnatwc.cefghijklmoqrtvwxyz", "-gnaty3aAbcdefhiklL7M100nrSstu"); 41 | end Compiler; 42 | 43 | package Linker is 44 | for Default_Switches ("ada") use ("-g", "-Wl,--gc-sections"); 45 | end Linker; 46 | 47 | end Echo_Example; 48 | 49 | -------------------------------------------------------------------------------- /examples/receive/receive_example.gpr: -------------------------------------------------------------------------------- 1 | project Receive_Example is 2 | 3 | for Object_Dir use "build"; 4 | for Main use ("receive_example.adb"); 5 | type Bsp_Type is 6 | ("DWM1001", "EVB1000"); 7 | Bsp : Bsp_Type := external ("BSP", "DWM1001"); 8 | 9 | case Bsp is 10 | 11 | when "DWM1001" => 12 | for Source_Dirs use (".", "../../src", "../../bsp-examples/dwm1001"); 13 | for Target use "arm-eabi"; 14 | for Runtime ("ada") use "ravenscar-full-nrf52832"; 15 | 16 | when "EVB1000" => 17 | for Source_Dirs use (".", "../../src", "../../bsp-examples/evb1000"); 18 | for Target use "arm-eabi"; 19 | for Runtime ("ada") use "ravenscar-full-nrf52832"; 20 | end case; 21 | 22 | package Ide is 23 | for Program_Host use "localhost:4242"; 24 | for Communication_Protocol use "extended-remote"; 25 | end Ide; 26 | 27 | package Builder is 28 | 29 | case Bsp is 30 | 31 | when "DWM1001" => 32 | for Default_Switches ("ada") use ("--RTS=ravenscar-full-nrf52832", "-j0", "-g"); 33 | 34 | when "EVB1000" => 35 | for Default_Switches ("ada") use ("--RTS=ravenscar-full-evb1000", "-j0", "-g"); 36 | end case; 37 | end Builder; 38 | 39 | package Compiler is 40 | for Default_Switches ("ada") use ("-gnatn", "-ffunction-sections", "-fdata-sections", "-gnatp", "-g", "-gnat12", "-gnatwc.cefghijklmoqrtvwxyz", "-gnaty3aAbcdefhiklL7M100nrSstu"); 41 | end Compiler; 42 | 43 | package Linker is 44 | for Default_Switches ("ada") use ("-g", "-Wl,--gc-sections"); 45 | end Linker; 46 | 47 | end Receive_Example; 48 | 49 | -------------------------------------------------------------------------------- /tests/test_dw1000.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | with AUnit.Reporter.Text; 23 | with AUnit.Run; 24 | with DW1000.System_Time.Suite; 25 | 26 | procedure Test_DW1000 is 27 | procedure Runner is new AUnit.Run.Test_Runner (DW1000.System_Time.Suite.Suite); 28 | 29 | Reporter : AUnit.Reporter.Text.Text_Reporter; 30 | 31 | begin 32 | Runner (Reporter); 33 | 34 | end Test_DW1000; 35 | -------------------------------------------------------------------------------- /src/dw1000-generic_wo_register_driver.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Unchecked_Conversion; 24 | with DW1000.Register_Driver; 25 | 26 | package body DW1000.Generic_WO_Register_Driver 27 | is 28 | subtype Register_Byte_Array is 29 | DW1000.Types.Byte_Array (1 .. Register_Type'Size / 8); 30 | 31 | function Register_To_Bytes is new Ada.Unchecked_Conversion 32 | (Source => Register_Type, 33 | Target => Register_Byte_Array); 34 | 35 | procedure Write (Reg : in Register_Type) is 36 | Reg_Bytes : Register_Byte_Array; 37 | 38 | begin 39 | Reg_Bytes := Register_To_Bytes (Reg); 40 | 41 | DW1000.Register_Driver.Write_Register (Register_ID, 42 | Sub_Register, 43 | Reg_Bytes); 44 | end Write; 45 | 46 | end DW1000.Generic_WO_Register_Driver; 47 | -------------------------------------------------------------------------------- /tests/dw1000-system_time-tests.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | with AUnit.Test_Fixtures; 23 | 24 | package DW1000.System_Time.Tests 25 | is 26 | type Test is new AUnit.Test_Fixtures.Test_Fixture with null record; 27 | 28 | procedure Test_Bits_40_Fine (T : in out Test); 29 | -- Proves the following property: 30 | -- (for all X in Bits_40'Range => 31 | -- X = To_Bits_40 (To_Fine_System_Time (X))) 32 | 33 | procedure Test_Bits_40_Coarse (T : in out Test); 34 | -- Proves the following property: 35 | -- (for all X in Bits_40'Range => 36 | -- X = To_Bits_40 (To_Coarse_System_Time (X))) 37 | 38 | procedure Test_To_Coarse_System_Time (T : in out Test); 39 | -- Proves the following property: 40 | -- (for all X in Coarse_System_Time => 41 | -- X = To_Coarse_System_Time (To_Fine_System_Time (X))) 42 | 43 | end DW1000.System_Time.Tests; 44 | -------------------------------------------------------------------------------- /tests/dw1000-system_time-suite.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | with AUnit.Test_Caller; 23 | with DW1000.System_Time.Tests; 24 | 25 | package body DW1000.System_Time.Suite 26 | is 27 | 28 | function Suite return Access_Test_Suite 29 | is 30 | package Caller is new AUnit.Test_Caller (Tests.Test); 31 | 32 | Ret : constant Access_Test_Suite := new Test_Suite; 33 | begin 34 | Ret.Add_Test(Caller.Create 35 | ("Test conversion: Bits_40 -> Fine -> Bits_40", 36 | Tests.Test_Bits_40_Fine'Access)); 37 | Ret.Add_Test(Caller.Create 38 | ("Test conversion: Bits_40 -> Coarse -> Bits_40", 39 | Tests.Test_Bits_40_Coarse'Access)); 40 | Ret.Add_Test(Caller.Create 41 | ("Test conversion: Coarse -> Fine -> Coarse", 42 | Tests.Test_To_Coarse_System_Time'Access)); 43 | 44 | return Ret; 45 | end Suite; 46 | 47 | end DW1000.System_Time.Suite; 48 | -------------------------------------------------------------------------------- /src/dw1000-generic_rw_register_driver.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Generic_RO_Register_Driver; 24 | with DW1000.Generic_WO_Register_Driver; 25 | 26 | package body DW1000.Generic_RW_Register_Driver 27 | is 28 | 29 | ------------------- 30 | -- Read_Driver -- 31 | ------------------- 32 | 33 | -- Reuse the Read/Write procedures from the other drivers. 34 | package Read_Driver is new Generic_RO_Register_Driver 35 | (Register_Type, 36 | Register_ID, 37 | Sub_Register); 38 | 39 | package Write_Driver is new Generic_WO_Register_Driver 40 | (Register_Type, 41 | Register_ID, 42 | Sub_Register); 43 | 44 | ------------ 45 | -- Read -- 46 | ------------ 47 | 48 | procedure Read (Reg : out Register_Type) is 49 | begin 50 | Read_Driver.Read (Reg); 51 | end Read; 52 | 53 | ------------- 54 | -- Write -- 55 | ------------- 56 | 57 | procedure Write (Reg : in Register_Type) is 58 | begin 59 | Write_Driver.Write (Reg); 60 | end Write; 61 | 62 | end DW1000.Generic_RW_Register_Driver; 63 | -------------------------------------------------------------------------------- /src/dw1000-generic_wo_register_driver.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.BSP; 24 | with DW1000.Types; 25 | 26 | -- This package provides a generic API for typed write-only registers. 27 | -- 28 | -- Register_Type is the typed representation of the register (e.g. a record 29 | -- with a representation clause matching the layout of the register according 30 | -- to the DW1000 User Manual). 31 | -- 32 | -- Register_ID is the numerical ID of the register file according to the 33 | -- DW1000 User Manual. 34 | -- 35 | -- Sub_Register is the offset of the sub-register within the register file. 36 | -- If the register file has no sub-registers then this should be set to 0. 37 | generic 38 | type Register_Type is private; 39 | Register_ID : DW1000.Types.Bits_6; 40 | Sub_Register : DW1000.Types.Bits_15 := 0; 41 | package DW1000.Generic_WO_Register_Driver 42 | is 43 | 44 | procedure Write (Reg : in Register_Type) 45 | with Global => (In_Out => DW1000.BSP.Device_State), 46 | Depends => (DW1000.BSP.Device_State =>+ Reg), 47 | SPARK_Mode => On; 48 | 49 | end DW1000.Generic_WO_Register_Driver; 50 | -------------------------------------------------------------------------------- /src/dw1000-generic_ro_register_driver.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.BSP; 24 | with DW1000.Types; 25 | 26 | -- This package provides a generic API for typed read-only registers. 27 | -- 28 | -- Register_Type is the typed representation of the register (e.g. a record 29 | -- with a representation clause matching the layout of the register according 30 | -- to the DW1000 User Manual). 31 | -- 32 | -- Register_ID is the numerical ID of the register file according to the 33 | -- DW1000 User Manual. 34 | -- 35 | -- Sub_Register is the offset of the sub-register within the register file. 36 | -- If the register file has no sub-registers then this should be set to 0. 37 | generic 38 | type Register_Type is private; 39 | Register_ID : DW1000.Types.Bits_6; 40 | Sub_Register : DW1000.Types.Bits_15 := 0; 41 | package DW1000.Generic_RO_Register_Driver 42 | is 43 | 44 | procedure Read (Reg : out Register_Type) 45 | with Global => (In_Out => DW1000.BSP.Device_State), 46 | Depends => (DW1000.BSP.Device_State => DW1000.BSP.Device_State, 47 | Reg => DW1000.BSP.Device_State), 48 | SPARK_Mode => On; 49 | 50 | end DW1000.Generic_RO_Register_Driver; 51 | -------------------------------------------------------------------------------- /src/dw1000-system_time.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | package body DW1000.System_Time 24 | with SPARK_Mode => On 25 | is 26 | 27 | -------------------------- 28 | -- System_Time_Offset -- 29 | -------------------------- 30 | 31 | function System_Time_Offset (Time : in Fine_System_Time; 32 | Span : in System_Time_Span) 33 | return Fine_System_Time is 34 | 35 | Span_FST : constant Fine_System_Time := Fine_System_Time (Span); 36 | 37 | begin 38 | if Fine_System_Time'Last - Time >= Span_FST then 39 | return Time + Span_FST; 40 | else 41 | -- Wrap-around case 42 | return Fine_System_Time'Last - Span_FST; 43 | end if; 44 | end System_Time_Offset; 45 | 46 | ---------------------- 47 | -- Calculate_Span -- 48 | ---------------------- 49 | 50 | function Calculate_Span (Start_Time : in Fine_System_Time; 51 | End_Time : in Fine_System_Time) 52 | return System_Time_Span is 53 | begin 54 | if Start_Time <= End_Time then 55 | return System_Time_Span (End_Time - Start_Time); 56 | 57 | else 58 | return System_Time_Span ((Fine_System_Time'Last - Start_Time) + 59 | End_Time); 60 | end if; 61 | end Calculate_Span; 62 | 63 | end DW1000.System_Time; 64 | -------------------------------------------------------------------------------- /src/dw1000-generic_rw_register_driver.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.BSP; 24 | with DW1000.Types; 25 | 26 | -- This package provides a generic API for typed read/write registers. 27 | -- 28 | -- Register_Type is the typed representation of the register (e.g. a record 29 | -- with a representation clause matching the layout of the register according 30 | -- to the DW1000 User Manual). 31 | -- 32 | -- Register_ID is the numerical ID of the register file according to the 33 | -- DW1000 User Manual. 34 | -- 35 | -- Sub_Register is the offset of the sub-register within the register file. 36 | -- If the register file has no sub-registers then this should be set to 0. 37 | generic 38 | type Register_Type is private; 39 | Register_ID : DW1000.Types.Bits_6; 40 | Sub_Register : DW1000.Types.Bits_15 := 0; 41 | package DW1000.Generic_RW_Register_Driver 42 | is 43 | 44 | procedure Read (Reg : out Register_Type) 45 | with Inline, 46 | Global => (In_Out => DW1000.BSP.Device_State), 47 | Depends => (DW1000.BSP.Device_State => DW1000.BSP.Device_State, 48 | Reg => DW1000.BSP.Device_State), 49 | SPARK_Mode => On; 50 | 51 | procedure Write (Reg : in Register_Type) 52 | with Inline, 53 | Global => (In_Out => DW1000.BSP.Device_State), 54 | Depends => (DW1000.BSP.Device_State =>+ Reg), 55 | SPARK_Mode => On; 56 | 57 | end DW1000.Generic_RW_Register_Driver; 58 | -------------------------------------------------------------------------------- /src/dw1000-generic_ro_register_driver.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Register_Driver; 24 | 25 | package body DW1000.Generic_RO_Register_Driver 26 | is 27 | subtype Register_Byte_Array is 28 | DW1000.Types.Byte_Array (1 .. Register_Type'Size / 8); 29 | 30 | ------------------- 31 | -- Deserialize -- 32 | ------------------- 33 | 34 | procedure Deserialize (Source : in Register_Byte_Array; 35 | Target : out Register_Type) 36 | with Inline, 37 | Depends => (Target => Source), 38 | SPARK_Mode => On; 39 | 40 | procedure Deserialize (Source : in Register_Byte_Array; 41 | Target : out Register_Type) 42 | with SPARK_Mode => Off is 43 | 44 | -- Overlay a byte array onto the target register value. 45 | Target_Bytes : Register_Byte_Array 46 | with Import, 47 | Convention => Ada, 48 | Address => Target'Address; 49 | 50 | begin 51 | Target_Bytes := Source; 52 | end Deserialize; 53 | 54 | ------------ 55 | -- Read -- 56 | ------------ 57 | 58 | procedure Read (Reg : out Register_Type) is 59 | Reg_Bytes : Register_Byte_Array; 60 | 61 | begin 62 | DW1000.Register_Driver.Read_Register (Register_ID, 63 | Sub_Register, 64 | Reg_Bytes); 65 | 66 | Deserialize (Source => Reg_Bytes, 67 | Target => Reg); 68 | end Read; 69 | 70 | end DW1000.Generic_RO_Register_Driver; 71 | -------------------------------------------------------------------------------- /src/dw1000-constants.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Types; use DW1000.Types; 24 | with DW1000.Register_Types; use DW1000.Register_Types; 25 | 26 | package DW1000.Constants 27 | with SPARK_Mode => On 28 | is 29 | 30 | ---------------------------------------------------------------------------- 31 | -- OTP memory word addresses 32 | OTP_ADDR_EUID : constant OTP_ADDR_Field := 16#00#; 33 | OTP_ADDR_LDOTUNE_CAL : constant OTP_ADDR_Field := 16#04#; 34 | OTP_ADDR_CHIP_ID : constant OTP_ADDR_Field := 16#06#; 35 | OTP_ADDR_LOT_ID : constant OTP_ADDR_Field := 16#07#; 36 | OTP_ADDR_CH1_TX_POWER_PRF_16 : constant OTP_ADDR_Field := 16#10#; 37 | OTP_ADDR_CH1_TX_POWER_PRF_64 : constant OTP_ADDR_Field := 16#11#; 38 | OTP_ADDR_CH2_TX_POWER_PRF_16 : constant OTP_ADDR_Field := 16#12#; 39 | OTP_ADDR_CH2_TX_POWER_PRF_64 : constant OTP_ADDR_Field := 16#13#; 40 | OTP_ADDR_CH3_TX_POWER_PRF_16 : constant OTP_ADDR_Field := 16#14#; 41 | OTP_ADDR_CH3_TX_POWER_PRF_64 : constant OTP_ADDR_Field := 16#15#; 42 | OTP_ADDR_CH4_TX_POWER_PRF_16 : constant OTP_ADDR_Field := 16#16#; 43 | OTP_ADDR_CH4_TX_POWER_PRF_64 : constant OTP_ADDR_Field := 16#17#; 44 | OTP_ADDR_CH5_TX_POWER_PRF_16 : constant OTP_ADDR_Field := 16#18#; 45 | OTP_ADDR_CH5_TX_POWER_PRF_64 : constant OTP_ADDR_Field := 16#19#; 46 | OTP_ADDR_CH7_TX_POWER_PRF_16 : constant OTP_ADDR_Field := 16#1A#; 47 | OTP_ADDR_CH7_TX_POWER_PRF_64 : constant OTP_ADDR_Field := 16#1B#; 48 | OTP_ADDR_ANTENNA_DELAY : constant OTP_ADDR_Field := 16#1C#; 49 | OTP_ADDR_XTAL_TRIM : constant OTP_ADDR_Field := 16#E0#; 50 | 51 | ---------------------------------------------------------------------------- 52 | -- Buffer lengths 53 | TX_BUFFER_Length : constant := 1024; 54 | RX_BUFFER_Length : constant := 1024; 55 | 56 | end DW1000.Constants; 57 | -------------------------------------------------------------------------------- /src/dw1000-ranging.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Driver; 24 | with DW1000.System_Time; use DW1000.System_Time; 25 | 26 | package DW1000.Ranging 27 | with SPARK_Mode => On 28 | is 29 | Air_Refractive_Index : constant := 1.0003; 30 | 31 | Speed_Of_Light_In_Vacuum : constant := 299_792_458.0; -- meters per second 32 | 33 | Speed_Of_Light_In_Air : constant 34 | := Speed_Of_Light_In_Vacuum / Air_Refractive_Index; -- meters per second 35 | 36 | type Meters is delta 0.001 range 0.0 .. 30_000.0; 37 | -- Distance in meters with a resolution of 1 mm. 38 | -- 39 | -- This type is constrained to a maximum range of 30 km, which is more than 40 | -- enough since the operational range of the DW1000 is limited to 300 m. 41 | 42 | type Biased_Distance is new Meters; 43 | -- Type for distance measurements (in meters) which includes a ranging bias. 44 | -- 45 | -- The bias is influenced by the UWB channel and pulse repetition frequency 46 | -- (PRF) that was used to perform the measurement. This bias must be removed 47 | -- for a more accurate ranging measurement. 48 | 49 | function Remove_Ranging_Bias 50 | (Measured_Distance : in Biased_Distance; 51 | Channel : in DW1000.Driver.Channel_Number; 52 | PRF : in DW1000.Driver.PRF_Type) return Meters 53 | with Global => null; 54 | -- Remove the ranging bias from a distance measurement. 55 | -- 56 | -- The distance calculated using the DW1000 contains a bias based on the 57 | -- channel and PRF configuration used during the measurement. This bias 58 | -- must be removed to achieve a more accurate ranging measurement. 59 | -- 60 | -- @param Measured_Distance The distance measurement which includes the 61 | -- ranging bias. 62 | -- 63 | -- @param Channel The UWB channel which was used to measure the distance. 64 | -- 65 | -- @param PRF The PRF which was used to measure the distance. 66 | -- 67 | -- @return The corrected distance, with the bias removed. 68 | 69 | end DW1000.Ranging; 70 | -------------------------------------------------------------------------------- /bsp-examples/evb1000/decadriver_config.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Interrupts.Names; 24 | with System; 25 | 26 | -- @summary 27 | -- Configuration options for the DecaDriver. 28 | package DecaDriver_Config 29 | is 30 | 31 | DW1000_IRQ_Id : constant Ada.Interrupts.Interrupt_ID 32 | := Ada.Interrupts.Names.EXTI9_5_Interrupt; 33 | -- The interrupt ID for the DW1000 IRQ line. 34 | 35 | Driver_Priority : constant System.Interrupt_Priority 36 | := System.Interrupt_Priority'Last; 37 | -- The interrupt priority used for the DecaDriver's protected objects. 38 | 39 | Receiver_Queue_Length : constant Positive := 2; 40 | -- The length of the receiver queue used to hold received packets 41 | -- on the host MCU side. 42 | -- 43 | -- The minimum value for this configuration parameter is 2. 44 | -- 45 | -- Larger values for this configuration parameter make it less likely for 46 | -- a packet to be missed (overrun condition). However, larger values will 47 | -- use more memory. 48 | 49 | Maximum_Receive_Frame_Length : constant Positive := 1024; 50 | -- Controls the buffer size used for storing received frames in the 51 | -- receiver driver queue. 52 | -- 53 | -- The minimum permitted value is 1. 54 | -- The maximum permitted value is 1024. 55 | -- 56 | -- The DW1000 supports extended frame lengths of up to 1024 bytes. However, 57 | -- the IEEE 802.15.4-2011 standard restricts the physical frame size to 58 | -- 127 bytes (see the constant aMaxPHYPacketSize in Table 70 in 59 | -- Section 9.2 of the IEEE 802.15.4-2011 standard). 60 | -- 61 | -- If you are using the extended capabilities of the DW1000 then this 62 | -- constant should be set to 1024. 63 | -- 64 | -- Otherwise, if you are only using frames up to the maximum size set in 65 | -- the standard (127 bytes) then you can set this constant to 127 to 66 | -- reduce the amount of memory used by the receiver driver's queue. 67 | -- 68 | -- If a frame is received by the driver whose length is smaller than this 69 | -- constant then the received frame is truncated to this length. For 70 | -- example, if Maximum_Receive_Frame_Size is set to 50, and a frame is 71 | -- received with a length of 62 bytes, then the received frame is truncated 72 | -- to the first 50 bytes (the last 12 bytes are ignored by the driver). 73 | 74 | end DecaDriver_Config; 75 | -------------------------------------------------------------------------------- /bsp-examples/dwm1001/decadriver_config.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Interrupts.Names; 24 | with System; 25 | 26 | -- @summary 27 | -- Configuration options for the DecaDriver. 28 | package DecaDriver_Config 29 | is 30 | 31 | DW1000_IRQ_Id : constant Ada.Interrupts.Interrupt_ID 32 | := Ada.Interrupts.Names.GPIOTE_Interrupt; 33 | -- The interrupt ID for the DW1000 IRQ line. 34 | -- 35 | -- This must not be a reserved interrupt. Note that GNAT Ravenscar runtimes 36 | -- from bb-runtimes never have reserved interrupts, so any Interrupt_ID 37 | -- is valid. 38 | 39 | Driver_Priority : constant System.Interrupt_Priority 40 | := System.Interrupt_Priority'Last; 41 | -- The interrupt priority used for the DecaDriver's protected objects. 42 | 43 | Receiver_Queue_Length : constant Positive := 2; 44 | -- The length of the receiver queue used to hold received packets 45 | -- on the host MCU side. 46 | -- 47 | -- The minimum value for this configuration parameter is 2. 48 | -- 49 | -- Larger values for this configuration parameter make it less likely for 50 | -- a packet to be missed (overrun condition). However, larger values will 51 | -- use more memory. 52 | 53 | Maximum_Receive_Frame_Length : constant Positive := 1024; 54 | -- Controls the buffer size used for storing received frames in the 55 | -- receiver driver queue. 56 | -- 57 | -- The minimum permitted value is 1. 58 | -- The maximum permitted value is 1024. 59 | -- 60 | -- The DW1000 supports extended frame lengths of up to 1024 bytes. However, 61 | -- the IEEE 802.15.4-2011 standard restricts the physical frame size to 62 | -- 127 bytes (see the constant aMaxPHYPacketSize in Table 70 in 63 | -- Section 9.2 of the IEEE 802.15.4-2011 standard). 64 | -- 65 | -- If you are using the extended capabilities of the DW1000 then this 66 | -- constant should be set to 1024. 67 | -- 68 | -- Otherwise, if you are only using frames up to the maximum size set in 69 | -- the standard (127 bytes) then you can set this constant to 127 to 70 | -- reduce the amount of memory used by the receiver driver's queue. 71 | -- 72 | -- If a frame is received by the driver whose length is smaller than this 73 | -- constant then the received frame is truncated to this length. For 74 | -- example, if Maximum_Receive_Frame_Size is set to 50, and a frame is 75 | -- received with a length of 62 bytes, then the received frame is truncated 76 | -- to the first 50 bytes (the last 12 bytes are ignored by the driver). 77 | 78 | end DecaDriver_Config; 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/damaki/DW1000.svg?branch=master)](https://travis-ci.com/damaki/DW1000) 2 | 3 | # DW1000 4 | 5 | This repository contains an Ada/SPARK driver for the 6 | [DecaWave DW1000](http://www.decawave.com/products/dw1000) 7 | ultra-wideband (UWB) radio chip. 8 | 9 | The driver code written and verified using the SPARK language (a subset of Ada). 10 | GNATprove is used to prove the absence of runtime errors such as: numerical overflow, 11 | infinite loops, division by zero, and out-of-bounds array accesses. 12 | 13 | The API is currently considered unstable. You may need to update your code to 14 | to reflect API changes as the driver is developed. 15 | 16 | ## License 17 | 18 | All files are licensed under the MIT license. 19 | 20 | ## Using the driver 21 | 22 | To use the driver, include the contents of the ``src`` directory into your 23 | project, as well as the appropriate BSP directory under `bsp-examples` 24 | (or provide your own implementation for your own hardware). 25 | 26 | Check out the [Wiki](https://github.com/damaki/DW1000/wiki) for more information 27 | on using the driver. 28 | 29 | ### Prerequisites 30 | 31 | Parts of the driver require certain runtime features that are not available on all 32 | bare-board Ada runtimes. In particular, the following features are used: 33 | * Protected objects are used by the ``DecaDriver``. This requires 34 | an Ada runtime supporting tasking (e.g. a Ravenscar runtime). 35 | * The ``Ada.Real_Time.Clock`` function is used by the ``DW1000.Driver`` 36 | package. This feature is also supported in Ravenscar runtimes. 37 | * The package ``Ada.Numerics.Generic_Elementary_Functions`` is used by the 38 | package ``DW1000.Reception_Quality``. Small footprint (SFP) Ravenscar 39 | runtimes don't support these math functions, but they are implemented in 40 | the full Ravenscar runtimes. 41 | 42 | Typically, this means that a full Ravenscar runtime is required as a minimum. 43 | AdaCore's [bb-runtimes](https://github.com/AdaCore/bb-runtimes) repository has 44 | runtimes available for a variety of bare-bones embedded targets. The exact 45 | runtime needed depends on your target board. 46 | 47 | If you don't use all of the features of this driver, then you can use a reduced 48 | runtime. For example, if you don't use the `DecaDriver` then you don't need a 49 | Ravenscar runtime (unless other parts of your code use Ravenscar features). 50 | 51 | ### Supported Boards 52 | 53 | This driver currently supports the [DWM1001](https://www.decawave.com/product/dwm1001-module/) 54 | module. This module is used in the [DWM1001-DEV](https://www.decawave.com/product/dwm1001-development-board/) 55 | development board and the [MDEK1001](https://www.decawave.com/product/mdek1001-deployment-kit/) 56 | development kit. 57 | 58 | Previously, the [EVB1000](https://www.decawave.com/product/evk1000-evaluation-kit/) 59 | was supported and an old port to this board is still present in the `bsp-examples` 60 | directory. This port is currently obsolete/broken due to lack of EVB1000 hardware 61 | available to develop with. 62 | 63 | ### Porting the BSP 64 | 65 | Porting the driver to a new target consists of re-implementing the `dw1000-bsp.adb` 66 | file, which implements the `DW1000.BSP` package. This package implements everything 67 | necessary to actually communicate with the DW1000 including: sending and receiving 68 | data via SPI, managing the DW1000 interrupt request (IRQ), resetting the 69 | DW1000, and waking it up from its sleep mode. 70 | 71 | The package spec is already defined in the package spec in the file 72 | `src/dw1000-bsp.ads`. This stays the same for all targets; only the package body 73 | needs to be re-implemented. 74 | 75 | An reference implementation for the DWM1001 target can be found in 76 | ``bsp-examples/dwm1001/dw1000-bsp.adb``. This is a useful starting point when 77 | porting to a new target. 78 | 79 | ## See Also 80 | 81 | If you are using the [DecaWave EVB1000](http://www.decawave.com/products/evk1000-evaluation-kit) 82 | evaluation board then there are the following two SPARK and Ada projects on 83 | GitHub which are useful: 84 | * [EVB1000](https://github.com/damaki/EVB1000): SPARK drivers for the LCD, LED, 85 | and switch peripherals on the EVB1000. 86 | * [Ravenscar-full-evb1000](https://github.com/damaki/ravenscar-full-evb1000): 87 | a full Ravenscar runtime for the STM32F105 ARM Cortex-M3 microcontroller, 88 | configured for the EVB1000. 89 | 90 | ## Examples 91 | 92 | See the [examples](https://github.com/damaki/DW1000/tree/master/examples) 93 | directory for various example programs using the driver. -------------------------------------------------------------------------------- /examples/receive/receive_example.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Real_Time; use Ada.Real_Time; 24 | with DecaDriver; 25 | with DW1000.BSP; 26 | with DW1000.Driver; use DW1000.Driver; 27 | with DW1000.Types; 28 | 29 | -- This simple example demonstrates using the DW1000 to receive packets. 30 | procedure Receive_Example 31 | with SPARK_Mode, 32 | Global => (Input => Ada.Real_Time.Clock_Time, 33 | In_Out => (DW1000.BSP.Device_State, 34 | DecaDriver.Driver)), 35 | Depends => (DecaDriver.Driver =>+ DW1000.BSP.Device_State, 36 | DW1000.BSP.Device_State =>+ DecaDriver.Driver, 37 | null => Ada.Real_Time.Clock_Time) 38 | is 39 | Rx_Packet : DW1000.Types.Byte_Array (1 .. 127) := (others => 0); 40 | Rx_Packet_Length : DecaDriver.Frame_Length_Number; 41 | Rx_Frame_Info : DecaDriver.Frame_Info_Type; 42 | Rx_Status : DecaDriver.Rx_Status_Type; 43 | Rx_Overrun : Boolean; 44 | 45 | begin 46 | -- Driver must be initialized once before it is used. 47 | DecaDriver.Driver.Initialize 48 | (Load_Antenna_Delay => True, 49 | Load_XTAL_Trim => True, 50 | Load_UCode_From_ROM => True); 51 | 52 | -- Configure the DW1000 53 | DecaDriver.Driver.Configure 54 | (DecaDriver.Configuration_Type' 55 | (Channel => 1, 56 | PRF => PRF_64MHz, 57 | Tx_Preamble_Length => PLEN_1024, 58 | Rx_PAC => PAC_8, 59 | Tx_Preamble_Code => 9, 60 | Rx_Preamble_Code => 9, 61 | Use_Nonstandard_SFD => False, 62 | Data_Rate => Data_Rate_110k, 63 | PHR_Mode => Standard_Frames, 64 | SFD_Timeout => 1024 + 64 + 1)); 65 | 66 | -- We don't need to configure the transmit power in this example, because 67 | -- we don't transmit any frames! 68 | 69 | -- Enable the LEDs controlled by the DW1000. 70 | DW1000.Driver.Configure_LEDs 71 | (Tx_LED_Enable => True, -- Enable transmit LED 72 | Rx_LED_Enable => True, -- Enable receive LED 73 | Rx_OK_LED_Enable => False, 74 | SFD_LED_Enable => False, 75 | Test_Flash => True); -- Flash both LEDs once 76 | 77 | -- In this example we only want to receive valid packets without errors, 78 | -- so configure the DW1000 to automatically re-enable the receiver when 79 | -- errors occur. The driver will not be notified of receiver errors whilst 80 | -- this is enabled. 81 | DW1000.Driver.Set_Auto_Rx_Reenable (Enable => True); 82 | 83 | -- Continuously receive packets 84 | loop 85 | -- Enable the receiver to listen for a packet 86 | DecaDriver.Driver.Start_Rx_Immediate; 87 | 88 | -- Wait for a packet 89 | DecaDriver.Driver.Rx_Wait 90 | (Frame => Rx_Packet, 91 | Length => Rx_Packet_Length, 92 | Frame_Info => Rx_Frame_Info, 93 | Status => Rx_Status, 94 | Overrun => Rx_Overrun); 95 | 96 | -- When execution has reached here then a packet has been received 97 | -- successfully. 98 | end loop; 99 | end Receive_Example; 100 | -------------------------------------------------------------------------------- /src/dw1000-ranging-single_sided.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | package DW1000.Ranging.Single_Sided 24 | with SPARK_Mode => On 25 | is 26 | 27 | function Compute_Distance 28 | (Tag_Tx_Poll_Timestamp : in Fine_System_Time; 29 | Anchor_Rx_Poll_Timestamp : in Fine_System_Time; 30 | Anchor_Tx_Resp_Timestamp : in Fine_System_Time; 31 | Tag_Rx_Resp_Timestamp : in Fine_System_Time) return Biased_Distance 32 | with Global => null; 33 | -- Compute the distance based on a single-sided ranging exchange. 34 | -- 35 | -- The distance measurement calculated by this function contains a bias 36 | -- which can be removed to obtain a more accurate distance measurement. 37 | -- The @Remove_Ranging_Bias@ function can be used to remove the bias. 38 | -- 39 | -- @param Tag_Tx_Poll_Timestamp The timestamp of the Tag's local clock when 40 | -- the Tag sent the poll message to the anchor. 41 | -- 42 | -- @param Anchor_Rx_Poll_Timestamp The timestamp of the Anchor's local 43 | -- clock when it received the poll message from the Tag. 44 | -- 45 | -- @param Anchor_Tx_Poll_Timestamp The timstamp of the Anchor's local clock 46 | -- when it sent the response message back to the Tag. 47 | -- 48 | -- @param Tag_Rx_Resp_Timestamp The timestamp of the Tag's local clock when 49 | -- it received the response from the Anchor. 50 | -- 51 | -- @return The measured distance between the tag and anchor. This 52 | -- measurement contains a bias which must be removed to obtain a more 53 | -- accurate measurement. 54 | 55 | function Compute_Distance 56 | (Tag_Tx_Poll_Timestamp : in Fine_System_Time; 57 | Anchor_Rx_Poll_Timestamp : in Fine_System_Time; 58 | Anchor_Tx_Resp_Timestamp : in Fine_System_Time; 59 | Tag_Rx_Resp_Timestamp : in Fine_System_Time; 60 | Channel : in DW1000.Driver.Channel_Number; 61 | PRF : in DW1000.Driver.PRF_Type) return Meters 62 | with Global => null; 63 | -- Compute the distance based on a single-sided ranging exchange, and 64 | -- automatically remove ranging bias. 65 | -- 66 | -- The distance measurement calculated by this function contains a bias 67 | -- which can be removed to obtain a more accurate distance measurement. 68 | -- The @Remove_Ranging_Bias@ function can be used to remove the bias. 69 | -- 70 | -- @param Tag_Tx_Poll_Timestamp The timestamp of the Tag's local clock when 71 | -- the Tag sent the poll message to the anchor. 72 | -- 73 | -- @param Anchor_Rx_Poll_Timestamp The timestamp of the Anchor's local 74 | -- clock when it received the poll message from the Tag. 75 | -- 76 | -- @param Anchor_Tx_Poll_Timestamp The timstamp of the Anchor's local clock 77 | -- when it sent the response message back to the Tag. 78 | -- 79 | -- @param Tag_Rx_Resp_Timestamp The timestamp of the Tag's local clock when 80 | -- it received the response from the Anchor. 81 | -- 82 | -- @param Channel The UWB channel on which the ranging exchange took place. 83 | -- 84 | -- @param PRF The PRF that was used for the ranging exchange. 85 | -- 86 | -- @return The measured distance between the tag and anchor. 87 | 88 | end DW1000.Ranging.Single_Sided; 89 | -------------------------------------------------------------------------------- /src/dw1000-types.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Interfaces; 24 | 25 | package DW1000.Types 26 | with SPARK_Mode => On 27 | is 28 | type Bits_1 is mod 2**1 with Size => 1; 29 | type Bits_2 is mod 2**2 with Size => 2; 30 | type Bits_3 is mod 2**3 with Size => 3; 31 | type Bits_4 is mod 2**4 with Size => 4; 32 | type Bits_5 is mod 2**5 with Size => 5; 33 | type Bits_6 is mod 2**6 with Size => 6; 34 | type Bits_7 is mod 2**7 with Size => 7; 35 | 36 | subtype Bits_8 is Interfaces.Unsigned_8; 37 | 38 | type Bits_9 is mod 2**9 with Size => 9; 39 | type Bits_10 is mod 2**10 with Size => 10; 40 | type Bits_11 is mod 2**11 with Size => 11; 41 | type Bits_12 is mod 2**12 with Size => 12; 42 | type Bits_13 is mod 2**13 with Size => 13; 43 | type Bits_14 is mod 2**14 with Size => 14; 44 | type Bits_15 is mod 2**15 with Size => 15; 45 | 46 | subtype Bits_16 is Interfaces.Unsigned_16; 47 | 48 | type Bits_17 is mod 2**17 with Size => 17; 49 | type Bits_18 is mod 2**18 with Size => 18; 50 | type Bits_19 is mod 2**19 with Size => 19; 51 | type Bits_20 is mod 2**20 with Size => 20; 52 | type Bits_21 is mod 2**21 with Size => 21; 53 | type Bits_22 is mod 2**22 with Size => 22; 54 | type Bits_23 is mod 2**23 with Size => 23; 55 | type Bits_24 is mod 2**24 with Size => 24; 56 | type Bits_25 is mod 2**25 with Size => 25; 57 | type Bits_26 is mod 2**26 with Size => 26; 58 | type Bits_27 is mod 2**27 with Size => 27; 59 | type Bits_28 is mod 2**28 with Size => 28; 60 | type Bits_29 is mod 2**29 with Size => 29; 61 | type Bits_30 is mod 2**30 with Size => 30; 62 | type Bits_31 is mod 2**31 with Size => 31; 63 | 64 | subtype Bits_32 is Interfaces.Unsigned_32; 65 | 66 | type Bits_33 is mod 2**33 with Size => 33; 67 | type Bits_34 is mod 2**34 with Size => 34; 68 | type Bits_35 is mod 2**35 with Size => 35; 69 | type Bits_36 is mod 2**36 with Size => 36; 70 | type Bits_37 is mod 2**37 with Size => 37; 71 | type Bits_38 is mod 2**38 with Size => 38; 72 | type Bits_39 is mod 2**39 with Size => 39; 73 | type Bits_40 is mod 2**40 with Size => 40; 74 | type Bits_41 is mod 2**41 with Size => 41; 75 | type Bits_42 is mod 2**42 with Size => 42; 76 | type Bits_43 is mod 2**43 with Size => 43; 77 | type Bits_44 is mod 2**44 with Size => 44; 78 | type Bits_45 is mod 2**45 with Size => 45; 79 | type Bits_46 is mod 2**46 with Size => 46; 80 | type Bits_47 is mod 2**47 with Size => 47; 81 | type Bits_48 is mod 2**48 with Size => 48; 82 | type Bits_49 is mod 2**49 with Size => 49; 83 | type Bits_50 is mod 2**50 with Size => 50; 84 | type Bits_51 is mod 2**51 with Size => 51; 85 | type Bits_52 is mod 2**52 with Size => 52; 86 | type Bits_53 is mod 2**53 with Size => 53; 87 | type Bits_54 is mod 2**54 with Size => 54; 88 | type Bits_55 is mod 2**55 with Size => 55; 89 | type Bits_56 is mod 2**56 with Size => 56; 90 | type Bits_57 is mod 2**57 with Size => 57; 91 | type Bits_58 is mod 2**58 with Size => 58; 92 | type Bits_59 is mod 2**59 with Size => 59; 93 | type Bits_60 is mod 2**60 with Size => 60; 94 | type Bits_61 is mod 2**61 with Size => 61; 95 | type Bits_62 is mod 2**62 with Size => 62; 96 | type Bits_63 is mod 2**63 with Size => 63; 97 | 98 | subtype Bits_64 is Interfaces.Unsigned_64; 99 | 100 | subtype Index is Natural range 0 .. Natural'Last - 1; 101 | 102 | type Byte_Array is array (Index range <>) of Bits_8; 103 | end DW1000.Types; 104 | -------------------------------------------------------------------------------- /examples/transmit/transmit_example.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Real_Time; use Ada.Real_Time; 24 | with Ada.Synchronous_Task_Control; use Ada.Synchronous_Task_Control; 25 | with DecaDriver; 26 | with DW1000.BSP; 27 | with DW1000.Driver; use DW1000.Driver; 28 | with DW1000.Types; 29 | with Tx_Power; 30 | 31 | -- This simple example demonstrates how to transmit packets. 32 | procedure Transmit_Example 33 | with SPARK_Mode, 34 | Global => (Input => Ada.Real_Time.Clock_Time, 35 | In_Out => (DW1000.BSP.Device_State, 36 | DecaDriver.Driver, 37 | DecaDriver.Tx_Complete_Flag)), 38 | Depends => (DecaDriver.Driver =>+ DW1000.BSP.Device_State, 39 | DW1000.BSP.Device_State =>+ DecaDriver.Driver, 40 | DecaDriver.Tx_Complete_Flag =>+ null, 41 | null => Ada.Real_Time.Clock_Time) 42 | is 43 | Packet : constant DW1000.Types.Byte_Array (1 .. 10) := (others => 16#AA#); 44 | 45 | Now : Ada.Real_Time.Time; 46 | 47 | begin 48 | -- Driver must be initialized once before it is used. 49 | DecaDriver.Driver.Initialize 50 | (Load_Antenna_Delay => True, 51 | Load_XTAL_Trim => True, 52 | Load_UCode_From_ROM => True); 53 | 54 | -- Configure the DW1000 55 | DecaDriver.Driver.Configure 56 | (DecaDriver.Configuration_Type' 57 | (Channel => 1, 58 | PRF => PRF_64MHz, 59 | Tx_Preamble_Length => PLEN_1024, 60 | Rx_PAC => PAC_8, 61 | Tx_Preamble_Code => 9, 62 | Rx_Preamble_Code => 9, 63 | Use_Nonstandard_SFD => False, 64 | Data_Rate => Data_Rate_110k, 65 | PHR_Mode => Standard_Frames, 66 | SFD_Timeout => 1024 + 64 + 1)); 67 | 68 | -- Configure the transmit power for the PRF and channel chosen. 69 | -- We use the reference values for the EVB1000 in this example. 70 | DW1000.Driver.Configure_Tx_Power 71 | (Tx_Power.Manual_Tx_Power_Table (1, PRF_64MHz)); 72 | 73 | -- Enable the LEDs controlled by the DW1000. 74 | DW1000.Driver.Configure_LEDs 75 | (Tx_LED_Enable => True, -- Enable transmit LED 76 | Rx_LED_Enable => True, -- Enable receive LED 77 | Rx_OK_LED_Enable => False, 78 | SFD_LED_Enable => False, 79 | Test_Flash => True); -- Flash both LEDs once 80 | 81 | Now := Ada.Real_Time.Clock; 82 | 83 | -- Send packets at a rate of 1 packet per second 84 | loop 85 | -- Load the packet into the transmitter's buffer. 86 | DW1000.Driver.Set_Tx_Data 87 | (Data => Packet, 88 | Offset => 0); 89 | 90 | -- Tell the driver the length of the packet and its position in the 91 | -- transmit buffer. 92 | DW1000.Driver.Set_Tx_Frame_Length 93 | (Length => Packet'Length, 94 | Offset => 0); 95 | 96 | -- Start transmitting the packet now. 97 | -- (don't turn on the receiver after transmitting). 98 | DecaDriver.Driver.Start_Tx_Immediate (Rx_After_Tx => False, 99 | Auto_Append_FCS => False); 100 | 101 | -- Wait for the packet to finish sending. 102 | Suspend_Until_True (DecaDriver.Tx_Complete_Flag); 103 | 104 | -- Wait for the time to send the next packet (1 second delay) 105 | Now := Now + Seconds (1); 106 | delay until Now; 107 | end loop; 108 | end Transmit_Example; 109 | -------------------------------------------------------------------------------- /src/dw1000-ranging-double_sided.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | package DW1000.Ranging.Double_Sided 24 | with SPARK_Mode => On 25 | is 26 | 27 | function Compute_Distance 28 | (Tag_Tx_Poll_Timestamp : in Fine_System_Time; 29 | Anchor_Rx_Poll_Timestamp : in Fine_System_Time; 30 | Anchor_Tx_Resp_Timestamp : in Fine_System_Time; 31 | Tag_Rx_Resp_Timestamp : in Fine_System_Time; 32 | Tag_Tx_Final_Timestamp : in Fine_System_Time; 33 | Anchor_Rx_Final_Timestamp : in Fine_System_Time) return Biased_Distance 34 | with Global => null; 35 | -- Compute the distance based on a double-sided ranging exchange. 36 | -- 37 | -- The distance measurement calculated by this function contains a bias 38 | -- which can be removed to obtain a more accurate distance measurement. 39 | -- The @Remove_Ranging_Bias@ function can be used to remove the bias. 40 | -- 41 | -- @param Tag_Tx_Poll_Timestamp The timestamp of the Tag's local clock when 42 | -- the Tag sent the poll message to the anchor. 43 | -- 44 | -- @param Anchor_Rx_Poll_Timestamp The timestamp of the Anchor's local 45 | -- clock when it received the poll message from the Tag. 46 | -- 47 | -- @param Anchor_Tx_Poll_Timestamp The timstamp of the Anchor's local clock 48 | -- when it sent the response message back to the Tag. 49 | -- 50 | -- @param Tag_Rx_Resp_Timestamp The timestamp of the Tag's local clock when 51 | -- it received the response from the Anchor. 52 | -- 53 | -- @param Tag_Tx_Final_Timestamp The timestamp of the Tag's local clock 54 | -- when it sent the final message to the Anchor. 55 | -- 56 | -- @param Anchor_Rx_Final_Timestamp The timestamp of the Anchor's local 57 | -- clocl when it received the Final message from the Tag. 58 | -- 59 | -- @return The measured distance between the tag and anchor. This 60 | -- measurement contains a bias which must be removed to obtain a more 61 | -- accurate measurement. 62 | 63 | function Compute_Distance 64 | (Tag_Tx_Poll_Timestamp : in Fine_System_Time; 65 | Anchor_Rx_Poll_Timestamp : in Fine_System_Time; 66 | Anchor_Tx_Resp_Timestamp : in Fine_System_Time; 67 | Tag_Rx_Resp_Timestamp : in Fine_System_Time; 68 | Tag_Tx_Final_Timestamp : in Fine_System_Time; 69 | Anchor_Rx_Final_Timestamp : in Fine_System_Time; 70 | Channel : in DW1000.Driver.Channel_Number; 71 | PRF : in DW1000.Driver.PRF_Type) return Meters 72 | with Global => null; 73 | -- Compute the distance based on a double-sided ranging exchange, and 74 | -- automatically remove ranging bias. 75 | -- 76 | -- @param Tag_Tx_Poll_Timestamp The timestamp of the Tag's local clock when 77 | -- the Tag sent the poll message to the anchor. 78 | -- 79 | -- @param Anchor_Rx_Poll_Timestamp The timestamp of the Anchor's local 80 | -- clock when it received the poll message from the Tag. 81 | -- 82 | -- @param Anchor_Tx_Poll_Timestamp The timstamp of the Anchor's local clock 83 | -- when it sent the response message back to the Tag. 84 | -- 85 | -- @param Tag_Rx_Resp_Timestamp The timestamp of the Tag's local clock when 86 | -- it received the response from the Anchor. 87 | -- 88 | -- @param Tag_Tx_Final_Timestamp The timestamp of the Tag's local clock 89 | -- when it sent the final message to the Anchor. 90 | -- 91 | -- @param Anchor_Rx_Final_Timestamp The timestamp of the Anchor's local 92 | -- clocl when it received the Final message from the Tag. 93 | -- 94 | -- @param Channel The UWB channel on which the ranging exchange took place. 95 | -- 96 | -- @param PRF The PRF that was used for the ranging exchange. 97 | -- 98 | -- @return The measured distance between the tag and anchor. 99 | 100 | end DW1000.Ranging.Double_Sided; 101 | -------------------------------------------------------------------------------- /src/dw1000-ranging-single_sided.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Types; use DW1000.Types; 24 | 25 | package body DW1000.Ranging.Single_Sided 26 | with SPARK_Mode => On 27 | is 28 | 29 | ------------------------ 30 | -- Compute_Distance -- 31 | ------------------------ 32 | 33 | function Compute_Distance 34 | (Tag_Tx_Poll_Timestamp : in Fine_System_Time; 35 | Anchor_Rx_Poll_Timestamp : in Fine_System_Time; 36 | Anchor_Tx_Resp_Timestamp : in Fine_System_Time; 37 | Tag_Rx_Resp_Timestamp : in Fine_System_Time) return Biased_Distance is 38 | 39 | Max_Time_Of_Flight : constant := 0.000_1; 40 | -- Limit the Time of Flight to a maximum of 0.000_1 seconds (100 us). 41 | -- 42 | -- This prevents overflow during the conversion from time of flight 43 | -- to distance. 44 | -- 45 | -- This limits the maximum computable distance to 29970 meters, but this 46 | -- should be plenty as the operational range of the DW1000 is about 47 | -- 100 times below this limit (300 m). 48 | 49 | type System_Time_Span_Div2 is 50 | delta System_Time_Span'Delta / 2.0 51 | range 0.0 .. System_Time_Span'Last / 2.0 52 | with Small => System_Time_Span'Small / 2.0; 53 | 54 | type Large_Meters is 55 | delta Meters'Delta 56 | range 0.0 .. (Max_Time_Of_Flight / System_Time_Span_Div2'Delta) * Speed_Of_Light_In_Vacuum; 57 | -- A fixed-point type with a large enough integer part to store the 58 | -- integer representation of a System_Time_Span_Div2 value. 59 | 60 | T_Tag : constant System_Time_Span := Calculate_Span 61 | (Start_Time => Tag_Tx_Poll_Timestamp, 62 | End_Time => Tag_Rx_Resp_Timestamp); 63 | 64 | T_Anchor : constant System_Time_Span := Calculate_Span 65 | (Start_Time => Anchor_Rx_Poll_Timestamp, 66 | End_Time => Anchor_Tx_Resp_Timestamp); 67 | 68 | Diff : System_Time_Span; 69 | 70 | Time_Of_Flight : System_Time_Span_Div2; 71 | 72 | Result : Large_Meters; 73 | 74 | begin 75 | if T_Anchor >= T_Tag then 76 | Time_Of_Flight := 0.0; 77 | 78 | else 79 | Diff := T_Tag - T_Anchor; 80 | Time_Of_Flight := System_Time_Span_Div2 (Diff / System_Time_Span (2.0)); 81 | end if; 82 | 83 | -- Limit the Time_ 84 | if Time_Of_Flight >= Max_Time_Of_Flight then 85 | Time_Of_Flight := Max_Time_Of_Flight; 86 | end if; 87 | 88 | pragma Assert_And_Cut (Time_Of_Flight <= Max_Time_Of_Flight); 89 | 90 | -- Convert the fixed-point representation to its integer represention 91 | -- (in multiples of the 'Delta). 92 | Result := Large_Meters (Time_Of_Flight / System_Time_Span_Div2 (System_Time_Span_Div2'Delta)); 93 | 94 | -- Multiply the ToF (s) with the speed of light (m/s) to yield 95 | -- the distance (m) in meters. 96 | Result := Result * Large_Meters (Speed_Of_Light_In_Vacuum); 97 | 98 | -- Convert back from integer representation to fixed-point representation. 99 | Result := Result / Large_Meters (1.0 / System_Time_Span_Div2'Delta); 100 | 101 | return Biased_Distance (Result); 102 | end Compute_Distance; 103 | 104 | ------------------------ 105 | -- Compute_Distance -- 106 | ------------------------ 107 | 108 | function Compute_Distance 109 | (Tag_Tx_Poll_Timestamp : in Fine_System_Time; 110 | Anchor_Rx_Poll_Timestamp : in Fine_System_Time; 111 | Anchor_Tx_Resp_Timestamp : in Fine_System_Time; 112 | Tag_Rx_Resp_Timestamp : in Fine_System_Time; 113 | Channel : in DW1000.Driver.Channel_Number; 114 | PRF : in DW1000.Driver.PRF_Type) return Meters is 115 | 116 | Distance_With_Bias : Biased_Distance; 117 | 118 | begin 119 | Distance_With_Bias := Compute_Distance 120 | (Tag_Tx_Poll_Timestamp => Tag_Tx_Poll_Timestamp, 121 | Anchor_Rx_Poll_Timestamp => Anchor_Rx_Poll_Timestamp, 122 | Anchor_Tx_Resp_Timestamp => Anchor_Tx_Resp_Timestamp, 123 | Tag_Rx_Resp_Timestamp => Tag_Rx_Resp_Timestamp); 124 | 125 | return Remove_Ranging_Bias 126 | (Measured_Distance => Distance_With_Bias, 127 | Channel => Channel, 128 | PRF => PRF); 129 | end Compute_Distance; 130 | 131 | end DW1000.Ranging.Single_Sided; 132 | -------------------------------------------------------------------------------- /src/dw1000-register_driver.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.BSP; 24 | with DW1000.Types; 25 | 26 | -- This package provides an octet-level interface to the DW1000's register 27 | -- set. 28 | package DW1000.Register_Driver 29 | with SPARK_Mode => On 30 | is 31 | 32 | type Operation_Type is (Read, Write) with Size => 1; 33 | for Operation_Type use (Read => 0, Write => 1); 34 | -- SPI transaction header Operation bit. 35 | 36 | type Sub_Index_Type is (Not_Present, Present) with Size => 1; 37 | for Sub_Index_Type use (Not_Present => 0, Present => 1); 38 | -- SPI transaction header Sub-Index presence bit. 39 | 40 | type Extended_Address_Type is (Not_Extended, Extended) with Size => 1; 41 | for Extended_Address_Type use (Not_Extended => 0, Extended => 1); 42 | -- SPI transaction header Extended address bit. 43 | -- 44 | -- This bit is only used for the 2 octet and 3 octet long headers. 45 | 46 | type Non_Indexed_Header is record 47 | Register_ID : DW1000.Types.Bits_6 := 0; 48 | Sub_Index : Sub_Index_Type := Not_Present; 49 | Operation : Operation_Type := Read; 50 | end record 51 | with Size => 8, 52 | Dynamic_Predicate => Non_Indexed_Header.Sub_Index = Not_Present; 53 | -- 1-octet SPI transaction header 54 | -- 55 | -- In this header the Sub_Index field must always be set to Not_Present. 56 | 57 | for Non_Indexed_Header use record 58 | Register_ID at 0 range 0 .. 5; 59 | Sub_Index at 0 range 6 .. 6; 60 | Operation at 0 range 7 .. 7; 61 | end record; 62 | 63 | type Short_Indexed_Header is record 64 | Register_ID : DW1000.Types.Bits_6 := 0; 65 | Sub_Index : Sub_Index_Type := Present; 66 | Operation : Operation_Type := Read; 67 | Register_Sub_Address : DW1000.Types.Bits_7 := 0; 68 | Extended_Address : Extended_Address_Type := Not_Extended; 69 | end record 70 | with Size => 16, 71 | Dynamic_Predicate => 72 | (Short_Indexed_Header.Sub_Index = Present and 73 | Short_Indexed_Header.Extended_Address = Not_Extended); 74 | -- 2-octet SPI transaction header 75 | -- 76 | -- In this header the Sub_Index field must always be set to Present 77 | -- and the Extended_Address field must always be set to Not_Extended. 78 | 79 | for Short_Indexed_Header use record 80 | Register_ID at 0 range 0 .. 5; 81 | Sub_Index at 0 range 6 .. 6; 82 | Operation at 0 range 7 .. 7; 83 | Register_Sub_Address at 0 range 8 .. 14; 84 | Extended_Address at 0 range 15 .. 15; 85 | end record; 86 | 87 | type Long_Indexed_Header is record 88 | Register_ID : DW1000.Types.Bits_6 := 0; 89 | Sub_Index : Sub_Index_Type := Present; 90 | Operation : Operation_Type := Read; 91 | Register_Sub_Address_LSB : DW1000.Types.Bits_7 := 0; 92 | Extended_Address : Extended_Address_Type := Extended; 93 | Register_Sub_Address_MSB : DW1000.Types.Bits_8 := 0; 94 | end record 95 | with Size => 24, 96 | Dynamic_Predicate => 97 | (Long_Indexed_Header.Sub_Index = Present and 98 | Long_Indexed_Header.Extended_Address = Extended); 99 | -- 3-octet SPI transaction header 100 | -- 101 | -- In this header the Sub_Index field must always be set to Present 102 | -- and the Extended_Address field must always be set to Extended. 103 | 104 | for Long_Indexed_Header use record 105 | Register_ID at 0 range 0 .. 5; 106 | Sub_Index at 0 range 6 .. 6; 107 | Operation at 0 range 7 .. 7; 108 | Register_Sub_Address_LSB at 0 range 8 .. 14; 109 | Extended_Address at 0 range 15 .. 15; 110 | Register_Sub_Address_MSB at 0 range 16 .. 23; 111 | end record; 112 | 113 | procedure Read_Register (Register_ID : in DW1000.Types.Bits_6; 114 | Sub_Address : in DW1000.Types.Bits_15; 115 | Data : out DW1000.Types.Byte_Array) 116 | with Global => (In_Out => DW1000.BSP.Device_State), 117 | Depends => (DW1000.BSP.Device_State =>+ (Register_ID, Sub_Address, Data), 118 | Data => (DW1000.BSP.Device_State, 119 | Register_ID, 120 | Sub_Address)), 121 | Pre => Data'Length > 0; 122 | -- Read a register on the DW1000. 123 | 124 | procedure Write_Register (Register_ID : in DW1000.Types.Bits_6; 125 | Sub_Address : in DW1000.Types.Bits_15; 126 | Data : in DW1000.Types.Byte_Array) 127 | with Global => (In_Out => DW1000.BSP.Device_State), 128 | Depends => (DW1000.BSP.Device_State =>+ (Register_ID, Sub_Address, Data)), 129 | Pre => Data'Length > 0; 130 | -- Write to a register on the DW1000. 131 | 132 | end DW1000.Register_Driver; 133 | -------------------------------------------------------------------------------- /bsp-examples/evb1000/stm32.ads: -------------------------------------------------------------------------------- 1 | -- This spec has been automatically generated from STM32F105xx.svd 2 | 3 | pragma Restrictions (No_Elaboration_Code); 4 | pragma Ada_2012; 5 | 6 | with Interfaces; use Interfaces; 7 | with System; 8 | 9 | -- STM32F105xx 10 | package STM32 is 11 | pragma Preelaborate; 12 | 13 | --------------- 14 | -- Base type -- 15 | --------------- 16 | 17 | subtype Word is Interfaces.Unsigned_32; 18 | subtype Short is Interfaces.Unsigned_16; 19 | subtype Byte is Interfaces.Unsigned_8; 20 | type Bit is mod 2**1 21 | with Size => 1; 22 | type UInt2 is mod 2**2 23 | with Size => 2; 24 | type UInt3 is mod 2**3 25 | with Size => 3; 26 | type UInt4 is mod 2**4 27 | with Size => 4; 28 | type UInt5 is mod 2**5 29 | with Size => 5; 30 | type UInt6 is mod 2**6 31 | with Size => 6; 32 | type UInt7 is mod 2**7 33 | with Size => 7; 34 | type UInt9 is mod 2**9 35 | with Size => 9; 36 | type UInt10 is mod 2**10 37 | with Size => 10; 38 | type UInt11 is mod 2**11 39 | with Size => 11; 40 | type UInt12 is mod 2**12 41 | with Size => 12; 42 | type UInt13 is mod 2**13 43 | with Size => 13; 44 | type UInt14 is mod 2**14 45 | with Size => 14; 46 | type UInt15 is mod 2**15 47 | with Size => 15; 48 | type UInt17 is mod 2**17 49 | with Size => 17; 50 | type UInt18 is mod 2**18 51 | with Size => 18; 52 | type UInt19 is mod 2**19 53 | with Size => 19; 54 | type UInt20 is mod 2**20 55 | with Size => 20; 56 | type UInt21 is mod 2**21 57 | with Size => 21; 58 | type UInt22 is mod 2**22 59 | with Size => 22; 60 | type UInt23 is mod 2**23 61 | with Size => 23; 62 | type UInt24 is mod 2**24 63 | with Size => 24; 64 | type UInt25 is mod 2**25 65 | with Size => 25; 66 | type UInt26 is mod 2**26 67 | with Size => 26; 68 | type UInt27 is mod 2**27 69 | with Size => 27; 70 | type UInt28 is mod 2**28 71 | with Size => 28; 72 | type UInt29 is mod 2**29 73 | with Size => 29; 74 | type UInt30 is mod 2**30 75 | with Size => 30; 76 | type UInt31 is mod 2**31 77 | with Size => 31; 78 | 79 | -------------------- 80 | -- Base addresses -- 81 | -------------------- 82 | 83 | PWR_Base : constant System.Address := 84 | System'To_Address (16#40007000#); 85 | GPIOA_Base : constant System.Address := 86 | System'To_Address (16#40010800#); 87 | GPIOB_Base : constant System.Address := 88 | System'To_Address (16#40010C00#); 89 | GPIOC_Base : constant System.Address := 90 | System'To_Address (16#40011000#); 91 | GPIOD_Base : constant System.Address := 92 | System'To_Address (16#40011400#); 93 | GPIOE_Base : constant System.Address := 94 | System'To_Address (16#40011800#); 95 | AFIO_Base : constant System.Address := 96 | System'To_Address (16#40010000#); 97 | EXTI_Base : constant System.Address := 98 | System'To_Address (16#40010400#); 99 | DMA1_Base : constant System.Address := 100 | System'To_Address (16#40020000#); 101 | DMA2_Base : constant System.Address := 102 | System'To_Address (16#40020400#); 103 | RTC_Base : constant System.Address := 104 | System'To_Address (16#40002800#); 105 | BKP_Base : constant System.Address := 106 | System'To_Address (16#40006C04#); 107 | IWDG_Base : constant System.Address := 108 | System'To_Address (16#40003000#); 109 | WWDG_Base : constant System.Address := 110 | System'To_Address (16#40002C00#); 111 | TIM1_Base : constant System.Address := 112 | System'To_Address (16#40012C00#); 113 | TIM2_Base : constant System.Address := 114 | System'To_Address (16#40000000#); 115 | TIM3_Base : constant System.Address := 116 | System'To_Address (16#40000400#); 117 | TIM4_Base : constant System.Address := 118 | System'To_Address (16#40000800#); 119 | TIM5_Base : constant System.Address := 120 | System'To_Address (16#40000C00#); 121 | TIM6_Base : constant System.Address := 122 | System'To_Address (16#40001000#); 123 | TIM7_Base : constant System.Address := 124 | System'To_Address (16#40001400#); 125 | I2C1_Base : constant System.Address := 126 | System'To_Address (16#40005400#); 127 | I2C2_Base : constant System.Address := 128 | System'To_Address (16#40005800#); 129 | SPI1_Base : constant System.Address := 130 | System'To_Address (16#40013000#); 131 | SPI2_Base : constant System.Address := 132 | System'To_Address (16#40003800#); 133 | SPI3_Base : constant System.Address := 134 | System'To_Address (16#40003C00#); 135 | USART1_Base : constant System.Address := 136 | System'To_Address (16#40013800#); 137 | USART2_Base : constant System.Address := 138 | System'To_Address (16#40004400#); 139 | USART3_Base : constant System.Address := 140 | System'To_Address (16#40004800#); 141 | ADC1_Base : constant System.Address := 142 | System'To_Address (16#40012400#); 143 | ADC2_Base : constant System.Address := 144 | System'To_Address (16#40012800#); 145 | CAN2_Base : constant System.Address := 146 | System'To_Address (16#40006800#); 147 | CAN1_Base : constant System.Address := 148 | System'To_Address (16#40006400#); 149 | USB_OTG_GLOBAL_Base : constant System.Address := 150 | System'To_Address (16#50000000#); 151 | USB_OTG_HOST_Base : constant System.Address := 152 | System'To_Address (16#50000400#); 153 | USB_OTG_DEVICE_Base : constant System.Address := 154 | System'To_Address (16#50000800#); 155 | USB_OTG_PWRCLK_Base : constant System.Address := 156 | System'To_Address (16#50000E00#); 157 | DAC_Base : constant System.Address := 158 | System'To_Address (16#40007400#); 159 | DBG_Base : constant System.Address := 160 | System'To_Address (16#E0042000#); 161 | UART4_Base : constant System.Address := 162 | System'To_Address (16#40004C00#); 163 | UART5_Base : constant System.Address := 164 | System'To_Address (16#40005000#); 165 | CRC_Base : constant System.Address := 166 | System'To_Address (16#40023000#); 167 | FLASH_Base : constant System.Address := 168 | System'To_Address (16#40022000#); 169 | RCC_Base : constant System.Address := 170 | System'To_Address (16#40021000#); 171 | NVIC_Base : constant System.Address := 172 | System'To_Address (16#E000E000#); 173 | 174 | end STM32; 175 | -------------------------------------------------------------------------------- /src/dw1000-register_driver.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Unchecked_Conversion; 24 | 25 | package body DW1000.Register_Driver 26 | with SPARK_Mode => On 27 | is 28 | 29 | subtype Non_Indexed_Header_Bytes is Types.Byte_Array (1 .. 1); 30 | subtype Short_Indexed_Header_Bytes is Types.Byte_Array (1 .. 2); 31 | subtype Long_Indexed_Header_Bytes is Types.Byte_Array (1 .. 3); 32 | 33 | function To_Bytes is new Ada.Unchecked_Conversion 34 | (Source => Non_Indexed_Header, 35 | Target => Non_Indexed_Header_Bytes); 36 | 37 | function To_Bytes is new Ada.Unchecked_Conversion 38 | (Source => Short_Indexed_Header, 39 | Target => Short_Indexed_Header_Bytes); 40 | 41 | function To_Bytes is new Ada.Unchecked_Conversion 42 | (Source => Long_Indexed_Header, 43 | Target => Long_Indexed_Header_Bytes); 44 | 45 | --------------------- 46 | -- Read_Register -- 47 | --------------------- 48 | 49 | procedure Read_Register (Register_ID : in DW1000.Types.Bits_6; 50 | Sub_Address : in DW1000.Types.Bits_15; 51 | Data : out DW1000.Types.Byte_Array) is 52 | 53 | use type Types.Bits_15; 54 | 55 | begin 56 | if Sub_Address = 0 then 57 | declare 58 | Header : constant Non_Indexed_Header := Non_Indexed_Header' 59 | (Operation => Read, 60 | Sub_Index => Not_Present, 61 | Register_ID => Register_ID); 62 | begin 63 | BSP.Read_Transaction (Header => To_Bytes (Header), 64 | Data => Data); 65 | end; 66 | 67 | elsif Sub_Address < 2**7 then 68 | declare 69 | Header : constant Short_Indexed_Header := Short_Indexed_Header' 70 | (Operation => Read, 71 | Sub_Index => Present, 72 | Register_ID => Register_ID, 73 | Extended_Address => Not_Extended, 74 | Register_Sub_Address => Types.Bits_7 (Sub_Address)); 75 | begin 76 | BSP.Read_Transaction (Header => To_Bytes (Header), 77 | Data => Data); 78 | end; 79 | 80 | else 81 | declare 82 | Header : constant Long_Indexed_Header := Long_Indexed_Header' 83 | (Operation => Read, 84 | Sub_Index => Present, 85 | Register_ID => Register_ID, 86 | Extended_Address => Extended, 87 | Register_Sub_Address_LSB => 88 | Types.Bits_7 (Sub_Address and 16#7F#), 89 | Register_Sub_Address_MSB => Types.Bits_8 (Sub_Address / 2**7)); 90 | begin 91 | BSP.Read_Transaction (Header => To_Bytes (Header), 92 | Data => Data); 93 | end; 94 | 95 | end if; 96 | end Read_Register; 97 | 98 | ---------------------- 99 | -- Write_Register -- 100 | ---------------------- 101 | 102 | procedure Write_Register (Register_ID : in DW1000.Types.Bits_6; 103 | Sub_Address : in DW1000.Types.Bits_15; 104 | Data : in DW1000.Types.Byte_Array) is 105 | 106 | use type Types.Bits_15; 107 | 108 | begin 109 | if Sub_Address = 0 then 110 | declare 111 | Header : constant Non_Indexed_Header := Non_Indexed_Header' 112 | (Operation => Write, 113 | Sub_Index => Not_Present, 114 | Register_ID => Register_ID); 115 | begin 116 | BSP.Write_Transaction (Header => To_Bytes (Header), 117 | Data => Data); 118 | end; 119 | 120 | elsif Sub_Address < 2**7 then 121 | declare 122 | Header : constant Short_Indexed_Header := Short_Indexed_Header' 123 | (Operation => Write, 124 | Sub_Index => Present, 125 | Register_ID => Register_ID, 126 | Extended_Address => Not_Extended, 127 | Register_Sub_Address => Types.Bits_7 (Sub_Address)); 128 | begin 129 | BSP.Write_Transaction (Header => To_Bytes (Header), 130 | Data => Data); 131 | end; 132 | 133 | else 134 | declare 135 | Header : constant Long_Indexed_Header := Long_Indexed_Header' 136 | (Operation => Write, 137 | Sub_Index => Present, 138 | Register_ID => Register_ID, 139 | Extended_Address => Extended, 140 | Register_Sub_Address_LSB => 141 | Types.Bits_7 (Sub_Address and 16#7F#), 142 | Register_Sub_Address_MSB => Types.Bits_8 (Sub_Address / 2**7)); 143 | begin 144 | BSP.Write_Transaction (Header => To_Bytes (Header), 145 | Data => Data); 146 | end; 147 | end if; 148 | end Write_Register; 149 | 150 | end DW1000.Register_Driver; 151 | -------------------------------------------------------------------------------- /examples/echo/echo_example.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Real_Time; use Ada.Real_Time; 24 | with DecaDriver; use DecaDriver; 25 | with DW1000.BSP; 26 | with DW1000.Driver; use DW1000.Driver; 27 | with DW1000.System_Time; use DW1000.System_Time; 28 | with DW1000.Types; 29 | with Tx_Power; 30 | 31 | -- This example continuously waits for a packet to be received, and then 32 | -- re-transmits the received packet after a 500 ms delay. 33 | procedure Echo_Example 34 | with SPARK_Mode, 35 | Global => (Input => Ada.Real_Time.Clock_Time, 36 | In_Out => (DW1000.BSP.Device_State, 37 | DecaDriver.Driver, 38 | DecaDriver.Tx_Complete_Flag)), 39 | Depends => (DecaDriver.Driver =>+ (DW1000.BSP.Device_State, 40 | DecaDriver.Driver), 41 | DW1000.BSP.Device_State =>+ (DecaDriver.Driver), 42 | DecaDriver.Tx_Complete_Flag =>+ (DecaDriver.Driver, 43 | DW1000.BSP.Device_State), 44 | null => Ada.Real_Time.Clock_Time) 45 | is 46 | Rx_Packet : DW1000.Types.Byte_Array (1 .. 127) := (others => 0); 47 | Rx_Packet_Length : DecaDriver.Frame_Length_Number; 48 | Rx_Frame_Info : DecaDriver.Frame_Info_Type; 49 | Rx_Status : DecaDriver.Rx_Status_Type; 50 | Rx_Overrun : Boolean; 51 | 52 | Rx_Timestamp : DW1000.System_Time.Fine_System_Time; 53 | Tx_Timestamp : DW1000.System_Time.Fine_System_Time; 54 | 55 | Tx_Result : DW1000.Driver.Result_Type; 56 | 57 | begin 58 | -- Driver must be initialized once before it is used. 59 | DecaDriver.Driver.Initialize 60 | (Load_Antenna_Delay => True, 61 | Load_XTAL_Trim => True, 62 | Load_UCode_From_ROM => True); 63 | 64 | -- Configure the DW1000 65 | DecaDriver.Driver.Configure 66 | (DecaDriver.Configuration_Type' 67 | (Channel => 1, 68 | PRF => PRF_64MHz, 69 | Tx_Preamble_Length => PLEN_1024, 70 | Rx_PAC => PAC_8, 71 | Tx_Preamble_Code => 9, 72 | Rx_Preamble_Code => 9, 73 | Use_Nonstandard_SFD => False, 74 | Data_Rate => Data_Rate_110k, 75 | PHR_Mode => Standard_Frames, 76 | SFD_Timeout => 1024 + 64 + 1)); 77 | 78 | -- Configure the transmit power for the PRF and channel chosen. 79 | -- We use the reference values for the EVB1000 in this example. 80 | DW1000.Driver.Configure_Tx_Power 81 | (Tx_Power.Manual_Tx_Power_Table (1, PRF_64MHz)); 82 | 83 | -- Enable the LEDs controlled by the DW1000. 84 | DW1000.Driver.Configure_LEDs 85 | (Tx_LED_Enable => True, -- Enable transmit LED 86 | Rx_LED_Enable => True, -- Enable receive LED 87 | Rx_OK_LED_Enable => False, 88 | SFD_LED_Enable => False, 89 | Test_Flash => True); -- Flash both LEDs once 90 | 91 | -- In this example we only want to receive valid packets without errors, 92 | -- so configure the DW1000 to automatically re-enable the receiver when 93 | -- errors occur. The driver will not be notified of receiver errors whilst 94 | -- this is enabled. 95 | DW1000.Driver.Set_Auto_Rx_Reenable (Enable => True); 96 | 97 | DecaDriver.Driver.Start_Rx_Immediate; 98 | 99 | -- Continuously receive packets, and echo them back after a 500 ms delay. 100 | loop 101 | DecaDriver.Driver.Rx_Wait 102 | (Frame => Rx_Packet, 103 | Length => Rx_Packet_Length, 104 | Frame_Info => Rx_Frame_Info, 105 | Status => Rx_Status, 106 | Overrun => Rx_Overrun); 107 | 108 | if Rx_Status = No_Error then 109 | -- Limit frame length 110 | Rx_Packet_Length := Frame_Length_Number'Min (Rx_Packet_Length, Rx_Packet'Length); 111 | 112 | -- Get the timestamp at which the packet was received. 113 | Rx_Timestamp := DecaDriver.Receive_Timestamp (Rx_Frame_Info); 114 | 115 | -- We want to send the packet 0.5 seconds after it was received. 116 | Tx_Timestamp := System_Time_Offset (Rx_Timestamp, 0.5); 117 | 118 | -- Configure the transmitter to transmit the packet 119 | -- at the delayed time. 120 | DW1000.Driver.Set_Delayed_Tx_Rx_Time (Coarse_System_Time (Tx_Timestamp)); 121 | 122 | -- Load the packet into the transmitter 123 | DW1000.Driver.Set_Tx_Data 124 | (Data => Rx_Packet (1 .. Rx_Packet_Length), 125 | Offset => 0); 126 | 127 | -- Tell the driver the length of the packet and its position in the 128 | -- transmit buffer. 129 | DW1000.Driver.Set_Tx_Frame_Length 130 | (Length => Rx_Packet_Length, 131 | Offset => 0); 132 | 133 | -- Transmit the delayed packet, and enable the receiver after the 134 | -- packet is sent. 135 | DecaDriver.Driver.Start_Tx_Delayed 136 | (Rx_After_Tx => True, 137 | Result => Tx_Result); 138 | 139 | -- If the target transmit time has already passed (e.g. because we 140 | -- took too long to configure the transmitter, etc...) then don't 141 | -- transmit and just wait for another packet 142 | if Tx_Result /= Success then 143 | DecaDriver.Driver.Start_Rx_Immediate; 144 | end if; 145 | end if; 146 | end loop; 147 | end Echo_Example; 148 | -------------------------------------------------------------------------------- /src/dw1000-bsp.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Types; 24 | 25 | -- This package defines low-level procedures for interfacing with the DW1000 26 | -- at the physical layer. 27 | -- 28 | -- The body for this package is not included in this project as it is very 29 | -- specific to the target hardware. Therefore, the body for this package 30 | -- must be implemented by the user for their target board. 31 | package DW1000.BSP 32 | with SPARK_Mode => On, 33 | Abstract_State => (Device_State with Synchronous, External), 34 | Initializes => Device_State 35 | is 36 | 37 | procedure Reset_DW1000 38 | with Global => (Output => Device_State), 39 | Depends => (Device_State => null); 40 | -- Resets the DW1000 via the RSTn line. 41 | 42 | procedure Get_Reset_State (State : out DW1000.Types.Bits_1) 43 | with Global => (Input => Device_State), 44 | Depends => (State => Device_State); 45 | -- Read the current state of the RSTn line. 46 | -- 47 | -- The State is 0 when the RSTn line is asserted (low), and 1 when the 48 | -- RSTn line is de-asserted (high). 49 | -- 50 | -- Reading the state of the RSTn is useful when waking up from the SLEEP 51 | -- or DEEPSLEEP states, as the DW1000 asserts the RSTn line whilst it is in 52 | -- the WAKEUP state. RSTn is de-asserted once it has entered the INIT 53 | -- state. 54 | 55 | procedure Acknowledge_DW1000_IRQ 56 | with Global => (In_Out => Device_State); 57 | -- Acknowledge the IRQ request from the DW1000. 58 | -- 59 | -- This should be called from the interrupt handler of the DW1000 IRQ line 60 | -- to acknowledge the interrupt. 61 | -- 62 | --- Failure to call this procedure from the interrupt handler may result in 63 | -- an infinite interrupt loop. 64 | 65 | procedure Disable_DW1000_IRQ 66 | with Global => (In_Out => Device_State); 67 | -- Disables the DW1000 IRQ to prevent the DW1000 interrupt from being 68 | -- triggered. 69 | -- 70 | -- Any IRQs requested after calling this function should be held pending 71 | -- until Enable_DW1000_IRQ is called. 72 | 73 | procedure Enable_DW1000_IRQ 74 | with Global => (In_Out => Device_State); 75 | -- Enables the DW1000 IRQ. 76 | 77 | procedure Use_Slow_SPI_Clock 78 | with Global => (In_Out => Device_State); 79 | -- Switch the BSP to use a slow SPI clock speed (no faster than 3 MHz). 80 | -- 81 | -- The slow SPI clock speed should be used when the DW1000 is in the INIT 82 | -- state. 83 | 84 | procedure Use_Fast_SPI_Clock 85 | with Global => (In_Out => Device_State); 86 | -- Switch the BSP to use a faster SPI clock speed (no faster than 20 MHz). 87 | -- 88 | -- The fast SPI clock speed can be used when the DW1000 has left the INIT 89 | -- state. 90 | 91 | procedure Wakeup (Wait_For_INIT : in Boolean) 92 | with Global => (In_Out => Device_State); 93 | -- Perform the Wakeup sequence. 94 | -- 95 | -- This asserts the WAKEUP condition for a minimum of 500 microseconds. 96 | -- 97 | -- If Wait_For_INIT is True, then this function will then also wait for up 98 | -- to an additional 4 milliseconds for the DW1000 to enter the INIT state. 99 | -- This guarantees that the SPI interface is ready after the return of this 100 | -- procedure. 101 | -- 102 | -- This is a non-blocking function (the Ada 'delay' statement is not used). 103 | -- Instead, a busy wait is be used for the delays. 104 | 105 | procedure Write_Transaction (Header : in DW1000.Types.Byte_Array; 106 | Data : in DW1000.Types.Byte_Array) 107 | with Global => (In_Out => Device_State), 108 | Depends => (Device_State =>+ (Header, Data)), 109 | Pre => (Header'Length in 1 .. 3 110 | and Data'Length > 0); 111 | -- Perform a "write" transaction to the DW1000. 112 | -- 113 | -- This procedure executes a write transaction by performing the following 114 | -- steps:z 115 | -- 1. Select the DW1000 on the SPI bus. 116 | -- 2. Send the transaction header bytes (1 .. 3 bytes) via the SPI 117 | -- interface. 118 | -- 3. Send the transaction data (variable length) to the DW1000 via the 119 | -- SPI interface. 120 | -- 4. Deselect the DW1000 on the SPI bus. 121 | -- 122 | -- Note: This procedure must not block. I.e. the procedure must not use 123 | -- the 'delay until' statement, nor call any protected entries. 124 | 125 | procedure Read_Transaction (Header : in DW1000.Types.Byte_Array; 126 | Data : out DW1000.Types.Byte_Array) 127 | with Global => (In_Out => Device_State), 128 | Depends => (Device_State =>+ (Header, Data), 129 | Data => (Header, Device_State)), 130 | Pre => (Header'Length in 1 .. 3 131 | and Data'Length > 0); 132 | -- Perform a "read" transaction from the DW1000. 133 | -- 134 | -- This procedure executes a write transaction by performing the following 135 | -- steps: 136 | -- 1. Select the DW1000 on the SPI bus. 137 | -- 2. Send the transaction header bytes (1 .. 3 bytes) via the SPI 138 | -- interface. 139 | -- 3. Read the transaction data (variable length) from the DW1000 via 140 | -- the SPI interface, and write the received bytes to the 'Data' byte 141 | -- array. 142 | -- 4. Deselect the DW1000 on the SPI bus. 143 | -- 144 | -- Note: This procedure must not block. I.e. the procedure must not use 145 | -- the 'delay until' statement, nor call any protected entries. 146 | 147 | end DW1000.BSP; 148 | -------------------------------------------------------------------------------- /bsp-examples/evb1000/stm32-nvic.ads: -------------------------------------------------------------------------------- 1 | -- This spec has been automatically generated from STM32F105xx.svd 2 | 3 | pragma Restrictions (No_Elaboration_Code); 4 | pragma Ada_2012; 5 | 6 | with System; 7 | 8 | package STM32.NVIC is 9 | pragma Preelaborate; 10 | 11 | --------------- 12 | -- Registers -- 13 | --------------- 14 | 15 | ------------------- 16 | -- ICTR_Register -- 17 | ------------------- 18 | 19 | subtype ICTR_INTLINESNUM_Field is STM32.UInt4; 20 | 21 | -- Interrupt Controller Type Register 22 | type ICTR_Register is record 23 | -- Read-only. Total number of interrupt lines in groups 24 | INTLINESNUM : ICTR_INTLINESNUM_Field; 25 | -- unspecified 26 | Reserved_4_31 : STM32.UInt28; 27 | end record 28 | with Volatile_Full_Access, Size => 32, 29 | Bit_Order => System.Low_Order_First; 30 | 31 | for ICTR_Register use record 32 | INTLINESNUM at 0 range 0 .. 3; 33 | Reserved_4_31 at 0 range 4 .. 31; 34 | end record; 35 | 36 | ------------------ 37 | -- IPR_Register -- 38 | ------------------ 39 | 40 | -- IPR0_IPR_N array element 41 | subtype IPR0_IPR_N_Element is STM32.Byte; 42 | 43 | -- IPR0_IPR_N array 44 | type IPR0_IPR_N_Field_Array is array (0 .. 3) of IPR0_IPR_N_Element 45 | with Component_Size => 8, Size => 32; 46 | 47 | -- Interrupt Priority Register 48 | type IPR_Register 49 | (As_Array : Boolean := False) 50 | is record 51 | case As_Array is 52 | when False => 53 | -- IPR_N as a value 54 | Val : STM32.Word; 55 | when True => 56 | -- IPR_N as an array 57 | Arr : IPR0_IPR_N_Field_Array; 58 | end case; 59 | end record 60 | with Unchecked_Union, Size => 32, Volatile_Full_Access, 61 | Bit_Order => System.Low_Order_First; 62 | 63 | for IPR_Register use record 64 | Val at 0 range 0 .. 31; 65 | Arr at 0 range 0 .. 31; 66 | end record; 67 | 68 | ------------------- 69 | -- STIR_Register -- 70 | ------------------- 71 | 72 | subtype STIR_INTID_Field is STM32.UInt9; 73 | 74 | -- Software Triggered Interrupt Register 75 | type STIR_Register is record 76 | -- Write-only. interrupt to be triggered 77 | INTID : STIR_INTID_Field := 16#0#; 78 | -- unspecified 79 | Reserved_9_31 : STM32.UInt23 := 16#0#; 80 | end record 81 | with Volatile_Full_Access, Size => 32, 82 | Bit_Order => System.Low_Order_First; 83 | 84 | for STIR_Register use record 85 | INTID at 0 range 0 .. 8; 86 | Reserved_9_31 at 0 range 9 .. 31; 87 | end record; 88 | 89 | ----------------- 90 | -- Peripherals -- 91 | ----------------- 92 | 93 | -- Nested Vectored Interrupt Controller 94 | type NVIC_Peripheral is record 95 | -- Interrupt Controller Type Register 96 | ICTR : ICTR_Register; 97 | -- Interrupt Set-Enable Register 98 | ISER0 : STM32.Word; 99 | -- Interrupt Set-Enable Register 100 | ISER1 : STM32.Word; 101 | -- Interrupt Set-Enable Register 102 | ISER2 : STM32.Word; 103 | -- Interrupt Clear-Enable Register 104 | ICER0 : STM32.Word; 105 | -- Interrupt Clear-Enable Register 106 | ICER1 : STM32.Word; 107 | -- Interrupt Clear-Enable Register 108 | ICER2 : STM32.Word; 109 | -- Interrupt Set-Pending Register 110 | ISPR0 : STM32.Word; 111 | -- Interrupt Set-Pending Register 112 | ISPR1 : STM32.Word; 113 | -- Interrupt Set-Pending Register 114 | ISPR2 : STM32.Word; 115 | -- Interrupt Clear-Pending Register 116 | ICPR0 : STM32.Word; 117 | -- Interrupt Clear-Pending Register 118 | ICPR1 : STM32.Word; 119 | -- Interrupt Clear-Pending Register 120 | ICPR2 : STM32.Word; 121 | -- Interrupt Active Bit Register 122 | IABR0 : STM32.Word; 123 | -- Interrupt Active Bit Register 124 | IABR1 : STM32.Word; 125 | -- Interrupt Active Bit Register 126 | IABR2 : STM32.Word; 127 | -- Interrupt Priority Register 128 | IPR0 : IPR_Register; 129 | -- Interrupt Priority Register 130 | IPR1 : IPR_Register; 131 | -- Interrupt Priority Register 132 | IPR2 : IPR_Register; 133 | -- Interrupt Priority Register 134 | IPR3 : IPR_Register; 135 | -- Interrupt Priority Register 136 | IPR4 : IPR_Register; 137 | -- Interrupt Priority Register 138 | IPR5 : IPR_Register; 139 | -- Interrupt Priority Register 140 | IPR6 : IPR_Register; 141 | -- Interrupt Priority Register 142 | IPR7 : IPR_Register; 143 | -- Interrupt Priority Register 144 | IPR8 : IPR_Register; 145 | -- Interrupt Priority Register 146 | IPR9 : IPR_Register; 147 | -- Interrupt Priority Register 148 | IPR10 : IPR_Register; 149 | -- Interrupt Priority Register 150 | IPR11 : IPR_Register; 151 | -- Interrupt Priority Register 152 | IPR12 : IPR_Register; 153 | -- Interrupt Priority Register 154 | IPR13 : IPR_Register; 155 | -- Interrupt Priority Register 156 | IPR14 : IPR_Register; 157 | -- Interrupt Priority Register 158 | IPR15 : IPR_Register; 159 | -- Interrupt Priority Register 160 | IPR16 : IPR_Register; 161 | -- Software Triggered Interrupt Register 162 | STIR : STIR_Register; 163 | end record 164 | with Volatile; 165 | 166 | for NVIC_Peripheral use record 167 | ICTR at 4 range 0 .. 31; 168 | ISER0 at 256 range 0 .. 31; 169 | ISER1 at 260 range 0 .. 31; 170 | ISER2 at 264 range 0 .. 31; 171 | ICER0 at 384 range 0 .. 31; 172 | ICER1 at 388 range 0 .. 31; 173 | ICER2 at 392 range 0 .. 31; 174 | ISPR0 at 512 range 0 .. 31; 175 | ISPR1 at 516 range 0 .. 31; 176 | ISPR2 at 520 range 0 .. 31; 177 | ICPR0 at 640 range 0 .. 31; 178 | ICPR1 at 644 range 0 .. 31; 179 | ICPR2 at 648 range 0 .. 31; 180 | IABR0 at 768 range 0 .. 31; 181 | IABR1 at 772 range 0 .. 31; 182 | IABR2 at 776 range 0 .. 31; 183 | IPR0 at 1024 range 0 .. 31; 184 | IPR1 at 1028 range 0 .. 31; 185 | IPR2 at 1032 range 0 .. 31; 186 | IPR3 at 1036 range 0 .. 31; 187 | IPR4 at 1040 range 0 .. 31; 188 | IPR5 at 1044 range 0 .. 31; 189 | IPR6 at 1048 range 0 .. 31; 190 | IPR7 at 1052 range 0 .. 31; 191 | IPR8 at 1056 range 0 .. 31; 192 | IPR9 at 1060 range 0 .. 31; 193 | IPR10 at 1064 range 0 .. 31; 194 | IPR11 at 1068 range 0 .. 31; 195 | IPR12 at 1072 range 0 .. 31; 196 | IPR13 at 1076 range 0 .. 31; 197 | IPR14 at 1080 range 0 .. 31; 198 | IPR15 at 1084 range 0 .. 31; 199 | IPR16 at 1088 range 0 .. 31; 200 | STIR at 3840 range 0 .. 31; 201 | end record; 202 | 203 | -- Nested Vectored Interrupt Controller 204 | NVIC_Periph : aliased NVIC_Peripheral 205 | with Import, Address => NVIC_Base; 206 | 207 | end STM32.NVIC; 208 | -------------------------------------------------------------------------------- /src/dw1000-ranging-double_sided.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Types; use DW1000.Types; 24 | 25 | package body DW1000.Ranging.Double_Sided 26 | with SPARK_Mode => On 27 | is 28 | 29 | ------------------------ 30 | -- Compute_Distance -- 31 | ------------------------ 32 | 33 | function Compute_Distance 34 | (Tag_Tx_Poll_Timestamp : in Fine_System_Time; 35 | Anchor_Rx_Poll_Timestamp : in Fine_System_Time; 36 | Anchor_Tx_Resp_Timestamp : in Fine_System_Time; 37 | Tag_Rx_Resp_Timestamp : in Fine_System_Time; 38 | Tag_Tx_Final_Timestamp : in Fine_System_Time; 39 | Anchor_Rx_Final_Timestamp : in Fine_System_Time) return Biased_Distance is 40 | 41 | Max_Time_Of_Flight : constant := 0.000_1; 42 | -- Limit the Time of Flight to a maximum of 0.000_1 seconds (100 us). 43 | -- 44 | -- This prevents overflow during the conversion from time of flight 45 | -- to distance. 46 | -- 47 | -- This limits the maximum computable distance to 2990 meters, but this 48 | -- should be plenty as the operational range of the DW1000 is about 49 | -- 10 times below this limit (300 m). 50 | 51 | type System_Time_Span_Div2 is 52 | delta System_Time_Span'Delta / 2.0 53 | range 0.0 .. System_Time_Span'Last -- need the same range as System_Time_Span 54 | with Small => System_Time_Span'Small / 2.0; 55 | 56 | type System_Time_Span_Div4 is 57 | delta System_Time_Span'Delta / 4.0 58 | range 0.0 .. System_Time_Span'Last / 2.0 59 | with Small => System_Time_Span'Small / 4.0; 60 | 61 | type Large_Meters is 62 | delta Meters'Delta 63 | range 0.0 .. (Max_Time_Of_Flight / System_Time_Span_Div4'Delta) * Speed_Of_Light_In_Vacuum; 64 | -- A fixed-point type with a large enough integer part to store the 65 | -- integer representation of a System_Time_Span_Div4 value. 66 | 67 | T_Roundtrip1 : constant System_Time_Span := Calculate_Span 68 | (Start_Time => Tag_Tx_Poll_Timestamp, 69 | End_Time => Tag_Rx_Resp_Timestamp); 70 | 71 | T_Reply1 : constant System_Time_Span := Calculate_Span 72 | (Start_Time => Anchor_Rx_Poll_Timestamp, 73 | End_Time => Anchor_Tx_Resp_Timestamp); 74 | 75 | T_Roundtrip2 : constant System_Time_Span := Calculate_Span 76 | (Start_Time => Anchor_Tx_Resp_Timestamp, 77 | End_Time => Anchor_Rx_Final_Timestamp); 78 | 79 | T_Reply2 : constant System_Time_Span := Calculate_Span 80 | (Start_Time => Tag_Rx_Resp_Timestamp, 81 | End_Time => Tag_Tx_Final_Timestamp); 82 | 83 | Time_Of_Flight_1 : System_Time_Span_Div2; 84 | Time_Of_Flight_2 : System_Time_Span_Div2; 85 | Time_Of_Flight : System_Time_Span_Div4; 86 | 87 | Diff : System_Time_Span; 88 | Sum : System_Time_Span_Div2; 89 | 90 | Result : Large_Meters; 91 | 92 | begin 93 | if (T_Reply1 > T_Roundtrip1) or (T_Reply2 > T_Roundtrip2) then 94 | Time_Of_Flight := 0.0; 95 | 96 | else 97 | Diff := T_Roundtrip1 - T_Reply1; 98 | Time_Of_Flight_1 := System_Time_Span_Div2 (Diff / System_Time_Span (2.0)); 99 | 100 | Diff := T_Roundtrip2 - T_Reply2; 101 | Time_Of_Flight_2 := System_Time_Span_Div2 (Diff / System_Time_Span (2.0)); 102 | 103 | Sum := Time_Of_Flight_1 + Time_Of_Flight_2; 104 | Time_Of_Flight := System_Time_Span_Div4 (Sum / System_Time_Span_Div4 (2.0)); 105 | end if; 106 | 107 | -- Cap ToF to 0.01 seconds to avoid overflow in the following calculations. 108 | if Time_Of_Flight >= Max_Time_Of_Flight then 109 | Time_Of_Flight := Max_Time_Of_Flight; 110 | end if; 111 | 112 | pragma Assert_And_Cut (Time_Of_Flight <= Max_Time_Of_Flight); 113 | 114 | -- Convert the fixed-point representation to its integer represention 115 | -- (in multiples of the 'Delta). 116 | Result := Large_Meters (Time_Of_Flight / System_Time_Span_Div4 (System_Time_Span_Div4'Delta)); 117 | 118 | -- Multiply the ToF (s) with the speed of light (m/s) to yield 119 | -- the distance (m) in meters. 120 | Result := Result * Large_Meters (Speed_Of_Light_In_Vacuum); 121 | 122 | -- Convert back from integer representation to fixed-point representation. 123 | Result := Result / Large_Meters (1.0 / System_Time_Span_Div4'Delta); 124 | 125 | return Biased_Distance (Result); 126 | end Compute_Distance; 127 | 128 | ------------------------ 129 | -- Compute_Distance -- 130 | ------------------------ 131 | 132 | function Compute_Distance 133 | (Tag_Tx_Poll_Timestamp : in Fine_System_Time; 134 | Anchor_Rx_Poll_Timestamp : in Fine_System_Time; 135 | Anchor_Tx_Resp_Timestamp : in Fine_System_Time; 136 | Tag_Rx_Resp_Timestamp : in Fine_System_Time; 137 | Tag_Tx_Final_Timestamp : in Fine_System_Time; 138 | Anchor_Rx_Final_Timestamp : in Fine_System_Time; 139 | Channel : in DW1000.Driver.Channel_Number; 140 | PRF : in DW1000.Driver.PRF_Type) return Meters is 141 | Distance_With_Bias : Biased_Distance; 142 | 143 | begin 144 | Distance_With_Bias := Compute_Distance 145 | (Tag_Tx_Poll_Timestamp => Tag_Tx_Poll_Timestamp, 146 | Anchor_Rx_Poll_Timestamp => Anchor_Rx_Poll_Timestamp, 147 | Anchor_Tx_Resp_Timestamp => Anchor_Tx_Resp_Timestamp, 148 | Tag_Rx_Resp_Timestamp => Tag_Rx_Resp_Timestamp, 149 | Tag_Tx_Final_Timestamp => Tag_Tx_Final_Timestamp, 150 | Anchor_Rx_Final_Timestamp => Anchor_Rx_Final_Timestamp); 151 | 152 | return Remove_Ranging_Bias 153 | (Measured_Distance => Distance_With_Bias, 154 | Channel => Channel, 155 | PRF => PRF); 156 | end Compute_Distance; 157 | 158 | end DW1000.Ranging.Double_Sided; 159 | -------------------------------------------------------------------------------- /src/dw1000-reception_quality.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Register_Types; use DW1000.Register_Types; 24 | with DW1000.Types; use DW1000.Types; 25 | 26 | -- @summary 27 | -- Utility functions for measuring the quality of received frames. 28 | package DW1000.Reception_Quality 29 | with SPARK_Mode => On 30 | is 31 | 32 | function Adjust_RXPACC (RXPACC : in RX_FINFO_RXPACC_Field; 33 | RXPACC_NOSAT : in RXPACC_NOSAT_Field; 34 | RXBR : in RX_FINFO_RXBR_Field; 35 | SFD_LENGTH : in Bits_8; 36 | Non_Standard_SFD : in Boolean) return RX_FINFO_RXPACC_Field 37 | with Pre => (RXBR /= Reserved 38 | and (if Non_Standard_SFD then SFD_LENGTH in 8 | 16)); 39 | -- Apply the correction to the RXPACC value. 40 | -- 41 | -- The preamble accumulation count (RXPACC) value may include SFD symbols 42 | -- in the count. This function removes SFD symbols from the preamble 43 | -- symbol count in RXPACC, and returns the adjusted RXPACC value. 44 | -- 45 | -- Note: This function does not support user-defined SFD sequences. It only 46 | -- supports the standard and DecaWave defined SFD sequences. The specific 47 | -- SFD sequence used is determined from the RXBR, SFD_LENGTH, and 48 | -- Non_Standard_SFD parameters. 49 | -- 50 | -- @param RXPACC The value of the RXPACC field from the RX_FINFO register. 51 | -- This is the value which is to be adjusted. 52 | -- 53 | -- @param RXPACC_NOSAT The value of the RXPACC_NOSAT register. 54 | -- 55 | -- @param RXBR The value of the RXBR field from the RX_FINFO register. 56 | -- This value determines the data rate of the received frame (110 kbps, 57 | -- 850 kbps, or 6.8 Mbps). 58 | -- 59 | -- @param SFD_LENGTH The value of the SFD_LENGTH field from the USR_SFD 60 | -- register. This value must be 8 or 16 symbols and is used only if 61 | -- Non_Standard_SFD is True. Otherwise, the value does not matter. 62 | -- 63 | -- @param Non_Standard_SFD Determines whether or not the standards-defined 64 | -- SFD sequence is used, or the DecaWave defined sequence is used. 65 | 66 | function Receive_Signal_Power (Use_16MHz_PRF : in Boolean; 67 | RXPACC : in RX_FINFO_RXPACC_Field; 68 | CIR_PWR : in RX_FQUAL_CIR_PWR_Field) 69 | return Float 70 | with Post => Receive_Signal_Power'Result in -142.81 .. -14.43; 71 | -- Compute the estimated receive signal power in dBm. 72 | -- 73 | -- @param Use_16MHz_PRF Set to True if a 16 MHz PRF is used, otherwise set 74 | -- to False to indicate a 64 MHz PRF. 75 | -- 76 | -- @param RXPACC The value of the RXPACC field from the RX_FINFO register. 77 | -- Note that this value should be corrected before calling this function 78 | -- if it is equal to the RXPACC_NOSAT register. See the description for 79 | -- the RXPACC field in the DW1000 User Manual in Section 7.2.18 for more 80 | -- information on correcting the RXPACC. 81 | -- 82 | -- @param CIR_PWR The value of the CIR_PWR field from the RX_FQUAL register 83 | -- 84 | -- @return The estimated receive signal power in dBm. The theoretical range 85 | -- is -166.90 dBm to -14.43 dBm. 86 | 87 | function First_Path_Signal_Power (Use_16MHz_PRF : in Boolean; 88 | F1 : in RX_TIME_FP_AMPL1_Field; 89 | F2 : in RX_FQUAL_FP_AMPL2_Field; 90 | F3 : in RX_FQUAL_FP_AMPL3_Field; 91 | RXPACC : in RX_FINFO_RXPACC_Field) 92 | return Float 93 | with Post => First_Path_Signal_Power'Result in -193.99 .. -17.44; 94 | -- Compute the estimated first path power level in dBm. 95 | -- 96 | -- @param Use_16MHz_PRF Set to True if a 16 MHz PRF is used, otherwise set 97 | -- to False to indicate a 64 MHz PRF. 98 | -- 99 | -- @param F1 The value of the FP_AMPL1 field from the RX_TIME register. 100 | -- 101 | -- @param F2 The value of the FP_AMPL2 field from the RX_FQUAL register. 102 | -- 103 | -- @param F3 The value of the FP_AMPL3 field from the RX_FQUAL register. 104 | -- 105 | -- @param RXPACC The value of the RXPACC field from the RX_FINFO register. 106 | -- Note that this value should be corrected before calling this function 107 | -- if it is equal to the RXPACC_NOSAT register. See the description for 108 | -- the RXPACC field in the DW1000 User Manual in Section 7.2.18 for more 109 | -- information on correcting the RXPACC. 110 | -- 111 | -- @return The estimated first path power in dBm. The theoretical range 112 | -- is -218.07 dBm to -12.67 dBm. 113 | 114 | function Transmitter_Clock_Offset (RXTOFS : in RX_TTCKO_RXTOFS_Field; 115 | RXTTCKI : in RX_TTCKI_RXTTCKI_Field) 116 | return Long_Float 117 | with Post => Transmitter_Clock_Offset'Result in -1.0 .. 1.0; 118 | -- Calculate the clock offset between the receiver's and transmitter's 119 | -- clocks. 120 | -- 121 | -- Since the transmitter and receiver radios are clocked by their own 122 | -- crystals, there can be a slight variation between the crystals' 123 | -- frequencies. This function provides a measure of the offset 124 | -- between this receiver and the remote transmitter clocks. 125 | -- 126 | -- @param RXTOFS The value of the RXTOFS field from the RX_TTCKO register. 127 | -- 128 | -- @param RXTTCKI The value of the RXTTCKI field from the RX_TTCKI 129 | -- register. 130 | -- 131 | -- @return The computed clock offset. A positive value indicates that the 132 | -- transmitter's clock is running faster than the receiver's clock, and 133 | -- a negative value indicates that the transmitter's clock is running 134 | -- slower than the receiver's clock. For example, a value of 7.014E-06 135 | -- indicates that the transmitter is faster by 7 ppm. Likewise, a value 136 | -- of -5.045E-06 indicates that the transmitter's clock is slower by 137 | -- 5 ppm. 138 | 139 | end DW1000.Reception_Quality; 140 | -------------------------------------------------------------------------------- /bsp-examples/dwm1001/nrf52.ads: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2010 - 2018, Nordic Semiconductor ASA 2 | -- 3 | -- All rights reserved. 4 | -- 5 | -- Redistribution and use in source and binary forms, with or without 6 | -- modification, are permitted provided that the following conditions are met: 7 | -- 8 | -- 1. Redistributions of source code must retain the above copyright notice, 9 | -- this list of conditions and the following disclaimer. 10 | -- 11 | -- 2. Redistributions in binary form, except as embedded into a Nordic 12 | -- Semiconductor ASA integrated circuit in a product or a software update for 13 | -- such product, must reproduce the above copyright notice, this list of 14 | -- conditions and the following disclaimer in the documentation and/or other 15 | -- materials provided with the distribution. 16 | -- 17 | -- 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | -- contributors may be used to endorse or promote products derived from this 19 | -- software without specific prior written permission. 20 | -- 21 | -- 4. This software, with or without modification, must only be used with a 22 | -- Nordic Semiconductor ASA integrated circuit. 23 | -- 24 | -- 5. Any software provided in binary form under this license must not be 25 | -- reverse engineered, decompiled, modified and/or disassembled. 26 | -- 27 | -- THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY 28 | -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 | -- WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A 30 | -- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR 31 | -- ASA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 | -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 33 | -- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 34 | -- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 | -- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 | -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | -- 39 | 40 | -- This spec has been automatically generated from nrf52.svd 41 | 42 | pragma Restrictions (No_Elaboration_Code); 43 | pragma Ada_2012; 44 | pragma Style_Checks (Off); 45 | 46 | with Interfaces; use Interfaces; 47 | with System; 48 | 49 | -- nRF52832 reference description for radio MCU with ARM 32-bit Cortex-M4 50 | -- Microcontroller 51 | package NRF52 is 52 | pragma Preelaborate; 53 | 54 | --------------- 55 | -- Base type -- 56 | --------------- 57 | 58 | type UInt32 is new Interfaces.Unsigned_32; 59 | type UInt16 is new Interfaces.Unsigned_16; 60 | type Byte is new Interfaces.Unsigned_8; 61 | type Bit is mod 2**1 62 | with Size => 1; 63 | type UInt2 is mod 2**2 64 | with Size => 2; 65 | type UInt3 is mod 2**3 66 | with Size => 3; 67 | type UInt4 is mod 2**4 68 | with Size => 4; 69 | type UInt5 is mod 2**5 70 | with Size => 5; 71 | type UInt6 is mod 2**6 72 | with Size => 6; 73 | type UInt7 is mod 2**7 74 | with Size => 7; 75 | type UInt9 is mod 2**9 76 | with Size => 9; 77 | type UInt10 is mod 2**10 78 | with Size => 10; 79 | type UInt11 is mod 2**11 80 | with Size => 11; 81 | type UInt12 is mod 2**12 82 | with Size => 12; 83 | type UInt13 is mod 2**13 84 | with Size => 13; 85 | type UInt14 is mod 2**14 86 | with Size => 14; 87 | type UInt15 is mod 2**15 88 | with Size => 15; 89 | type UInt17 is mod 2**17 90 | with Size => 17; 91 | type UInt18 is mod 2**18 92 | with Size => 18; 93 | type UInt19 is mod 2**19 94 | with Size => 19; 95 | type UInt20 is mod 2**20 96 | with Size => 20; 97 | type UInt21 is mod 2**21 98 | with Size => 21; 99 | type UInt22 is mod 2**22 100 | with Size => 22; 101 | type UInt23 is mod 2**23 102 | with Size => 23; 103 | type UInt24 is mod 2**24 104 | with Size => 24; 105 | type UInt25 is mod 2**25 106 | with Size => 25; 107 | type UInt26 is mod 2**26 108 | with Size => 26; 109 | type UInt27 is mod 2**27 110 | with Size => 27; 111 | type UInt28 is mod 2**28 112 | with Size => 28; 113 | type UInt29 is mod 2**29 114 | with Size => 29; 115 | type UInt30 is mod 2**30 116 | with Size => 30; 117 | type UInt31 is mod 2**31 118 | with Size => 31; 119 | 120 | -------------------- 121 | -- Base addresses -- 122 | -------------------- 123 | 124 | FICR_Base : constant System.Address := System'To_Address (16#10000000#); 125 | UICR_Base : constant System.Address := System'To_Address (16#10001000#); 126 | BPROT_Base : constant System.Address := System'To_Address (16#40000000#); 127 | POWER_Base : constant System.Address := System'To_Address (16#40000000#); 128 | CLOCK_Base : constant System.Address := System'To_Address (16#40000000#); 129 | RADIO_Base : constant System.Address := System'To_Address (16#40001000#); 130 | UARTE0_Base : constant System.Address := System'To_Address (16#40002000#); 131 | UART0_Base : constant System.Address := System'To_Address (16#40002000#); 132 | SPIM0_Base : constant System.Address := System'To_Address (16#40003000#); 133 | SPIS0_Base : constant System.Address := System'To_Address (16#40003000#); 134 | TWIM0_Base : constant System.Address := System'To_Address (16#40003000#); 135 | TWIS0_Base : constant System.Address := System'To_Address (16#40003000#); 136 | SPI0_Base : constant System.Address := System'To_Address (16#40003000#); 137 | TWI0_Base : constant System.Address := System'To_Address (16#40003000#); 138 | SPIM1_Base : constant System.Address := System'To_Address (16#40004000#); 139 | SPIS1_Base : constant System.Address := System'To_Address (16#40004000#); 140 | TWIM1_Base : constant System.Address := System'To_Address (16#40004000#); 141 | TWIS1_Base : constant System.Address := System'To_Address (16#40004000#); 142 | SPI1_Base : constant System.Address := System'To_Address (16#40004000#); 143 | TWI1_Base : constant System.Address := System'To_Address (16#40004000#); 144 | NFCT_Base : constant System.Address := System'To_Address (16#40005000#); 145 | GPIOTE_Base : constant System.Address := System'To_Address (16#40006000#); 146 | SAADC_Base : constant System.Address := System'To_Address (16#40007000#); 147 | TIMER0_Base : constant System.Address := System'To_Address (16#40008000#); 148 | TIMER1_Base : constant System.Address := System'To_Address (16#40009000#); 149 | TIMER2_Base : constant System.Address := System'To_Address (16#4000A000#); 150 | RTC0_Base : constant System.Address := System'To_Address (16#4000B000#); 151 | TEMP_Base : constant System.Address := System'To_Address (16#4000C000#); 152 | RNG_Base : constant System.Address := System'To_Address (16#4000D000#); 153 | ECB_Base : constant System.Address := System'To_Address (16#4000E000#); 154 | CCM_Base : constant System.Address := System'To_Address (16#4000F000#); 155 | AAR_Base : constant System.Address := System'To_Address (16#4000F000#); 156 | WDT_Base : constant System.Address := System'To_Address (16#40010000#); 157 | RTC1_Base : constant System.Address := System'To_Address (16#40011000#); 158 | QDEC_Base : constant System.Address := System'To_Address (16#40012000#); 159 | COMP_Base : constant System.Address := System'To_Address (16#40013000#); 160 | LPCOMP_Base : constant System.Address := System'To_Address (16#40013000#); 161 | SWI0_Base : constant System.Address := System'To_Address (16#40014000#); 162 | EGU0_Base : constant System.Address := System'To_Address (16#40014000#); 163 | SWI1_Base : constant System.Address := System'To_Address (16#40015000#); 164 | EGU1_Base : constant System.Address := System'To_Address (16#40015000#); 165 | SWI2_Base : constant System.Address := System'To_Address (16#40016000#); 166 | EGU2_Base : constant System.Address := System'To_Address (16#40016000#); 167 | SWI3_Base : constant System.Address := System'To_Address (16#40017000#); 168 | EGU3_Base : constant System.Address := System'To_Address (16#40017000#); 169 | SWI4_Base : constant System.Address := System'To_Address (16#40018000#); 170 | EGU4_Base : constant System.Address := System'To_Address (16#40018000#); 171 | SWI5_Base : constant System.Address := System'To_Address (16#40019000#); 172 | EGU5_Base : constant System.Address := System'To_Address (16#40019000#); 173 | TIMER3_Base : constant System.Address := System'To_Address (16#4001A000#); 174 | TIMER4_Base : constant System.Address := System'To_Address (16#4001B000#); 175 | PWM0_Base : constant System.Address := System'To_Address (16#4001C000#); 176 | PDM_Base : constant System.Address := System'To_Address (16#4001D000#); 177 | NVMC_Base : constant System.Address := System'To_Address (16#4001E000#); 178 | PPI_Base : constant System.Address := System'To_Address (16#4001F000#); 179 | MWU_Base : constant System.Address := System'To_Address (16#40020000#); 180 | PWM1_Base : constant System.Address := System'To_Address (16#40021000#); 181 | PWM2_Base : constant System.Address := System'To_Address (16#40022000#); 182 | SPIM2_Base : constant System.Address := System'To_Address (16#40023000#); 183 | SPIS2_Base : constant System.Address := System'To_Address (16#40023000#); 184 | SPI2_Base : constant System.Address := System'To_Address (16#40023000#); 185 | RTC2_Base : constant System.Address := System'To_Address (16#40024000#); 186 | I2S_Base : constant System.Address := System'To_Address (16#40025000#); 187 | FPU_Base : constant System.Address := System'To_Address (16#40026000#); 188 | P0_Base : constant System.Address := System'To_Address (16#50000000#); 189 | 190 | end NRF52; 191 | -------------------------------------------------------------------------------- /bsp-examples/evb1000/stm32-exti.ads: -------------------------------------------------------------------------------- 1 | -- This spec has been automatically generated from STM32F105xx.svd 2 | 3 | pragma Restrictions (No_Elaboration_Code); 4 | pragma Ada_2012; 5 | 6 | with System; 7 | 8 | package STM32.EXTI is 9 | pragma Preelaborate; 10 | 11 | --------------- 12 | -- Registers -- 13 | --------------- 14 | 15 | ------------------ 16 | -- IMR_Register -- 17 | ------------------ 18 | 19 | ------------ 20 | -- IMR.MR -- 21 | ------------ 22 | 23 | -- IMR_MR array element 24 | subtype IMR_MR_Element is STM32.Bit; 25 | 26 | -- IMR_MR array 27 | type IMR_MR_Field_Array is array (0 .. 19) of IMR_MR_Element 28 | with Component_Size => 1, Size => 20; 29 | 30 | -- Type definition for IMR_MR 31 | type IMR_MR_Field 32 | (As_Array : Boolean := False) 33 | is record 34 | case As_Array is 35 | when False => 36 | -- MR as a value 37 | Val : STM32.UInt20; 38 | when True => 39 | -- MR as an array 40 | Arr : IMR_MR_Field_Array; 41 | end case; 42 | end record 43 | with Unchecked_Union, Size => 20; 44 | 45 | for IMR_MR_Field use record 46 | Val at 0 range 0 .. 19; 47 | Arr at 0 range 0 .. 19; 48 | end record; 49 | 50 | -- Interrupt mask register (EXTI_IMR) 51 | type IMR_Register is record 52 | -- Interrupt Mask on line 0 53 | MR : IMR_MR_Field := (As_Array => False, Val => 16#0#); 54 | -- unspecified 55 | Reserved_20_31 : STM32.UInt12 := 16#0#; 56 | end record 57 | with Volatile_Full_Access, Size => 32, 58 | Bit_Order => System.Low_Order_First; 59 | 60 | for IMR_Register use record 61 | MR at 0 range 0 .. 19; 62 | Reserved_20_31 at 0 range 20 .. 31; 63 | end record; 64 | 65 | ------------------ 66 | -- EMR_Register -- 67 | ------------------ 68 | 69 | ------------ 70 | -- EMR.MR -- 71 | ------------ 72 | 73 | -- EMR_MR array element 74 | subtype EMR_MR_Element is STM32.Bit; 75 | 76 | -- EMR_MR array 77 | type EMR_MR_Field_Array is array (0 .. 19) of EMR_MR_Element 78 | with Component_Size => 1, Size => 20; 79 | 80 | -- Type definition for EMR_MR 81 | type EMR_MR_Field 82 | (As_Array : Boolean := False) 83 | is record 84 | case As_Array is 85 | when False => 86 | -- MR as a value 87 | Val : STM32.UInt20; 88 | when True => 89 | -- MR as an array 90 | Arr : EMR_MR_Field_Array; 91 | end case; 92 | end record 93 | with Unchecked_Union, Size => 20; 94 | 95 | for EMR_MR_Field use record 96 | Val at 0 range 0 .. 19; 97 | Arr at 0 range 0 .. 19; 98 | end record; 99 | 100 | -- Event mask register (EXTI_EMR) 101 | type EMR_Register is record 102 | -- Event Mask on line 0 103 | MR : EMR_MR_Field := (As_Array => False, Val => 16#0#); 104 | -- unspecified 105 | Reserved_20_31 : STM32.UInt12 := 16#0#; 106 | end record 107 | with Volatile_Full_Access, Size => 32, 108 | Bit_Order => System.Low_Order_First; 109 | 110 | for EMR_Register use record 111 | MR at 0 range 0 .. 19; 112 | Reserved_20_31 at 0 range 20 .. 31; 113 | end record; 114 | 115 | ------------------- 116 | -- RTSR_Register -- 117 | ------------------- 118 | 119 | ------------- 120 | -- RTSR.TR -- 121 | ------------- 122 | 123 | -- RTSR_TR array element 124 | subtype RTSR_TR_Element is STM32.Bit; 125 | 126 | -- RTSR_TR array 127 | type RTSR_TR_Field_Array is array (0 .. 19) of RTSR_TR_Element 128 | with Component_Size => 1, Size => 20; 129 | 130 | -- Type definition for RTSR_TR 131 | type RTSR_TR_Field 132 | (As_Array : Boolean := False) 133 | is record 134 | case As_Array is 135 | when False => 136 | -- TR as a value 137 | Val : STM32.UInt20; 138 | when True => 139 | -- TR as an array 140 | Arr : RTSR_TR_Field_Array; 141 | end case; 142 | end record 143 | with Unchecked_Union, Size => 20; 144 | 145 | for RTSR_TR_Field use record 146 | Val at 0 range 0 .. 19; 147 | Arr at 0 range 0 .. 19; 148 | end record; 149 | 150 | -- Rising Trigger selection register (EXTI_RTSR) 151 | type RTSR_Register is record 152 | -- Rising trigger event configuration of line 0 153 | TR : RTSR_TR_Field := (As_Array => False, Val => 16#0#); 154 | -- unspecified 155 | Reserved_20_31 : STM32.UInt12 := 16#0#; 156 | end record 157 | with Volatile_Full_Access, Size => 32, 158 | Bit_Order => System.Low_Order_First; 159 | 160 | for RTSR_Register use record 161 | TR at 0 range 0 .. 19; 162 | Reserved_20_31 at 0 range 20 .. 31; 163 | end record; 164 | 165 | ------------------- 166 | -- FTSR_Register -- 167 | ------------------- 168 | 169 | ------------- 170 | -- FTSR.TR -- 171 | ------------- 172 | 173 | -- FTSR_TR array element 174 | subtype FTSR_TR_Element is STM32.Bit; 175 | 176 | -- FTSR_TR array 177 | type FTSR_TR_Field_Array is array (0 .. 19) of FTSR_TR_Element 178 | with Component_Size => 1, Size => 20; 179 | 180 | -- Type definition for FTSR_TR 181 | type FTSR_TR_Field 182 | (As_Array : Boolean := False) 183 | is record 184 | case As_Array is 185 | when False => 186 | -- TR as a value 187 | Val : STM32.UInt20; 188 | when True => 189 | -- TR as an array 190 | Arr : FTSR_TR_Field_Array; 191 | end case; 192 | end record 193 | with Unchecked_Union, Size => 20; 194 | 195 | for FTSR_TR_Field use record 196 | Val at 0 range 0 .. 19; 197 | Arr at 0 range 0 .. 19; 198 | end record; 199 | 200 | -- Falling Trigger selection register (EXTI_FTSR) 201 | type FTSR_Register is record 202 | -- Falling trigger event configuration of line 0 203 | TR : FTSR_TR_Field := (As_Array => False, Val => 16#0#); 204 | -- unspecified 205 | Reserved_20_31 : STM32.UInt12 := 16#0#; 206 | end record 207 | with Volatile_Full_Access, Size => 32, 208 | Bit_Order => System.Low_Order_First; 209 | 210 | for FTSR_Register use record 211 | TR at 0 range 0 .. 19; 212 | Reserved_20_31 at 0 range 20 .. 31; 213 | end record; 214 | 215 | -------------------- 216 | -- SWIER_Register -- 217 | -------------------- 218 | 219 | ----------------- 220 | -- SWIER.SWIER -- 221 | ----------------- 222 | 223 | -- SWIER array element 224 | subtype SWIER_Element is STM32.Bit; 225 | 226 | -- SWIER array 227 | type SWIER_Field_Array is array (0 .. 19) of SWIER_Element 228 | with Component_Size => 1, Size => 20; 229 | 230 | -- Type definition for SWIER 231 | type SWIER_Field 232 | (As_Array : Boolean := False) 233 | is record 234 | case As_Array is 235 | when False => 236 | -- SWIER as a value 237 | Val : STM32.UInt20; 238 | when True => 239 | -- SWIER as an array 240 | Arr : SWIER_Field_Array; 241 | end case; 242 | end record 243 | with Unchecked_Union, Size => 20; 244 | 245 | for SWIER_Field use record 246 | Val at 0 range 0 .. 19; 247 | Arr at 0 range 0 .. 19; 248 | end record; 249 | 250 | -- Software interrupt event register (EXTI_SWIER) 251 | type SWIER_Register is record 252 | -- Software Interrupt on line 0 253 | SWIER : SWIER_Field := (As_Array => False, Val => 16#0#); 254 | -- unspecified 255 | Reserved_20_31 : STM32.UInt12 := 16#0#; 256 | end record 257 | with Volatile_Full_Access, Size => 32, 258 | Bit_Order => System.Low_Order_First; 259 | 260 | for SWIER_Register use record 261 | SWIER at 0 range 0 .. 19; 262 | Reserved_20_31 at 0 range 20 .. 31; 263 | end record; 264 | 265 | ----------------- 266 | -- PR_Register -- 267 | ----------------- 268 | 269 | ----------- 270 | -- PR.PR -- 271 | ----------- 272 | 273 | -- PR array element 274 | subtype PR_Element is STM32.Bit; 275 | 276 | -- PR array 277 | type PR_Field_Array is array (0 .. 19) of PR_Element 278 | with Component_Size => 1, Size => 20; 279 | 280 | -- Type definition for PR 281 | type PR_Field 282 | (As_Array : Boolean := False) 283 | is record 284 | case As_Array is 285 | when False => 286 | -- PR as a value 287 | Val : STM32.UInt20; 288 | when True => 289 | -- PR as an array 290 | Arr : PR_Field_Array; 291 | end case; 292 | end record 293 | with Unchecked_Union, Size => 20; 294 | 295 | for PR_Field use record 296 | Val at 0 range 0 .. 19; 297 | Arr at 0 range 0 .. 19; 298 | end record; 299 | 300 | -- Pending register (EXTI_PR) 301 | type PR_Register is record 302 | -- Pending bit 0 303 | PR : PR_Field := (As_Array => False, Val => 16#0#); 304 | -- unspecified 305 | Reserved_20_31 : STM32.UInt12 := 16#0#; 306 | end record 307 | with Volatile_Full_Access, Size => 32, 308 | Bit_Order => System.Low_Order_First; 309 | 310 | for PR_Register use record 311 | PR at 0 range 0 .. 19; 312 | Reserved_20_31 at 0 range 20 .. 31; 313 | end record; 314 | 315 | ----------------- 316 | -- Peripherals -- 317 | ----------------- 318 | 319 | -- EXTI 320 | type EXTI_Peripheral is record 321 | -- Interrupt mask register (EXTI_IMR) 322 | IMR : IMR_Register; 323 | -- Event mask register (EXTI_EMR) 324 | EMR : EMR_Register; 325 | -- Rising Trigger selection register (EXTI_RTSR) 326 | RTSR : RTSR_Register; 327 | -- Falling Trigger selection register (EXTI_FTSR) 328 | FTSR : FTSR_Register; 329 | -- Software interrupt event register (EXTI_SWIER) 330 | SWIER : SWIER_Register; 331 | -- Pending register (EXTI_PR) 332 | PR : PR_Register; 333 | end record 334 | with Volatile; 335 | 336 | for EXTI_Peripheral use record 337 | IMR at 0 range 0 .. 31; 338 | EMR at 4 range 0 .. 31; 339 | RTSR at 8 range 0 .. 31; 340 | FTSR at 12 range 0 .. 31; 341 | SWIER at 16 range 0 .. 31; 342 | PR at 20 range 0 .. 31; 343 | end record; 344 | 345 | -- EXTI 346 | EXTI_Periph : aliased EXTI_Peripheral 347 | with Import, Address => EXTI_Base; 348 | 349 | end STM32.EXTI; 350 | -------------------------------------------------------------------------------- /bsp-examples/evb1000/dw1000-bsp.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 5 | -- of this software and associated documentation files (the "Software"), to 6 | -- deal in the Software without restriction, including without limitation the 7 | -- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | -- sell copies of the Software, and to permit persons to whom the Software is 9 | -- furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 | -- IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Real_Time; use Ada.Real_Time; 24 | with Interfaces; use Interfaces; 25 | with STM32.AFIO; 26 | with STM32.EXTI; 27 | with STM32.GPIO; 28 | with STM32.NVIC; 29 | with STM32.RCC; 30 | with STM32.SPI; 31 | 32 | -- BSP implementation for the EVB1000 eval board. 33 | -- 34 | -- This BSP is designed for a Ravenscar runtime, and makes use of a protected 35 | -- object to satisfy the Synchronous requirement of the abstract Device_State. 36 | -- The use of a protected object protects against races between tasks 37 | -- and the DW1000 IRQ, which both may attempt to access the SPI bus. 38 | -- 39 | -- To adapt this runtime for a ZFP profile (where protected objects are 40 | -- prohibited) another mechanim must be used. For example, interrupts may 41 | -- be disabled during SPI transactions. 42 | package body DW1000.BSP 43 | with SPARK_Mode => Off 44 | is 45 | 46 | procedure Select_Device 47 | is 48 | begin 49 | STM32.GPIO.GPIOA_Periph.BSRR.BR := 50 | STM32.GPIO.BSRR_BR_Field'(As_Array => True, 51 | Arr => (4 => 1, others => 0)); 52 | end Select_Device; 53 | 54 | procedure Deselect_Device 55 | is 56 | begin 57 | STM32.GPIO.GPIOA_Periph.BSRR.BS := 58 | STM32.GPIO.BSRR_BS_Field'(As_Array => True, 59 | Arr => (4 => 1, others => 0)); 60 | end Deselect_Device; 61 | 62 | procedure Reset_DW1000 63 | is 64 | begin 65 | -- Configure RSTn GPIO as output 66 | STM32.GPIO.GPIOA_Periph.CRL.MODE0 := 2#11#; -- Output 50 MHz 67 | STM32.GPIO.GPIOA_Periph.CRL.CNF0 := 2#00#; -- Output push-pull 68 | 69 | -- Drive the RSTn line low 70 | STM32.GPIO.GPIOA_Periph.BSRR.BR := 71 | STM32.GPIO.BSRR_BR_Field'(As_Array => True, 72 | Arr => (1 => 1, others => 0)); 73 | 74 | -- Put the RSTn line to hi-Z 75 | STM32.GPIO.GPIOA_Periph.CRL.MODE0 := 2#00#; -- Input 76 | STM32.GPIO.GPIOA_Periph.CRL.CNF0 := 2#01#; -- Floating input 77 | end Reset_DW1000; 78 | 79 | procedure Get_Reset_State (State : out DW1000.Types.Bits_1) 80 | is 81 | begin 82 | State := DW1000.Types.Bits_1 (STM32.GPIO.GPIOA_Periph.IDR.IDR.Arr(0)); 83 | end Get_Reset_State; 84 | 85 | procedure Acknowledge_DW1000_IRQ 86 | is 87 | begin 88 | STM32.EXTI.EXTI_Periph.PR.PR.Arr (5) := 1; 89 | end Acknowledge_DW1000_IRQ; 90 | 91 | procedure Disable_DW1000_IRQ 92 | is 93 | begin 94 | -- Disable IRQ #25 (EXTI9_5_Interrupt) 95 | STM32.NVIC.NVIC_Periph.ICER0 := 16#0200_0000#; 96 | end Disable_DW1000_IRQ; 97 | 98 | 99 | procedure Enable_DW1000_IRQ 100 | is 101 | begin 102 | -- Enable IRQ #25 (EXTI9_5_Interrupt) 103 | STM32.NVIC.NVIC_Periph.ISER0 := 16#0200_0000#; 104 | end Enable_DW1000_IRQ; 105 | 106 | 107 | procedure Use_Slow_SPI_Clock 108 | is 109 | begin 110 | -- Use /32 prescaler (72 MHz / 32 = 2.25 MHz clock) 111 | STM32.SPI.SPI1_Periph.CR1.BR := 2#100#; 112 | end Use_Slow_SPI_Clock; 113 | 114 | 115 | procedure Use_Fast_SPI_Clock 116 | is 117 | begin 118 | -- Use /4 prescaler (72 MHz / 4 = 18 MHz clock) 119 | STM32.SPI.SPI1_Periph.CR1.BR := 2#001#; 120 | end Use_Fast_SPI_Clock; 121 | 122 | 123 | procedure Assert_WAKEUP 124 | is 125 | begin 126 | STM32.GPIO.GPIOB_Periph.BSRR.BS := 127 | STM32.GPIO.BSRR_BS_Field'(As_Array => True, 128 | Arr => (0 => 1, others => 0)); 129 | end Assert_WAKEUP; 130 | 131 | 132 | procedure Deassert_WAKEUP 133 | is 134 | begin 135 | STM32.GPIO.GPIOB_Periph.BSRR.BR := 136 | STM32.GPIO.BSRR_BR_Field'(As_Array => True, 137 | Arr => (0 => 1, others => 0)); 138 | end Deassert_WAKEUP; 139 | 140 | 141 | procedure Write_Transaction(Header : in DW1000.Types.Byte_Array; 142 | Data : in DW1000.Types.Byte_Array) 143 | is 144 | use type STM32.Bit; 145 | 146 | begin 147 | Disable_DW1000_IRQ; 148 | 149 | Select_Device; 150 | 151 | -- Send header 152 | for I in Header'Range loop 153 | STM32.SPI.SPI1_Periph.DR.DR := Unsigned_16 (Header (I) ); 154 | 155 | loop 156 | exit when STM32.SPI.SPI1_Periph.SR.TXE = 1; 157 | end loop; 158 | end loop; 159 | 160 | -- Send data 161 | for I in Data'Range loop 162 | loop 163 | exit when STM32.SPI.SPI1_Periph.SR.TXE = 1; 164 | end loop; 165 | 166 | STM32.SPI.SPI1_Periph.DR.DR := Unsigned_16 (Data (I) ); 167 | end loop; 168 | 169 | -- Wait for the last byte to finish transmitting. 170 | loop 171 | exit when STM32.SPI.SPI1_Periph.SR.BSY = 0; 172 | end loop; 173 | 174 | Deselect_Device; 175 | 176 | Enable_DW1000_IRQ; 177 | 178 | end Write_Transaction; 179 | 180 | procedure Read_Transaction(Header : in DW1000.Types.Byte_Array; 181 | Data : out DW1000.Types.Byte_Array) 182 | is 183 | use type STM32.Bit; 184 | 185 | begin 186 | Disable_DW1000_IRQ; 187 | 188 | Select_Device; 189 | 190 | -- Send header 191 | for I in Header'Range loop 192 | STM32.SPI.SPI1_Periph.DR.DR := Unsigned_16 (Header (I)); 193 | 194 | loop 195 | exit when STM32.SPI.SPI1_Periph.SR.TXE = 1; 196 | end loop; 197 | end loop; 198 | 199 | loop 200 | exit when STM32.SPI.SPI1_Periph.SR.BSY = 0; 201 | end loop; 202 | 203 | -- Read data 204 | for I in Data'Range loop 205 | -- Send a dummy byte to begin the transfer 206 | STM32.SPI.SPI1_Periph.DR.DR := 16#0000#; 207 | 208 | loop 209 | exit when STM32.SPI.SPI1_Periph.SR.BSY = 0; 210 | end loop; 211 | 212 | Data (I) := Unsigned_8 (STM32.SPI.SPI1_Periph.DR.DR and 16#FF#); 213 | end loop; 214 | 215 | Deselect_Device; 216 | 217 | Enable_DW1000_IRQ; 218 | 219 | end Read_Transaction; 220 | 221 | begin 222 | -- Enable peripheral clocks 223 | STM32.RCC.RCC_Periph.APB2ENR.SPI1EN := 1; 224 | STM32.RCC.RCC_Periph.APB2ENR.AFIOEN := 1; 225 | STM32.RCC.RCC_Periph.APB2ENR.IOPAEN := 1; 226 | STM32.RCC.RCC_Periph.APB2ENR.IOPBEN := 1; 227 | 228 | -- Configure GPIO 229 | STM32.GPIO.GPIOA_Periph.CRL.MODE4 := 2#11#; 230 | STM32.GPIO.GPIOA_Periph.CRL.MODE5 := 2#11#; 231 | STM32.GPIO.GPIOA_Periph.CRL.MODE6 := 2#00#; 232 | STM32.GPIO.GPIOA_Periph.CRL.MODE7 := 2#11#; 233 | STM32.GPIO.GPIOA_Periph.CRL.CNF4 := 2#00#; 234 | STM32.GPIO.GPIOA_Periph.CRL.CNF5 := 2#10#; 235 | STM32.GPIO.GPIOA_Periph.CRL.CNF6 := 2#10#; 236 | STM32.GPIO.GPIOA_Periph.CRL.CNF7 := 2#10#; 237 | 238 | STM32.GPIO.GPIOB_Periph.CRL.MODE0 := 2#11#; 239 | STM32.GPIO.GPIOB_Periph.CRL.CNF0 := 2#00#; 240 | 241 | Deselect_Device; 242 | Deassert_WAKEUP; 243 | 244 | -- Configure SPI 245 | STM32.SPI.SPI1_Periph.CR1 := 246 | STM32.SPI.CR1_Register'(CPHA => 0, 247 | CPOL => 0, 248 | MSTR => 1, 249 | BR => 2#100#, -- /32 prescaler 250 | SPE => 0, 251 | LSBFIRST => 0, -- MSB first 252 | SSI => 1, 253 | SSM => 1, 254 | RXONLY => 0, -- Full duplex 255 | DFF => 0, -- 8-bit data 256 | CRCNEXT => 0, 257 | CRCEN => 0, -- No CRC 258 | BIDIOE => 0, 259 | BIDIMODE => 0, -- Bidirectional 260 | Reserved_16_31 => 0); 261 | STM32.SPI.SPI1_Periph.CRCPR.CRCPOLY := 7; 262 | STM32.SPI.SPI1_Periph.CR1.SPE := 1; 263 | 264 | -- Configure IRQ 265 | STM32.GPIO.GPIOB_Periph.CRL.CNF5 := 2#10#; -- Input with pull-up/down 266 | STM32.GPIO.GPIOB_Periph.CRL.MODE5 := 2#00#; -- Input mode 267 | STM32.GPIO.GPIOB_Periph.BRR.BR.Arr (5) := 1; -- Pull-down 268 | 269 | STM32.AFIO.AFIO_Periph.EXTICR2.EXTI.Arr (5) := 2#0001#; -- GPIOB 270 | 271 | STM32.EXTI.EXTI_Periph.IMR.MR.Arr (5) := 1; -- Enable interrupt 272 | STM32.EXTI.EXTI_Periph.EMR.MR.Arr (5) := 0; 273 | STM32.EXTI.EXTI_Periph.RTSR.TR.Arr (5) := 1; -- Rising edge enabled 274 | STM32.EXTI.EXTI_Periph.FTSR.TR.Arr (5) := 0; -- Falling edge disabled 275 | 276 | -- Device might be sleeping, so assert the WAKEUP pin to wake it. 277 | -- WAKEUP pin must be asserted for at least 500 microseconds. 278 | Assert_WAKEUP; 279 | declare 280 | use type DW1000.Types.Bits_1; 281 | 282 | Now : Ada.Real_Time.Time; 283 | WAKEUP_End : Ada.Real_Time.Time; 284 | RSTn_State : DW1000.Types.Bits_1; 285 | begin 286 | Now := Ada.Real_Time.Clock; 287 | WAKEUP_End := Now + Microseconds (500); 288 | 289 | delay until WAKEUP_End; 290 | 291 | Deassert_WAKEUP; 292 | 293 | -- Reset the device. This only has an effect if the device wasn't asleep. 294 | -- Since if the device was asleep then it is now in the WAKEUP state for 295 | -- approx. 4 ms, and during this state it keeps the RSTn line low anyway. 296 | Reset_DW1000; 297 | 298 | -- Delay for 4 ms to allow the DW1000 to transition into the INIT state. 299 | -- Otherwise, user code may not be able to communicate with the DW1000 300 | -- if elaboration finishes within 4 ms and the user immediately tries to 301 | -- use the DW1000, since it will still be in the WAKEUP state. 302 | Now := Ada.Real_Time.Clock; 303 | WAKEUP_End := Now + Milliseconds (4); 304 | 305 | loop 306 | -- The DW1000 de-asserts the RSTn line when it exits the WAKEUP state 307 | -- which lets us exit early. 308 | Get_Reset_State (RSTn_State); 309 | exit when RSTn_State = 1; 310 | 311 | -- Otherwise, exit anyway after 4 ms. 312 | Now := Ada.Real_Time.Clock; 313 | exit when Now >= WAKEUP_End; 314 | end loop; 315 | end; 316 | 317 | end DW1000.BSP; 318 | -------------------------------------------------------------------------------- /bsp-examples/evb1000/tx_power.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Driver; use DW1000.Driver; 24 | 25 | -- @summary 26 | -- Reference transmit power gain tables for both smart transmit power and 27 | -- manual transmit power modes for the EVB1000 hardware. 28 | -- 29 | -- @description 30 | -- These tables are targeted for the EVB1000 evaluation boards, and can serve 31 | -- as a starting point for calibrating the transmit power for different 32 | -- hardware targets and antennas. 33 | -- 34 | -- Below is an example of using this package to configure the DW1000 35 | -- transmitter to operate in the smart tx power mode, when using UWB channel 36 | -- 4 and a PRF of 64 MHz: 37 | -- 38 | -- DecaDriver.Transmitter.Configure_Tx_Power 39 | -- (Smart_Tx_Power_Table (4, PRF_64MHz)); 40 | -- 41 | -- Note that if the channel number has the type DW1000.Driver.Channel_Number 42 | -- then it is necessary to cast the Channel_Number variable to the type 43 | -- Positive when indexing these tables. An example of this is shown below: 44 | -- 45 | -- DecaDriver.Transmitter.Configure_Tx_Power 46 | -- (Smart_Tx_Power_Table (Positive (Channel), PRF_64MHz)); 47 | -- 48 | -- The values in this package were calculated from Section 7.2.31.4 in the 49 | -- DW1000 User Manual. 50 | package Tx_Power 51 | with SPARK_Mode => On 52 | is 53 | 54 | -- Values for the smart tx power mode 55 | Smart_Tx_Power_Table : constant Tx_Power_Config_Table := 56 | (1 | 2 => (PRF_16MHz => 57 | (Smart_Tx_Power_Enabled => True, 58 | Boost_Normal => (Fine_Gain => 10.5, 59 | Coarse_Gain => Gain_7_5_dB), 60 | Boost_500us => (Fine_Gain => 10.5, 61 | Coarse_Gain => Gain_10_dB), 62 | Boost_250us => (Fine_Gain => 10.5, 63 | Coarse_Gain => Gain_12_5_dB), 64 | Boost_125us => (Fine_Gain => 10.5, 65 | Coarse_Gain => Gain_15_dB)), 66 | 67 | PRF_64MHz => 68 | (Smart_Tx_Power_Enabled => True, 69 | Boost_Normal => (Fine_Gain => 3.5, 70 | Coarse_Gain => Gain_7_5_dB), 71 | Boost_500us => (Fine_Gain => 3.5, 72 | Coarse_Gain => Gain_10_dB), 73 | Boost_250us => (Fine_Gain => 3.5, 74 | Coarse_Gain => Gain_12_5_dB), 75 | Boost_125us => (Fine_Gain => 3.5, 76 | Coarse_Gain => Gain_15_dB))), 77 | 78 | 3 => (PRF_16MHz => 79 | (Smart_Tx_Power_Enabled => True, 80 | Boost_Normal => (Fine_Gain => 7.5, 81 | Coarse_Gain => Gain_7_5_dB), 82 | Boost_500us => (Fine_Gain => 7.5, 83 | Coarse_Gain => Gain_10_dB), 84 | Boost_250us => (Fine_Gain => 7.5, 85 | Coarse_Gain => Gain_12_5_dB), 86 | Boost_125us => (Fine_Gain => 7.5, 87 | Coarse_Gain => Gain_15_dB)), 88 | 89 | PRF_64MHz => 90 | (Smart_Tx_Power_Enabled => True, 91 | Boost_Normal => (Fine_Gain => 5.5, 92 | Coarse_Gain => Gain_5_dB), 93 | Boost_500us => (Fine_Gain => 5.5, 94 | Coarse_Gain => Gain_7_5_dB), 95 | Boost_250us => (Fine_Gain => 5.5, 96 | Coarse_Gain => Gain_10_dB), 97 | Boost_125us => (Fine_Gain => 5.5, 98 | Coarse_Gain => Gain_12_5_dB))), 99 | 100 | 4 => (PRF_16MHz => 101 | (Smart_Tx_Power_Enabled => True, 102 | Boost_Normal => (Fine_Gain => 15.5, 103 | Coarse_Gain => Gain_10_dB), 104 | Boost_500us => (Fine_Gain => 15.5, 105 | Coarse_Gain => Gain_12_5_dB), 106 | Boost_250us => (Fine_Gain => 15.5, 107 | Coarse_Gain => Gain_15_dB), 108 | Boost_125us => (Fine_Gain => 15.5, 109 | Coarse_Gain => Gain_15_dB)), 110 | 111 | PRF_64MHz => 112 | (Smart_Tx_Power_Enabled => True, 113 | Boost_Normal => (Fine_Gain => 13.0, 114 | Coarse_Gain => Gain_5_dB), 115 | Boost_500us => (Fine_Gain => 13.0, 116 | Coarse_Gain => Gain_7_5_dB), 117 | Boost_250us => (Fine_Gain => 13.0, 118 | Coarse_Gain => Gain_10_dB), 119 | Boost_125us => (Fine_Gain => 13.0, 120 | Coarse_Gain => Gain_12_5_dB))), 121 | 122 | 5 | 6 => (PRF_16MHz => 123 | (Smart_Tx_Power_Enabled => True, 124 | Boost_Normal => (Fine_Gain => 4.0, 125 | Coarse_Gain => Gain_10_dB), 126 | Boost_500us => (Fine_Gain => 4.0, 127 | Coarse_Gain => Gain_12_5_dB), 128 | Boost_250us => (Fine_Gain => 4.0, 129 | Coarse_Gain => Gain_15_dB), 130 | Boost_125us => (Fine_Gain => 7.0, 131 | Coarse_Gain => Gain_15_dB)), 132 | 133 | PRF_64MHz => 134 | (Smart_Tx_Power_Enabled => True, 135 | Boost_Normal => (Fine_Gain => 2.5, 136 | Coarse_Gain => Gain_5_dB), 137 | Boost_500us => (Fine_Gain => 2.5, 138 | Coarse_Gain => Gain_7_5_dB), 139 | Boost_250us => (Fine_Gain => 2.5, 140 | Coarse_Gain => Gain_10_dB), 141 | Boost_125us => (Fine_Gain => 2.5, 142 | Coarse_Gain => Gain_12_5_dB))), 143 | 144 | 7 => (PRF_16MHz => 145 | (Smart_Tx_Power_Enabled => True, 146 | Boost_Normal => (Fine_Gain => 9.0, 147 | Coarse_Gain => Gain_5_dB), 148 | Boost_500us => (Fine_Gain => 9.0, 149 | Coarse_Gain => Gain_7_5_dB), 150 | Boost_250us => (Fine_Gain => 9.0, 151 | Coarse_Gain => Gain_10_dB), 152 | Boost_125us => (Fine_Gain => 9.0, 153 | Coarse_Gain => Gain_12_5_dB)), 154 | 155 | PRF_64MHz => 156 | (Smart_Tx_Power_Enabled => True, 157 | Boost_Normal => (Fine_Gain => 8.5, 158 | Coarse_Gain => Gain_0_dB), 159 | Boost_500us => (Fine_Gain => 8.5, 160 | Coarse_Gain => Gain_2_5_dB), 161 | Boost_250us => (Fine_Gain => 8.5, 162 | Coarse_Gain => Gain_7_5_dB), 163 | Boost_125us => (Fine_Gain => 8.5, 164 | Coarse_Gain => Gain_10_dB)))); 165 | 166 | -- Values for the manual tx power mode 167 | Manual_Tx_Power_Table : constant Tx_Power_Config_Table := 168 | (1 | 2 => (PRF_16MHz => 169 | (Smart_Tx_Power_Enabled => False, 170 | Boost_SHR | Boost_PhR => (Fine_Gain => 10.5, 171 | Coarse_Gain => Gain_7_5_dB)), 172 | 173 | PRF_64MHz => 174 | (Smart_Tx_Power_Enabled => False, 175 | Boost_SHR | Boost_PHR => (Fine_Gain => 3.5, 176 | Coarse_Gain => Gain_7_5_dB))), 177 | 178 | 3 => (PRF_16MHz => 179 | (Smart_Tx_Power_Enabled => False, 180 | Boost_SHR | Boost_PHR => (Fine_Gain => 7.5, 181 | Coarse_Gain => Gain_7_5_dB)), 182 | 183 | PRF_64MHz => 184 | (Smart_Tx_Power_Enabled => False, 185 | Boost_SHR | Boost_PHR => (Fine_Gain => 5.5, 186 | Coarse_Gain => Gain_5_dB))), 187 | 188 | 4 => (PRF_16MHz => 189 | (Smart_Tx_Power_Enabled => False, 190 | Boost_SHR | Boost_PHR => (Fine_Gain => 15.5, 191 | Coarse_Gain => Gain_10_dB)), 192 | 193 | PRF_64MHz => 194 | (Smart_Tx_Power_Enabled => False, 195 | Boost_SHR | Boost_PHR => (Fine_Gain => 13.0, 196 | Coarse_Gain => Gain_5_dB))), 197 | 198 | 5 | 6 => (PRF_16MHz => 199 | (Smart_Tx_Power_Enabled => False, 200 | Boost_SHR | Boost_PHR => (Fine_Gain => 4.0, 201 | Coarse_Gain => Gain_10_dB)), 202 | 203 | PRF_64MHz => 204 | (Smart_Tx_Power_Enabled => False, 205 | Boost_SHR | Boost_PHR => (Fine_Gain => 2.5, 206 | Coarse_Gain => Gain_5_dB))), 207 | 208 | 7 => (PRF_16MHz => 209 | (Smart_Tx_Power_Enabled => False, 210 | Boost_SHR | Boost_PHR => (Fine_Gain => 9.0, 211 | Coarse_Gain => Gain_5_dB)), 212 | 213 | PRF_64MHz => 214 | (Smart_Tx_Power_Enabled => False, 215 | Boost_SHR | Boost_PHR => (Fine_Gain => 8.5, 216 | Coarse_Gain => Gain_0_dB)))); 217 | 218 | end Tx_Power; 219 | -------------------------------------------------------------------------------- /bsp-examples/dwm1001/tx_power.ads: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with DW1000.Driver; use DW1000.Driver; 24 | with DW1000.Register_Types; use DW1000.Register_Types; 25 | 26 | -- @summary 27 | -- Reference transmit power gain tables for both smart transmit power and 28 | -- manual transmit power modes for the EVB1000 hardware. 29 | -- 30 | -- @description 31 | -- These tables are targeted for the EVB1000 evaluation boards, and can serve 32 | -- as a starting point for calibrating the transmit power for different 33 | -- hardware targets and antennas. 34 | -- 35 | -- Below is an example of using this package to configure the DW1000 36 | -- transmitter to operate in the smart tx power mode, when using UWB channel 37 | -- 4 and a PRF of 64 MHz: 38 | -- 39 | -- DecaDriver.Transmitter.Configure_Tx_Power 40 | -- (Smart_Tx_Power_Table (4, PRF_64MHz)); 41 | -- 42 | -- Note that if the channel number has the type DW1000.Driver.Channel_Number 43 | -- then it is necessary to cast the Channel_Number variable to the type 44 | -- Positive when indexing these tables. An example of this is shown below: 45 | -- 46 | -- DecaDriver.Transmitter.Configure_Tx_Power 47 | -- (Smart_Tx_Power_Table (Positive (Channel), PRF_64MHz)); 48 | -- 49 | -- The values in this package were calculated from Section 7.2.31.4 in the 50 | -- DW1000 User Manual. 51 | package Tx_Power 52 | with SPARK_Mode => On 53 | is 54 | 55 | -- Values for the smart tx power mode 56 | Smart_Tx_Power_Table : constant Tx_Power_Config_Table := 57 | (1 | 2 => (PRF_16MHz => 58 | (Smart_Tx_Power_Enabled => True, 59 | Boost_Normal => (Fine_Gain => 10.5, 60 | Coarse_Gain => Gain_7_5_dB), 61 | Boost_500us => (Fine_Gain => 10.5, 62 | Coarse_Gain => Gain_10_dB), 63 | Boost_250us => (Fine_Gain => 10.5, 64 | Coarse_Gain => Gain_12_5_dB), 65 | Boost_125us => (Fine_Gain => 10.5, 66 | Coarse_Gain => Gain_15_dB)), 67 | 68 | PRF_64MHz => 69 | (Smart_Tx_Power_Enabled => True, 70 | Boost_Normal => (Fine_Gain => 3.5, 71 | Coarse_Gain => Gain_7_5_dB), 72 | Boost_500us => (Fine_Gain => 3.5, 73 | Coarse_Gain => Gain_10_dB), 74 | Boost_250us => (Fine_Gain => 3.5, 75 | Coarse_Gain => Gain_12_5_dB), 76 | Boost_125us => (Fine_Gain => 3.5, 77 | Coarse_Gain => Gain_15_dB))), 78 | 79 | 3 => (PRF_16MHz => 80 | (Smart_Tx_Power_Enabled => True, 81 | Boost_Normal => (Fine_Gain => 7.5, 82 | Coarse_Gain => Gain_7_5_dB), 83 | Boost_500us => (Fine_Gain => 7.5, 84 | Coarse_Gain => Gain_10_dB), 85 | Boost_250us => (Fine_Gain => 7.5, 86 | Coarse_Gain => Gain_12_5_dB), 87 | Boost_125us => (Fine_Gain => 7.5, 88 | Coarse_Gain => Gain_15_dB)), 89 | 90 | PRF_64MHz => 91 | (Smart_Tx_Power_Enabled => True, 92 | Boost_Normal => (Fine_Gain => 5.5, 93 | Coarse_Gain => Gain_5_dB), 94 | Boost_500us => (Fine_Gain => 5.5, 95 | Coarse_Gain => Gain_7_5_dB), 96 | Boost_250us => (Fine_Gain => 5.5, 97 | Coarse_Gain => Gain_10_dB), 98 | Boost_125us => (Fine_Gain => 5.5, 99 | Coarse_Gain => Gain_12_5_dB))), 100 | 101 | 4 => (PRF_16MHz => 102 | (Smart_Tx_Power_Enabled => True, 103 | Boost_Normal => (Fine_Gain => 15.5, 104 | Coarse_Gain => Gain_10_dB), 105 | Boost_500us => (Fine_Gain => 15.5, 106 | Coarse_Gain => Gain_12_5_dB), 107 | Boost_250us => (Fine_Gain => 15.5, 108 | Coarse_Gain => Gain_15_dB), 109 | Boost_125us => (Fine_Gain => 15.5, 110 | Coarse_Gain => Gain_15_dB)), 111 | 112 | PRF_64MHz => 113 | (Smart_Tx_Power_Enabled => True, 114 | Boost_Normal => (Fine_Gain => 13.0, 115 | Coarse_Gain => Gain_5_dB), 116 | Boost_500us => (Fine_Gain => 13.0, 117 | Coarse_Gain => Gain_7_5_dB), 118 | Boost_250us => (Fine_Gain => 13.0, 119 | Coarse_Gain => Gain_10_dB), 120 | Boost_125us => (Fine_Gain => 13.0, 121 | Coarse_Gain => Gain_12_5_dB))), 122 | 123 | 5 | 6 => (PRF_16MHz => 124 | (Smart_Tx_Power_Enabled => True, 125 | Boost_Normal => (Fine_Gain => 4.0, 126 | Coarse_Gain => Gain_10_dB), 127 | Boost_500us => (Fine_Gain => 4.0, 128 | Coarse_Gain => Gain_12_5_dB), 129 | Boost_250us => (Fine_Gain => 4.0, 130 | Coarse_Gain => Gain_15_dB), 131 | Boost_125us => (Fine_Gain => 7.0, 132 | Coarse_Gain => Gain_15_dB)), 133 | 134 | PRF_64MHz => 135 | (Smart_Tx_Power_Enabled => True, 136 | Boost_Normal => (Fine_Gain => 2.5, 137 | Coarse_Gain => Gain_5_dB), 138 | Boost_500us => (Fine_Gain => 2.5, 139 | Coarse_Gain => Gain_7_5_dB), 140 | Boost_250us => (Fine_Gain => 2.5, 141 | Coarse_Gain => Gain_10_dB), 142 | Boost_125us => (Fine_Gain => 2.5, 143 | Coarse_Gain => Gain_12_5_dB))), 144 | 145 | 7 => (PRF_16MHz => 146 | (Smart_Tx_Power_Enabled => True, 147 | Boost_Normal => (Fine_Gain => 9.0, 148 | Coarse_Gain => Gain_5_dB), 149 | Boost_500us => (Fine_Gain => 9.0, 150 | Coarse_Gain => Gain_7_5_dB), 151 | Boost_250us => (Fine_Gain => 9.0, 152 | Coarse_Gain => Gain_10_dB), 153 | Boost_125us => (Fine_Gain => 9.0, 154 | Coarse_Gain => Gain_12_5_dB)), 155 | 156 | PRF_64MHz => 157 | (Smart_Tx_Power_Enabled => True, 158 | Boost_Normal => (Fine_Gain => 8.5, 159 | Coarse_Gain => Gain_0_dB), 160 | Boost_500us => (Fine_Gain => 8.5, 161 | Coarse_Gain => Gain_2_5_dB), 162 | Boost_250us => (Fine_Gain => 8.5, 163 | Coarse_Gain => Gain_7_5_dB), 164 | Boost_125us => (Fine_Gain => 8.5, 165 | Coarse_Gain => Gain_10_dB)))); 166 | 167 | -- Values for the manual tx power mode 168 | Manual_Tx_Power_Table : constant Tx_Power_Config_Table := 169 | (1 | 2 => (PRF_16MHz => 170 | (Smart_Tx_Power_Enabled => False, 171 | Boost_SHR | Boost_PhR => (Fine_Gain => 10.5, 172 | Coarse_Gain => Gain_7_5_dB)), 173 | 174 | PRF_64MHz => 175 | (Smart_Tx_Power_Enabled => False, 176 | Boost_SHR | Boost_PHR => (Fine_Gain => 3.5, 177 | Coarse_Gain => Gain_7_5_dB))), 178 | 179 | 3 => (PRF_16MHz => 180 | (Smart_Tx_Power_Enabled => False, 181 | Boost_SHR | Boost_PHR => (Fine_Gain => 7.5, 182 | Coarse_Gain => Gain_7_5_dB)), 183 | 184 | PRF_64MHz => 185 | (Smart_Tx_Power_Enabled => False, 186 | Boost_SHR | Boost_PHR => (Fine_Gain => 5.5, 187 | Coarse_Gain => Gain_5_dB))), 188 | 189 | 4 => (PRF_16MHz => 190 | (Smart_Tx_Power_Enabled => False, 191 | Boost_SHR | Boost_PHR => (Fine_Gain => 15.5, 192 | Coarse_Gain => Gain_10_dB)), 193 | 194 | PRF_64MHz => 195 | (Smart_Tx_Power_Enabled => False, 196 | Boost_SHR | Boost_PHR => (Fine_Gain => 13.0, 197 | Coarse_Gain => Gain_5_dB))), 198 | 199 | 5 | 6 => (PRF_16MHz => 200 | (Smart_Tx_Power_Enabled => False, 201 | Boost_SHR | Boost_PHR => (Fine_Gain => 4.0, 202 | Coarse_Gain => Gain_10_dB)), 203 | 204 | PRF_64MHz => 205 | (Smart_Tx_Power_Enabled => False, 206 | Boost_SHR | Boost_PHR => (Fine_Gain => 2.5, 207 | Coarse_Gain => Gain_5_dB))), 208 | 209 | 7 => (PRF_16MHz => 210 | (Smart_Tx_Power_Enabled => False, 211 | Boost_SHR | Boost_PHR => (Fine_Gain => 9.0, 212 | Coarse_Gain => Gain_5_dB)), 213 | 214 | PRF_64MHz => 215 | (Smart_Tx_Power_Enabled => False, 216 | Boost_SHR | Boost_PHR => (Fine_Gain => 8.5, 217 | Coarse_Gain => Gain_0_dB)))); 218 | 219 | end Tx_Power; 220 | -------------------------------------------------------------------------------- /bsp-examples/dwm1001/nrf52-spi.ads: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2010 - 2018, Nordic Semiconductor ASA 2 | -- 3 | -- All rights reserved. 4 | -- 5 | -- Redistribution and use in source and binary forms, with or without 6 | -- modification, are permitted provided that the following conditions are met: 7 | -- 8 | -- 1. Redistributions of source code must retain the above copyright notice, 9 | -- this list of conditions and the following disclaimer. 10 | -- 11 | -- 2. Redistributions in binary form, except as embedded into a Nordic 12 | -- Semiconductor ASA integrated circuit in a product or a software update for 13 | -- such product, must reproduce the above copyright notice, this list of 14 | -- conditions and the following disclaimer in the documentation and/or other 15 | -- materials provided with the distribution. 16 | -- 17 | -- 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 | -- contributors may be used to endorse or promote products derived from this 19 | -- software without specific prior written permission. 20 | -- 21 | -- 4. This software, with or without modification, must only be used with a 22 | -- Nordic Semiconductor ASA integrated circuit. 23 | -- 24 | -- 5. Any software provided in binary form under this license must not be 25 | -- reverse engineered, decompiled, modified and/or disassembled. 26 | -- 27 | -- THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY 28 | -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 29 | -- WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A 30 | -- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR 31 | -- ASA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32 | -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 33 | -- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 34 | -- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 | -- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 | -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | -- 39 | 40 | -- This spec has been automatically generated from nrf52.svd 41 | 42 | pragma Restrictions (No_Elaboration_Code); 43 | pragma Ada_2012; 44 | pragma Style_Checks (Off); 45 | 46 | with System; 47 | 48 | package NRF52.SPI is 49 | pragma Preelaborate; 50 | 51 | --------------- 52 | -- Registers -- 53 | --------------- 54 | 55 | subtype EVENTS_READY_EVENTS_READY_Field is NRF52.Bit; 56 | 57 | -- TXD byte sent and RXD byte received 58 | type EVENTS_READY_Register is record 59 | EVENTS_READY : EVENTS_READY_EVENTS_READY_Field := 16#0#; 60 | -- unspecified 61 | Reserved_1_31 : NRF52.UInt31 := 16#0#; 62 | end record 63 | with Volatile_Full_Access, Object_Size => 32, 64 | Bit_Order => System.Low_Order_First; 65 | 66 | for EVENTS_READY_Register use record 67 | EVENTS_READY at 0 range 0 .. 0; 68 | Reserved_1_31 at 0 range 1 .. 31; 69 | end record; 70 | 71 | -- Write '1' to Enable interrupt for READY event 72 | type INTENSET_READY_Field is 73 | (-- Read: Disabled 74 | Disabled, 75 | -- Read: Enabled 76 | Enabled) 77 | with Size => 1; 78 | for INTENSET_READY_Field use 79 | (Disabled => 0, 80 | Enabled => 1); 81 | 82 | -- Write '1' to Enable interrupt for READY event 83 | type INTENSET_READY_Field_1 is 84 | (-- Reset value for the field 85 | Intenset_Ready_Field_Reset, 86 | -- Enable 87 | Set) 88 | with Size => 1; 89 | for INTENSET_READY_Field_1 use 90 | (Intenset_Ready_Field_Reset => 0, 91 | Set => 1); 92 | 93 | -- Enable interrupt 94 | type INTENSET_Register is record 95 | -- unspecified 96 | Reserved_0_1 : NRF52.UInt2 := 16#0#; 97 | -- Write '1' to Enable interrupt for READY event 98 | READY : INTENSET_READY_Field_1 := Intenset_Ready_Field_Reset; 99 | -- unspecified 100 | Reserved_3_31 : NRF52.UInt29 := 16#0#; 101 | end record 102 | with Volatile_Full_Access, Object_Size => 32, 103 | Bit_Order => System.Low_Order_First; 104 | 105 | for INTENSET_Register use record 106 | Reserved_0_1 at 0 range 0 .. 1; 107 | READY at 0 range 2 .. 2; 108 | Reserved_3_31 at 0 range 3 .. 31; 109 | end record; 110 | 111 | -- Write '1' to Disable interrupt for READY event 112 | type INTENCLR_READY_Field is 113 | (-- Read: Disabled 114 | Disabled, 115 | -- Read: Enabled 116 | Enabled) 117 | with Size => 1; 118 | for INTENCLR_READY_Field use 119 | (Disabled => 0, 120 | Enabled => 1); 121 | 122 | -- Write '1' to Disable interrupt for READY event 123 | type INTENCLR_READY_Field_1 is 124 | (-- Reset value for the field 125 | Intenclr_Ready_Field_Reset, 126 | -- Disable 127 | Clear) 128 | with Size => 1; 129 | for INTENCLR_READY_Field_1 use 130 | (Intenclr_Ready_Field_Reset => 0, 131 | Clear => 1); 132 | 133 | -- Disable interrupt 134 | type INTENCLR_Register is record 135 | -- unspecified 136 | Reserved_0_1 : NRF52.UInt2 := 16#0#; 137 | -- Write '1' to Disable interrupt for READY event 138 | READY : INTENCLR_READY_Field_1 := Intenclr_Ready_Field_Reset; 139 | -- unspecified 140 | Reserved_3_31 : NRF52.UInt29 := 16#0#; 141 | end record 142 | with Volatile_Full_Access, Object_Size => 32, 143 | Bit_Order => System.Low_Order_First; 144 | 145 | for INTENCLR_Register use record 146 | Reserved_0_1 at 0 range 0 .. 1; 147 | READY at 0 range 2 .. 2; 148 | Reserved_3_31 at 0 range 3 .. 31; 149 | end record; 150 | 151 | -- Enable or disable SPI 152 | type ENABLE_ENABLE_Field is 153 | (-- Disable SPI 154 | Disabled, 155 | -- Enable SPI 156 | Enabled) 157 | with Size => 4; 158 | for ENABLE_ENABLE_Field use 159 | (Disabled => 0, 160 | Enabled => 1); 161 | 162 | -- Enable SPI 163 | type ENABLE_Register is record 164 | -- Enable or disable SPI 165 | ENABLE : ENABLE_ENABLE_Field := NRF52.SPI.Disabled; 166 | -- unspecified 167 | Reserved_4_31 : NRF52.UInt28 := 16#0#; 168 | end record 169 | with Volatile_Full_Access, Object_Size => 32, 170 | Bit_Order => System.Low_Order_First; 171 | 172 | for ENABLE_Register use record 173 | ENABLE at 0 range 0 .. 3; 174 | Reserved_4_31 at 0 range 4 .. 31; 175 | end record; 176 | 177 | ---------------------------------- 178 | -- SPI_PSEL cluster's Registers -- 179 | ---------------------------------- 180 | 181 | -- Unspecified 182 | type SPI_PSEL_Cluster is record 183 | -- Pin select for SCK 184 | SCK : aliased NRF52.UInt32; 185 | -- Pin select for MOSI 186 | MOSI : aliased NRF52.UInt32; 187 | -- Pin select for MISO 188 | MISO : aliased NRF52.UInt32; 189 | end record 190 | with Size => 96; 191 | 192 | for SPI_PSEL_Cluster use record 193 | SCK at 16#0# range 0 .. 31; 194 | MOSI at 16#4# range 0 .. 31; 195 | MISO at 16#8# range 0 .. 31; 196 | end record; 197 | 198 | subtype RXD_RXD_Field is NRF52.Byte; 199 | 200 | -- RXD register 201 | type RXD_Register is record 202 | -- Read-only. *** Reading this field has side effects on other resources 203 | -- ***. RX data received. Double buffered 204 | RXD : RXD_RXD_Field; 205 | -- unspecified 206 | Reserved_8_31 : NRF52.UInt24; 207 | end record 208 | with Volatile_Full_Access, Object_Size => 32, 209 | Bit_Order => System.Low_Order_First; 210 | 211 | for RXD_Register use record 212 | RXD at 0 range 0 .. 7; 213 | Reserved_8_31 at 0 range 8 .. 31; 214 | end record; 215 | 216 | subtype TXD_TXD_Field is NRF52.Byte; 217 | 218 | -- TXD register 219 | type TXD_Register is record 220 | -- TX data to send. Double buffered 221 | TXD : TXD_TXD_Field := 16#0#; 222 | -- unspecified 223 | Reserved_8_31 : NRF52.UInt24 := 16#0#; 224 | end record 225 | with Volatile_Full_Access, Object_Size => 32, 226 | Bit_Order => System.Low_Order_First; 227 | 228 | for TXD_Register use record 229 | TXD at 0 range 0 .. 7; 230 | Reserved_8_31 at 0 range 8 .. 31; 231 | end record; 232 | 233 | -- Bit order 234 | type CONFIG_ORDER_Field is 235 | (-- Most significant bit shifted out first 236 | Msbfirst, 237 | -- Least significant bit shifted out first 238 | Lsbfirst) 239 | with Size => 1; 240 | for CONFIG_ORDER_Field use 241 | (Msbfirst => 0, 242 | Lsbfirst => 1); 243 | 244 | -- Serial clock (SCK) phase 245 | type CONFIG_CPHA_Field is 246 | (-- Sample on leading edge of clock, shift serial data on trailing edge 247 | Leading, 248 | -- Sample on trailing edge of clock, shift serial data on leading edge 249 | Trailing) 250 | with Size => 1; 251 | for CONFIG_CPHA_Field use 252 | (Leading => 0, 253 | Trailing => 1); 254 | 255 | -- Serial clock (SCK) polarity 256 | type CONFIG_CPOL_Field is 257 | (-- Active high 258 | Activehigh, 259 | -- Active low 260 | Activelow) 261 | with Size => 1; 262 | for CONFIG_CPOL_Field use 263 | (Activehigh => 0, 264 | Activelow => 1); 265 | 266 | -- Configuration register 267 | type CONFIG_Register is record 268 | -- Bit order 269 | ORDER : CONFIG_ORDER_Field := NRF52.SPI.Msbfirst; 270 | -- Serial clock (SCK) phase 271 | CPHA : CONFIG_CPHA_Field := NRF52.SPI.Leading; 272 | -- Serial clock (SCK) polarity 273 | CPOL : CONFIG_CPOL_Field := NRF52.SPI.Activehigh; 274 | -- unspecified 275 | Reserved_3_31 : NRF52.UInt29 := 16#0#; 276 | end record 277 | with Volatile_Full_Access, Object_Size => 32, 278 | Bit_Order => System.Low_Order_First; 279 | 280 | for CONFIG_Register use record 281 | ORDER at 0 range 0 .. 0; 282 | CPHA at 0 range 1 .. 1; 283 | CPOL at 0 range 2 .. 2; 284 | Reserved_3_31 at 0 range 3 .. 31; 285 | end record; 286 | 287 | ---------------------------------- 288 | -- SPI_PSEL cluster's Registers -- 289 | ---------------------------------- 290 | 291 | ---------------------------------- 292 | -- SPI_PSEL cluster's Registers -- 293 | ---------------------------------- 294 | 295 | ----------------- 296 | -- Peripherals -- 297 | ----------------- 298 | 299 | -- Serial Peripheral Interface 0 300 | type SPI_Peripheral is record 301 | -- TXD byte sent and RXD byte received 302 | EVENTS_READY : aliased EVENTS_READY_Register; 303 | -- Enable interrupt 304 | INTENSET : aliased INTENSET_Register; 305 | -- Disable interrupt 306 | INTENCLR : aliased INTENCLR_Register; 307 | -- Enable SPI 308 | ENABLE : aliased ENABLE_Register; 309 | -- Unspecified 310 | PSEL : aliased SPI_PSEL_Cluster; 311 | -- RXD register 312 | RXD : aliased RXD_Register; 313 | -- TXD register 314 | TXD : aliased TXD_Register; 315 | -- SPI frequency 316 | FREQUENCY : aliased NRF52.UInt32; 317 | -- Configuration register 318 | CONFIG : aliased CONFIG_Register; 319 | end record 320 | with Volatile; 321 | 322 | for SPI_Peripheral use record 323 | EVENTS_READY at 16#108# range 0 .. 31; 324 | INTENSET at 16#304# range 0 .. 31; 325 | INTENCLR at 16#308# range 0 .. 31; 326 | ENABLE at 16#500# range 0 .. 31; 327 | PSEL at 16#508# range 0 .. 95; 328 | RXD at 16#518# range 0 .. 31; 329 | TXD at 16#51C# range 0 .. 31; 330 | FREQUENCY at 16#524# range 0 .. 31; 331 | CONFIG at 16#554# range 0 .. 31; 332 | end record; 333 | 334 | -- Serial Peripheral Interface 0 335 | SPI0_Periph : aliased SPI_Peripheral 336 | with Import, Address => SPI0_Base; 337 | 338 | -- Serial Peripheral Interface 1 339 | SPI1_Periph : aliased SPI_Peripheral 340 | with Import, Address => SPI1_Base; 341 | 342 | -- Serial Peripheral Interface 2 343 | SPI2_Periph : aliased SPI_Peripheral 344 | with Import, Address => SPI2_Base; 345 | 346 | end NRF52.SPI; 347 | -------------------------------------------------------------------------------- /src/dw1000-reception_quality.adb: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright (c) 2016 Daniel King 3 | -- 4 | -- Permission is hereby granted, free of charge, to any person obtaining a 5 | -- copy of this software and associated documentation files (the "Software"), 6 | -- to deal in the Software without restriction, including without limitation 7 | -- the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | -- and/or sell copies of the Software, and to permit persons to whom the 9 | -- Software is furnished to do so, subject to the following conditions: 10 | -- 11 | -- The above copyright notice and this permission notice shall be included in 12 | -- all copies or substantial portions of the Software. 13 | -- 14 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | -- DEALINGS IN THE SOFTWARE. 21 | ------------------------------------------------------------------------------- 22 | 23 | with Ada.Numerics.Generic_Elementary_Functions; 24 | with Interfaces; use Interfaces; 25 | 26 | package body DW1000.Reception_Quality 27 | with SPARK_Mode => On 28 | is 29 | 30 | ------------- 31 | -- Log10 -- 32 | ------------- 33 | 34 | function Log10 (X : in Long_Float) return Long_Float 35 | with Global => null, 36 | Pre => X > 0.0; 37 | -- Compute the base 10 logarithm. 38 | -- 39 | -- This function is a wrapper around the Log function in the package 40 | -- Ada.Numerics.Generic_Elementary_Functions. This is necessary since 41 | -- the Ada.Numerics.Generic_Elementary_Functions package is not in SPARK. 42 | -- 43 | -- The precondition of this function ensures that the Log function in 44 | -- Ada.Numerics.Generic_Elementary_Functions doesn't raise an 45 | -- Argument_Error function. 46 | 47 | function Log10 (X : in Long_Float) return Long_Float 48 | with SPARK_Mode => Off is 49 | 50 | package Long_Float_Math is 51 | new Ada.Numerics.Generic_Elementary_Functions (Long_Float); 52 | begin 53 | return Long_Float_Math.Log (X, 10.0); 54 | end Log10; 55 | 56 | --------------------- 57 | -- Adjust_RXPACC -- 58 | --------------------- 59 | 60 | function Adjust_RXPACC (RXPACC : in RX_FINFO_RXPACC_Field; 61 | RXPACC_NOSAT : in RXPACC_NOSAT_Field; 62 | RXBR : in RX_FINFO_RXBR_Field; 63 | SFD_LENGTH : in Bits_8; 64 | Non_Standard_SFD : in Boolean) return RX_FINFO_RXPACC_Field is 65 | 66 | RXPACC_Adjustment : RX_FINFO_RXPACC_Field; 67 | 68 | begin 69 | if RXPACC_NOSAT_Field (RXPACC) = RXPACC_NOSAT then 70 | if Non_Standard_SFD then 71 | -- DecaWave-defined SFD sequence is used 72 | if RXBR = Data_Rate_110K then 73 | -- 110 kbps data rate. SFD length is always 64 symbols 74 | RXPACC_Adjustment := 82; 75 | else 76 | -- 850 kbps and 6.8 Mbps. SFD length is 8 or 16 symbols 77 | RXPACC_Adjustment := (if SFD_LENGTH = 8 then 10 else 18); 78 | end if; 79 | 80 | else 81 | -- Standard-defined SFD sequence is used 82 | if RXBR = Data_Rate_110K then 83 | -- 110 kbps data rate. SFD length is always 64 symbols 84 | RXPACC_Adjustment := 64; 85 | else 86 | -- 850 kbps and 6.8 Mbps. SFD length is always 8 symbols. 87 | RXPACC_Adjustment := 5; 88 | end if; 89 | end if; 90 | else 91 | -- No adjustment necessary 92 | RXPACC_Adjustment := 0; 93 | end if; 94 | 95 | if RXPACC_Adjustment > RXPACC then 96 | return 0; 97 | else 98 | return RXPACC - RXPACC_Adjustment; 99 | end if; 100 | end Adjust_RXPACC; 101 | 102 | ---------------------------- 103 | -- Receive_Signal_Power -- 104 | ---------------------------- 105 | 106 | function Receive_Signal_Power (Use_16MHz_PRF : in Boolean; 107 | RXPACC : in RX_FINFO_RXPACC_Field; 108 | CIR_PWR : in RX_FQUAL_CIR_PWR_Field) 109 | return Float is 110 | 111 | subtype Numerator_Range is Long_Float 112 | range 2.0**17 .. (2.0**16 - 1.0) * 2.0**17; 113 | 114 | subtype Denominator_Range is Long_Float 115 | range 1.0 .. (2.0**12 - 1.0)**2; 116 | 117 | type CIR_PWR_Range is range 0 .. (2**16 - 1) * 2**17; 118 | 119 | type RXPACC_Sq_Range is range 0 .. RX_FINFO_RXPACC_Field'Last**2; 120 | 121 | N : Numerator_Range; 122 | D : Denominator_Range; 123 | A : Long_Float; 124 | R : Long_Float; 125 | begin 126 | -- Calculation from the DW1000 User Manual for the receive signal power 127 | -- is as follows: 128 | -- _ _ 129 | -- | C * 2**17 | 130 | -- 10 * log10 | --------- | - A 131 | -- |_ N**2 _| 132 | -- 133 | -- Where: 134 | -- * C is the CIR_PWR value 135 | -- * N is the RXPACC value 136 | -- * A is 113.77 for a 16 MHz PRF or 121.74 for a 64 MHz PRF 137 | 138 | if CIR_PWR /= 0 then 139 | N := Long_Float (CIR_PWR_Range (CIR_PWR) * 2**17); 140 | 141 | pragma Assert (N in Numerator_Range); 142 | else 143 | -- Prevent value of 0 for the numerator, otherwise the input 144 | -- to the Log function would be 0, which is not permitted. 145 | N := 2.0**17; 146 | 147 | pragma Assert (N in Numerator_Range); 148 | end if; 149 | 150 | pragma Assert_And_Cut (N in Numerator_Range); 151 | 152 | if RXPACC /= 0 then 153 | D := Long_Float (RXPACC_Sq_Range (RXPACC) * RXPACC_Sq_Range (RXPACC)); 154 | 155 | pragma Assert (D in Denominator_Range); 156 | else 157 | -- Prevent division by zero. 158 | -- In theory, this should never happen. 159 | D := 1.0; 160 | 161 | pragma Assert (D in Denominator_Range); 162 | end if; 163 | 164 | pragma Assert_And_Cut (N in Numerator_Range and D in Denominator_Range); 165 | 166 | R := Log10 (N / D); 167 | 168 | -- The values in this assumption are based on the mathemtical min/max 169 | -- values of Log10 based on the possible range of the input: N / D. 170 | pragma Assume 171 | (R in -2.10699788590519423954821296166977269784955865640566952845 172 | .. 9.933983230052930026417915579094972598428724237632091142242, 173 | "The possible output range of log10, for the possible input range"); 174 | 175 | if Use_16MHz_PRF then 176 | A := 113.77; -- 16 MHz PRF 177 | else 178 | A := 121.74; -- 64 MHz PRF 179 | end if; 180 | 181 | return Float ((10.0 * R) - A); 182 | 183 | end Receive_Signal_Power; 184 | 185 | ------------------------------- 186 | -- First_Path_Signal_Power -- 187 | ------------------------------- 188 | 189 | function First_Path_Signal_Power (Use_16MHz_PRF : in Boolean; 190 | F1 : in RX_TIME_FP_AMPL1_Field; 191 | F2 : in RX_FQUAL_FP_AMPL2_Field; 192 | F3 : in RX_FQUAL_FP_AMPL3_Field; 193 | RXPACC : in RX_FINFO_RXPACC_Field) 194 | return Float is 195 | 196 | subtype F_Range is Long_Float range 0.0 .. (2.0**16 - 1.0)**2; 197 | 198 | subtype Numerator_Range is Long_Float 199 | range 1.0 .. (F_Range'Last * 3.0); 200 | 201 | subtype Denominator_Range is Long_Float 202 | range 1.0 .. (2.0**12 - 1.0)**2; 203 | 204 | type AMPL_Sq_Range is range 0 .. (2**16 - 1)**2; 205 | 206 | type AMPL_Sum_Range is range 0 .. AMPL_Sq_Range'Last * 3; 207 | 208 | type RXPACC_Sq_Range is range 0 .. RX_FINFO_RXPACC_Field'Last**2; 209 | 210 | F_Sum : AMPL_Sum_Range; 211 | N : Numerator_Range; 212 | D : Denominator_Range; 213 | R : Long_Float; 214 | A : Long_Float; 215 | begin 216 | -- Calculation from the DW1000 User Manual for the receive signal power 217 | -- is as follows: 218 | -- _ _ 219 | -- | F1**2 + F2**2 + F3**3 | 220 | -- 10 * log10 | --------------------- | - A 221 | -- |_ N**2 _| 222 | -- 223 | -- Where: 224 | -- * F1 is the FP_AMPL1 field from the RX_TIME register 225 | -- * F2 is the FP_AMPL2 field from the RX_FQUAL register 226 | -- * F3 is the FP_AMPL3 field from the RX_FQUAL register 227 | -- * N is the RXPACC value 228 | -- * A is 113.77 for a 16 MHz PRF or 121.74 for a 64 MHz PRF 229 | 230 | if F1 /= 0 or F2 /= 0 or F3 /= 0 then 231 | F_Sum := (AMPL_Sum_Range (AMPL_Sq_Range (F1) * AMPL_Sq_Range (F1)) 232 | + AMPL_Sum_Range (AMPL_Sq_Range (F2) * AMPL_Sq_Range (F2)) 233 | + AMPL_Sum_Range (AMPL_Sq_Range (F3) * AMPL_Sq_Range (F3))); 234 | 235 | N := Numerator_Range (F_Sum); 236 | 237 | pragma Assert (N in Numerator_Range); 238 | else 239 | N := 1.0; 240 | 241 | pragma Assert (N in Numerator_Range); 242 | end if; 243 | 244 | pragma Assert_And_Cut (N in Numerator_Range); 245 | 246 | if RXPACC /= 0 then 247 | D := Denominator_Range (RXPACC_Sq_Range (RXPACC) * RXPACC_Sq_Range (RXPACC)); 248 | 249 | pragma Assert (D in Denominator_Range); 250 | else 251 | -- Prevent division by zero. 252 | -- In theory, this should never happen. 253 | D := 1.0; 254 | 255 | pragma Assert (D in Denominator_Range); 256 | end if; 257 | 258 | pragma Assert_And_Cut (N in Numerator_Range and D in Denominator_Range); 259 | 260 | R := Log10 (N / D); 261 | 262 | -- The values in this assumption are based on the mathemtical min/max 263 | -- values of Log10 based on the possible range of the input: N / D. 264 | pragma Assume 265 | (R in -7.22450781219257524826183006241290354369191576604307340090 266 | .. 9.632946607530499415568708737557182286738992505552491879931, 267 | "The possible output range of log10, for the possible input range"); 268 | 269 | if Use_16MHz_PRF then 270 | A := 113.77; -- 16 MHz PRF 271 | else 272 | A := 121.74; -- 64 MHz PRF 273 | end if; 274 | 275 | return Float ((10.0 * R) - A); 276 | 277 | end First_Path_Signal_Power; 278 | 279 | -------------------------------- 280 | -- Transmitter_Clock_Offset -- 281 | -------------------------------- 282 | 283 | function Transmitter_Clock_Offset (RXTOFS : in RX_TTCKO_RXTOFS_Field; 284 | RXTTCKI : in RX_TTCKI_RXTTCKI_Field) 285 | return Long_Float is 286 | 287 | Offset : Long_Float; 288 | Interval : Long_Float; 289 | begin 290 | if RXTOFS > -2**18 then 291 | Offset := Long_Float (RXTOFS); 292 | else 293 | -- Special case for the most negative number 294 | -- (closest to negative infinity). 295 | -- Normally, this value would indicate -2.0**18, however, we must 296 | -- constrain the range of Offset to -(2.0**18 - 1.0) so that we can 297 | -- prove that Offset / Interval >= -1.0. 298 | -- 299 | -- If Offset is allowed to have the value -2.0**18 then it is not 300 | -- possible for GNATprove to prove that Offset / Interval >= -1.0 301 | -- (presumably the rounding may cause the proof to fail for -1.0) 302 | 303 | Offset := -2.0**18 + 1.0; 304 | end if; 305 | 306 | pragma Assert_And_Cut (Offset in -2.0**18 + 1.0 .. 2.0**18 - 1.0); 307 | 308 | -- RXTTCKI takes one of two values (Section 7.2.21 of the User Manual): 309 | -- 16#01F00000# for a 16 MHz PRF 310 | -- 16#01FC0000# for a 64 MHz PRF 311 | -- Based on this assumption, we can constrain the potential range of 312 | -- Interval to prove absence of overflow and range errors. 313 | Interval := Long_Float (Bits_32 (RXTTCKI) and 16#01FC0000#); 314 | 315 | pragma Assert_And_Cut 316 | (Offset in -(2.0**18 - 1.0) .. 2.0**18 - 1.0 317 | and then Interval in 0.0 | 2.0**18 .. 16#01FC0000.0# 318 | and then 319 | (if Interval /= 0.0 then Offset > -Interval and Offset < Interval)); 320 | 321 | if Interval /= 0.0 then 322 | pragma Assert (if Offset < 0.0 then Offset / Interval >= -1.0); 323 | pragma Assert (if Offset >= 0.0 then Offset / Interval <= 1.0); 324 | 325 | return Offset / Interval; 326 | else 327 | return 0.0; 328 | end if; 329 | end Transmitter_Clock_Offset; 330 | 331 | end DW1000.Reception_Quality; 332 | --------------------------------------------------------------------------------