Compare commits

...

78 Commits

Author SHA1 Message Date
alan 79f58fce9f Merge remote-tracking branch 'origin/elite_zm/alan' into elite_zm/alan 2019-07-03 15:14:14 +08:00
alan 6472622002 test compile 2019-07-03 15:13:46 +08:00
YiChin 5e3d7d34df bug fix 2019-06-06 15:15:45 +08:00
alan 0535498711 test 2019-06-06 11:45:44 +08:00
YiChin 2e7377787b SPI init has a bug 2019-05-14 13:09:53 +08:00
alan 47d43a27da power on scan test 2019-05-14 11:16:12 +08:00
YiChin b448eeb958 warning fix 2019-05-14 11:11:09 +08:00
alan e0934045d2 power on test 2019-05-14 09:39:37 +08:00
YiChin 2180e7011b GLED 2019-05-13 18:39:44 +08:00
YiChin 8de364dca3 Merge branch 'elite_zm/alan' of https://bitbucket.org/YiChin2018/bioprocc2650 into elite_zm/alan 2019-05-13 18:20:40 +08:00
YiChin dc24e93681 sth idk 2019-05-13 18:10:45 +08:00
alan d60633137a GLED test 2019-05-13 18:09:02 +08:00
YiChin de86c581fc compile pass 2019-05-13 16:57:12 +08:00
alan a2a192b421 value modify 2019-05-13 16:11:40 +08:00
Ta-Shun Su 638c92912c rename global variable 2019-05-13 00:14:59 +08:00
Ta-Shun Su 058ce18fe0 save 2019-05-13 00:09:13 +08:00
Ta-Shun Su 41bf1cc8bf save 2019-05-11 23:49:43 +08:00
Ta-Shun Su d691b7f6f3 headstage_sti 2019-05-11 23:39:01 +08:00
Ta-Shun Su 66b7f82339 headstage_sti 2019-05-11 22:05:19 +08:00
Ta-Shun Su 323ee6ee9f headstage_sti 2019-05-11 20:37:44 +08:00
Ta-Shun Su c057e057f4 save 2019-05-11 19:48:08 +08:00
Ta-Shun Su 122269fd7d save 2019-05-11 19:41:09 +08:00
Ta-Shun Su b4219fe097 master main 2019-05-11 18:24:53 +08:00
Ta-Shun Su 6a11e0ccca add host_test code from host_test/master 2019-05-11 18:16:45 +08:00
Ta-Shun Su 21b6fb3038 save 2019-05-10 00:19:19 +08:00
Ta-Shun Su 1708d32d49 save 2019-05-09 23:50:23 +08:00
Ta-Shun Su aab152ba8c save 2019-05-09 23:37:59 +08:00
Ta-Shun Su 6084a294a5 save 2019-05-09 23:07:55 +08:00
Ta-Shun Su d7555c84dd add document 2019-05-09 22:59:55 +08:00
Ta-Shun Su b562d111b8 add copyright 2019-05-09 22:34:07 +08:00
Ta-Shun Su 787e98c9b1 add idea files 2019-05-09 22:28:48 +08:00
Ta-Shun Su b81a3ff623 add README 2019-05-09 22:23:28 +08:00
YiChin2018 02a8696873 compile pass 2019-05-09 18:56:01 +08:00
YiChin2018 3ac0352ac3 Merge branch 'master' of https://bitbucket.org/YiChin2018/bioprocc2650
# Conflicts:
#	simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_tni.h
2019-05-09 18:17:38 +08:00
YiChin2018 e9b7f2f90b tni compile pass 2019-05-09 18:14:46 +08:00
Ta-Shun Su 6df42ea165 save 2019-05-09 18:12:41 +08:00
Ta-Shun Su ecd558f138 save 2019-05-09 17:59:41 +08:00
Ta-Shun Su 13a7844327 save 2019-05-09 17:44:48 +08:00
Ta-Shun Su c840b10d30 save 2019-05-09 16:57:36 +08:00
Ta-Shun Su 00d1f3539f save 2019-05-09 16:24:34 +08:00
Ta-Shun Su 665b1beaa8 save 2019-05-09 00:25:33 +08:00
Ta-Shun Su c344b5c1d1 save 2019-05-08 16:44:29 +08:00
Ta-Shun Su 2c36d20976 save 2019-05-08 16:41:03 +08:00
Ta-Shun Su eaed2ca15f save 2019-05-08 15:24:52 +08:00
Ta-Shun Su 28f17b7495 save 2019-05-08 13:28:51 +08:00
Ta-Shun Su 98329ba665 save 2019-05-08 12:38:27 +08:00
Ta-Shun Su 4a9bab8012 save 2019-05-08 11:46:47 +08:00
Ta-Shun Su 60dcc8ef7c headstage_notify.h 2019-05-08 11:18:48 +08:00
Ta-Shun Su 1883718a3a reformat 2019-05-08 10:51:31 +08:00
YiChin2018 2eed05577a link pass 2019-05-08 10:46:59 +08:00
YiChin2018 44b4e249bb compile pass 2019-05-08 10:37:17 +08:00
Ta-Shun Su e7ba561277 save 2019-05-08 01:35:24 +08:00
Ta-Shun Su bb12cc95d8 save 2019-05-08 01:25:08 +08:00
Ta-Shun Su e335a53b0c pwm 2019-05-08 01:02:20 +08:00
Ta-Shun Su ff0d0a7e56 save 2019-05-08 00:44:39 +08:00
Ta-Shun Su bb9711ed6a save 2019-05-08 00:31:02 +08:00
Ta-Shun Su 1015afb5d9 Merge branch 'tss/0101' 2019-05-08 00:23:08 +08:00
Ta-Shun Su b8bcf3acc4 save 2019-05-08 00:18:19 +08:00
Ta-Shun Su db0e149192 save 2019-05-08 00:17:37 +08:00
Ta-Shun Su a2d41bd680 save 2019-05-08 00:14:57 +08:00
Ta-Shun Su e485d54102 save 2019-05-08 00:14:04 +08:00
Ta-Shun Su 1eb10e9fe8 save 2019-05-07 23:46:26 +08:00
Ta-Shun Su a9bff07401 add uni 2019-05-07 23:41:37 +08:00
Ta-Shun Su 2ca42aa666 save 2019-05-07 23:34:11 +08:00
Ta-Shun Su ae080d798b save 2019-05-07 23:31:39 +08:00
Ta-Shun Su 2fa4300f8e arm ramp 2019-05-07 23:21:46 +08:00
Ta-Shun Su 70b1bff19a led 2019-05-07 23:13:35 +08:00
Ta-Shun Su bf2b1b1b98 save 2019-05-07 14:57:52 +08:00
Ta-Shun Su a04c82b07d save 2019-05-07 12:45:50 +08:00
Ta-Shun Su 50ec272125 save 2019-05-07 12:35:30 +08:00
Ta-Shun Su c34f7befc0 save 2019-05-07 12:18:47 +08:00
Ta-Shun Su 7531af6a48 save 2019-05-07 12:11:36 +08:00
Ta-Shun Su 1453da201c save 2019-05-07 11:43:32 +08:00
Ta-Shun Su 846e4938e4 save 2019-05-07 09:31:16 +08:00
Ta-Shun Su b55e595a67 led 2019-05-07 01:46:25 +08:00
Ta-Shun Su 69c71112c7 cis 2019-05-07 01:20:00 +08:00
Ta-Shun Su 61f7df84ac save 2019-05-07 00:22:03 +08:00
Ta-Shun Su 0022512f44 refactor simple_peripheral.c 2019-05-06 23:19:16 +08:00
99 changed files with 6523 additions and 5976 deletions
+1 -1
View File
@@ -8,6 +8,6 @@ AllowAllParametersOfDeclarationOnNextLine: false
AllowShortFunctionsOnASingleLine: Empty
BinPackArguments: false
BinPackParameters: false
IndentCaseLabels: false
IndentCaseLabels: true
SortIncludes: true
TabWidth: 4
+7
View File
@@ -0,0 +1,7 @@
<component name="CopyrightManager">
<copyright>
<option name="keyword" value="Copyright .*" />
<option name="notice" value="Copyright (c) &amp;#36;today.year. BioPro. Scientific." />
<option name="myName" value="BioProSci" />
</copyright>
</component>
+7
View File
@@ -0,0 +1,7 @@
<component name="CopyrightManager">
<settings default="BioProSci">
<module2copyright>
<element module="SimplePeripheral" copyright="BioProSci" />
</module2copyright>
</settings>
</component>
+3
View File
@@ -0,0 +1,3 @@
<component name="DependencyValidationManager">
<scope name="HostTest" pattern="file[BioProCC2650]:simplelink/ble_sdk_2_02_02_25/src/examples/host_test/cc26xx/app/master//*" />
</component>
+3
View File
@@ -0,0 +1,3 @@
<component name="DependencyValidationManager">
<scope name="SimplePeripheral" pattern="file[BioProCC2650]:simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage//*" />
</component>
+63
View File
@@ -0,0 +1,63 @@
BioProCC2650
============
BioPro Device
-------------
### Major source code path
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage.h`
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/simple_peripheral.c`
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/main.c`
### Current project
1. Elite
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_tni.h`
2. Neulive 1.2
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_uni.h`
3. Neulive 1.3
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_neulive.h`
4. EliteZM
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_zm.h`
5. NeuliveSTI
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_sti.h`
### Notable source code
* gpio table
`simplelink/ble_sdk_2_02_02_25/src/boards/BOOSTXL_CC2650MA/BOOSTXL_CC2650MA.h`
`simplelink/ble_sdk_2_02_02_25/src/boards/CC2650_LAUNCHXL/CC2650_LAUNCHXL.h`
* characteristic
`simplelink/ble_sdk_2_02_02_25/src/profiles/simple_profile/simple_gatt_profile.h`
`simplelink/ble_sdk_2_02_02_25/src/profiles/simple_profile/cc26xx/simple_gatt_profile.c`
BioPro Control
--------------
major source code path:
`simplelink/ble_sdk_2_02_02_25/src/examples/host_test/cc26xx/app/host_test_app.c`
`simplelink/ble_sdk_2_02_02_25/src/examples/host_test/cc26xx/app/main.c`
-----------------------------------------------
Copyright (c) 2019. BioPro. Scientific.
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/common/cc26xx/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/controller/cc26xx/inc/
-1
View File
@@ -1 +0,0 @@
../tirtos_cc13xx_cc26xx_2_21_01_08/products/cc26xxware_2_24_03_17272/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/hal/src/inc/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/hal/src/target/_common/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/hal/src/target/_common/cc26xx/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/heapmgr/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/examples/host_test/cc26xx/app/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/icall/inc/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/icall/src/inc/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/inc/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/npi/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/osal/src/inc/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/profiles/roles/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/profiles/dev_info/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/profiles/simple_profile/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/rom/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/services/src/saddr/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/components/services/src/sdata/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/
-1
View File
@@ -1 +0,0 @@
../simplelink/ble_sdk_2_02_02_25/src/target/
@@ -1,12 +1,12 @@
XOPTS = -I"C:/ti/xdctools_3_32_00_06_core/packages/" -Dxdc_target_types__=C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/ti/targets/arm/elf/std.h -Dxdc_target_name__=M3
XOPTS = -I"C:/ti/xdctools_3_32_02_25_core/packages/" -Dxdc_target_types__=C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/ti/targets/arm/elf/std.h -Dxdc_target_name__=M3
vpath % C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/ti/sysbios/
vpath %.c C:/ti/xdctools_3_32_00_06_core/packages/
vpath %.c C:/ti/xdctools_3_32_02_25_core/packages/
CCOPTS = --endian=little -mv7M3 --abi=eabi -q -ms --opt_for_speed=0 --program_level_compile -o3 -g --optimize_with_debug -Dti_sysbios_knl_Task_minimizeLatency__D=FALSE -Dti_sysbios_family_arm_cc26xx_Boot_driverlibVersion=2 -Dti_sysbios_knl_Clock_stopCheckNext__D=TRUE -Dti_sysbios_family_arm_m3_Hwi_enableException__D=TRUE -Dti_sysbios_family_arm_m3_Hwi_disablePriority__D=32U -Dti_sysbios_family_arm_m3_Hwi_numSparseInterrupts__D=0U
XDC_ROOT = C:/ti/xdctools_3_32_00_06_core/packages/
XDC_ROOT = C:/ti/xdctools_3_32_02_25_core/packages/
BIOS_ROOT = C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/ti/sysbios/
@@ -22,8 +22,8 @@ CC = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armcl -c $(CCOPTS) -I
ASM = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armcl -c $(CCOPTS) -I C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/include
AR = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armar rq
DEL = C:/ti/xdctools_3_32_00_06_core/packages/../bin/rm -f
CP = C:/ti/xdctools_3_32_00_06_core/packages/../bin/cp -f
DEL = C:/ti/xdctools_3_32_02_25_core/packages/../bin/rm -f
CP = C:/ti/xdctools_3_32_02_25_core/packages/../bin/cp -f
define RM
$(if $(wildcard $1),$(DEL) $1,:)
@@ -16,7 +16,7 @@
# sources were generated) is:
# C:\ti\simplelink\ble_sdk_2_02_02_25\examples\cc2650em\simple_peripheral\ccs\config\src
#
GEN_SRC_DIR ?= ../../config/src
GEN_SRC_DIR ?= ../../../../../ti/simplelink/ble_sdk_2_02_02_25/examples/cc2650em/simple_peripheral/ccs/config/src
ifeq (,$(wildcard $(GEN_SRC_DIR)))
$(error "ERROR: GEN_SRC_DIR must be set to the directory containing the generated sources")
@@ -1,12 +1,12 @@
XOPTS = -I"C:/ti/xdctools_3_32_02_25_core/packages/" -Dxdc_target_types__=C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/ti/targets/arm/elf/std.h -Dxdc_target_name__=M3
XOPTS = -I"C:/ti/xdctools_3_32_00_06_core/packages/" -Dxdc_target_types__=C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/ti/targets/arm/elf/std.h -Dxdc_target_name__=M3
vpath % C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/ti/sysbios/
vpath %.c C:/ti/xdctools_3_32_02_25_core/packages/
vpath %.c C:/ti/xdctools_3_32_00_06_core/packages/
CCOPTS = --endian=little -mv7M3 --abi=eabi -q -ms --opt_for_speed=0 --program_level_compile -o3 -g --optimize_with_debug -Dti_sysbios_knl_Task_minimizeLatency__D=FALSE -Dti_sysbios_family_arm_cc26xx_Boot_driverlibVersion=2 -Dti_sysbios_knl_Clock_stopCheckNext__D=TRUE -Dti_sysbios_family_arm_m3_Hwi_enableException__D=TRUE -Dti_sysbios_family_arm_m3_Hwi_disablePriority__D=32U -Dti_sysbios_family_arm_m3_Hwi_numSparseInterrupts__D=0U
XDC_ROOT = C:/ti/xdctools_3_32_02_25_core/packages/
XDC_ROOT = C:/ti/xdctools_3_32_00_06_core/packages/
BIOS_ROOT = C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/ti/sysbios/
@@ -22,8 +22,8 @@ CC = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armcl -c $(CCOPTS) -I
ASM = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armcl -c $(CCOPTS) -I C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/include
AR = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armar rq
DEL = C:/ti/xdctools_3_32_02_25_core/packages/../bin/rm -f
CP = C:/ti/xdctools_3_32_02_25_core/packages/../bin/cp -f
DEL = C:/ti/xdctools_3_32_00_06_core/packages/../bin/rm -f
CP = C:/ti/xdctools_3_32_00_06_core/packages/../bin/cp -f
define RM
$(if $(wildcard $1),$(DEL) $1,:)
@@ -1,9 +1,10 @@
/*
** Stack Frontier Generator 1.1.0 (2016-03-28 14:11:07.308000)
** Stack Frontier Generator 1.1.0 (2019-05-13 17:33:59.404000)
**
** WARNING - Auto-generated file. Modifications could be lost!
*/
--define=ICALL_STACK0_ADDR=0xe001
--define=ICALL_STACK0_START=0xe000
--define=ICALL_RAM0_START=0x20004368
--define=ICALL_STACK0_ADDR=0xf001
--define=ICALL_STACK0_START=0xf000
--define=ICALL_RAM0_START=0x20004320
@@ -1,9 +1,10 @@
/*
** Stack Frontier Generator 1.1.0 (2016-03-28 14:11:07.308000)
** Stack Frontier Generator 1.1.0 (2019-05-13 17:33:59.404000)
**
** WARNING - Auto-generated file. Modifications could be lost!
*/
--define=ICALL_RAM0_START=0x20004368
--define=ICALL_STACK0_START=0xe000
--define=ICALL_STACK0_ADDR=0xe001
--define=ICALL_RAM0_START=0x20004320
--define=ICALL_STACK0_START=0xf000
--define=ICALL_STACK0_ADDR=0xf001
@@ -4,5 +4,5 @@
*/
"C:\ti\simplelink\ble_sdk_2_02_02_25\blelib\host\host_pxxx.a"
"C:\ti\simplelink\ble_sdk_2_02_02_25\blelib\ctrl\cc2640\cc2640_ctrl_pxxx_ext.a"
"C:\ti\simplelink\ble_sdk_2_02_02_25\blelib\hci_tl\cc26xx\cc26xx_hci_tl_none_v41_v42.a"
"C:\ti\simplelink\ble_sdk_2_02_02_25\blelib\ctrl\cc2640\cc2640_ctrl_pxxx.a"
"C:\ti\simplelink\ble_sdk_2_02_02_25\blelib\hci_tl\cc26xx\cc26xx_hci_tl_none.a"
@@ -16,7 +16,7 @@
# sources were generated) is:
# C:\ti\simplelink\ble_sdk_2_02_02_25\examples\cc2650lp\simple_peripheral\ccs\config\src
#
GEN_SRC_DIR ?= ../../config/src
GEN_SRC_DIR ?= ../../../../../ti/simplelink/ble_sdk_2_02_02_25/examples/cc2650lp/simple_peripheral/ccs/config/src
ifeq (,$(wildcard $(GEN_SRC_DIR)))
$(error "ERROR: GEN_SRC_DIR must be set to the directory containing the generated sources")
@@ -16,11 +16,11 @@ BIOS_INC = -I"C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/pa
TARGET_INC = -I"C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/"
INCS = $(BIOS_INC) $(TARGET_INC) --include_path="C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.3.LTS/include" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/icall/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/roles/cc26xx" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/roles" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/dev_info" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/simple_profile/cc26xx" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/simple_profile" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/common/cc26xx" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/heapmgr" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/controller/cc26xx/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/hal/src/target/_common" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/target" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/hal/src/target/_common/cc26xx" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/hal/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/osal/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/services/src/sdata" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/services/src/saddr" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/icall/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/rom" --include_path="C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/cc26xxware_2_24_03_17272" -IC:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/
INCS = $(BIOS_INC) $(TARGET_INC) --include_path="C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/include" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/npi" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/icall/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/roles/cc26xx" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/roles" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/dev_info" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/simple_profile/cc26xx" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/profiles/simple_profile" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/common/cc26xx" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/heapmgr" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/controller/cc26xx/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/hal/src/target/_common" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/target" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/hal/src/target/_common/cc26xx" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/hal/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/osal/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/services/src/sdata" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/services/src/saddr" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/components/icall/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/inc" --include_path="C:/ti/simplelink/ble_sdk_2_02_02_25/src/rom" --include_path="C:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/cc26xxware_2_24_03_17272" -IC:/ti/tirtos_cc13xx_cc26xx_2_21_01_08/products/bios_6_46_01_38/packages/
CC = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.3.LTS/bin/armcl -c $(CCOPTS) -I C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.3.LTS/include
ASM = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.3.LTS/bin/armcl -c $(CCOPTS) -I C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.3.LTS/include
AR = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.3.LTS/bin/armar rq
CC = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armcl -c $(CCOPTS) -I C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/include
ASM = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armcl -c $(CCOPTS) -I C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/include
AR = C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.4.LTS/bin/armar rq
DEL = C:/ti/xdctools_3_32_00_06_core/packages/../bin/rm -f
CP = C:/ti/xdctools_3_32_00_06_core/packages/../bin/cp -f
@@ -36,10 +36,11 @@
* CC2650 Booster Pack.
*/
/*
* ====================== Includes ============================================
*/
// clang-format off
#include <xdc/std.h>
#include <xdc/runtime/System.h>
@@ -56,6 +57,7 @@
#include <inc/hw_ints.h>
#include <driverlib/ioc.h>
#include <driverlib/udma.h>
// clang-format on
#include "Board.h"
@@ -65,7 +67,7 @@
* settings for this board.
* When a pin is allocated and then de-allocated, it will revert to the state
* configured in this table.
*/
*/
/* Place into subsections to allow the TI linker to remove items properly */
#if defined(__TI_COMPILER_VERSION__)
@@ -73,19 +75,20 @@
#pragma DATA_SECTION(PINCC26XX_hwAttrs, ".const:PINCC26XX_hwAttrs")
#endif
const PIN_Config BoardGpioInitTable[] = {
Board_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
Board_GLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
Board_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN, /* UART RX */
Board_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL, /* UART TX */
Board_SRDY | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL, /* SRDY */
Board_MRDY | PIN_INPUT_EN | PIN_PULLDOWN, /* MRDY */
PIN_TERMINATE
};
const PIN_Config BoardGpioInitTable[] = { //
Board_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
Board_GLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* LED initially off */
Board_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN, /* UART RX */
Board_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL, /* UART TX */
Board_SRDY | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL, /* SRDY */
Board_MRDY | PIN_INPUT_EN | PIN_PULLDOWN, /* MRDY */
PIN_TERMINATE};
const PINCC26XX_HWAttrs PINCC26XX_hwAttrs = {
//
.intPriority = ~0,
.swiPriority = 0
//
};
/*============================================================================*/
@@ -96,13 +99,14 @@ const PINCC26XX_HWAttrs PINCC26XX_hwAttrs = {
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_SECTION(PowerCC26XX_config, ".const:PowerCC26XX_config")
#endif
const PowerCC26XX_Config PowerCC26XX_config = {
.policyInitFxn = NULL,
.policyFxn = &PowerCC26XX_standbyPolicy,
.calibrateFxn = &PowerCC26XX_calibrate,
.enablePolicy = TRUE,
.calibrateRCOSC_LF = TRUE,
.calibrateRCOSC_HF = TRUE,
.policyInitFxn = NULL,
.policyFxn = &PowerCC26XX_standbyPolicy,
.calibrateFxn = &PowerCC26XX_calibrate,
.enablePolicy = TRUE,
.calibrateRCOSC_LF = TRUE,
.calibrateRCOSC_HF = TRUE,
};
/*
* ============================= Power end ====================================
@@ -126,28 +130,32 @@ UARTCC26XX_Object uartCC26XXObjects[BOOSTXL_CC2650MA_UARTCOUNT];
/* UART hardware parameter structure, also used to assign UART pins */
const UARTCC26XX_HWAttrsV2 uartCC26XXHWAttrs[BOOSTXL_CC2650MA_UARTCOUNT] = {
//
{
.baseAddr = UART0_BASE,
.powerMngrId = PowerCC26XX_PERIPH_UART0,
.intNum = INT_UART0_COMB,
.intPriority = ~0,
.swiPriority = 0,
.txPin = Board_UART_TX,
.rxPin = Board_UART_RX,
.ctsPin = PIN_UNASSIGNED,
.rtsPin = PIN_UNASSIGNED
.baseAddr = UART0_BASE,
.powerMngrId = PowerCC26XX_PERIPH_UART0,
.intNum = INT_UART0_COMB,
.intPriority = ~0,
.swiPriority = 0,
.txPin = Board_UART_TX,
.rxPin = Board_UART_RX,
.ctsPin = PIN_UNASSIGNED,
.rtsPin = PIN_UNASSIGNED
//
}
//
};
/* UART configuration structure */
const UART_Config UART_config[] = {
const UART_Config UART_config[] = { //
{
//
.fxnTablePtr = &UARTCC26XX_fxnTable,
.object = &uartCC26XXObjects[0],
.hwAttrs = &uartCC26XXHWAttrs[0]
//
},
{NULL, NULL, NULL}
};
{NULL, NULL, NULL}};
/*
* ============================= UART end =====================================
*/
@@ -169,22 +177,27 @@ UDMACC26XX_Object udmaObjects[BOOSTXL_CC2650MA_UDMACOUNT];
/* UDMA configuration structure */
const UDMACC26XX_HWAttrs udmaHWAttrs[BOOSTXL_CC2650MA_UDMACOUNT] = {
//
{
//
.baseAddr = UDMA0_BASE,
.powerMngrId = PowerCC26XX_PERIPH_UDMA,
.intNum = INT_DMA_ERR,
.intPriority = ~0
//
}
//
};
/* UDMA configuration structure */
const UDMACC26XX_Config UDMACC26XX_config[] = {
const UDMACC26XX_Config UDMACC26XX_config[] = { //
{
.object = &udmaObjects[0],
.hwAttrs = &udmaHWAttrs[0]
//
.object = &udmaObjects[0],
.hwAttrs = &udmaHWAttrs[0]
//
},
{NULL, NULL}
};
{NULL, NULL}};
/*
* ============================= UDMA end =====================================
*/
@@ -206,40 +219,62 @@ SPICC26XXDMA_Object spiCC26XXDMAObjects[BOOSTXL_CC2650MA_SPICOUNT];
/* SPI configuration structure, describing which pins are to be used */
const SPICC26XXDMA_HWAttrsV1 spiCC26XXDMAHWAttrs[BOOSTXL_CC2650MA_UDMACOUNT] = {
//
{
.baseAddr = SSI0_BASE,
.intNum = INT_SSI0_COMB,
.intPriority = ~0,
.swiPriority = 0,
.powerMngrId = PowerCC26XX_PERIPH_SSI0,
.defaultTxBufValue = 0,
.rxChannelBitMask = 1<<UDMA_CHAN_SSI0_RX,
.txChannelBitMask = 1<<UDMA_CHAN_SSI0_TX,
.mosiPin = Board_SPI0_MOSI,
.misoPin = Board_SPI0_MISO,
.clkPin = Board_SPI0_CLK,
.csnPin = Board_SPI0_CS
//
.baseAddr = SSI0_BASE,
.intNum = INT_SSI0_COMB,
.intPriority = ~0,
.swiPriority = 0,
.powerMngrId = PowerCC26XX_PERIPH_SSI0,
.defaultTxBufValue = 0,
.rxChannelBitMask = 1 << UDMA_CHAN_SSI0_RX,
.txChannelBitMask = 1 << UDMA_CHAN_SSI0_TX,
.mosiPin = Board_SPI0_MOSI,
.misoPin = Board_SPI0_MISO,
.clkPin = Board_SPI0_CLK,
.csnPin = Board_SPI0_CS
//
},
#ifdef HEADSTAGE_SPI_USE_2
{
//
.baseAddr = SSI1_BASE,
.intNum = INT_SSI1_COMB,
.intPriority = ~0,
.swiPriority = 0,
.powerMngrId = PowerCC26XX_PERIPH_SSI1,
.defaultTxBufValue = 0,
.rxChannelBitMask = 1 << UDMA_CHAN_SSI1_RX,
.txChannelBitMask = 1 << UDMA_CHAN_SSI1_TX,
.mosiPin = Board_SPI1_MOSI,
.misoPin = Board_SPI1_MISO,
.clkPin = Board_SPI1_CLK,
.csnPin = Board_SPI1_CS //
},
#endif
};
/* SPI configuration structure */
const SPI_Config SPI_config[] = {
const SPI_Config SPI_config[] = { //
{
.fxnTablePtr = &SPICC26XXDMA_fxnTable,
.object = &spiCC26XXDMAObjects[0],
.hwAttrs = &spiCC26XXDMAHWAttrs[0]
//
.fxnTablePtr = &SPICC26XXDMA_fxnTable,
.object = &spiCC26XXDMAObjects[0],
.hwAttrs = &spiCC26XXDMAHWAttrs[0]
//
},
{
.fxnTablePtr = &SPICC26XXDMA_fxnTable,
.object = &spiCC26XXDMAObjects[1],
.hwAttrs = &spiCC26XXDMAHWAttrs[1]
//
.fxnTablePtr = &SPICC26XXDMA_fxnTable,
.object = &spiCC26XXDMAObjects[1],
.hwAttrs = &spiCC26XXDMAHWAttrs[1]
//
},
{NULL, NULL, NULL}
};
{NULL, NULL, NULL}};
/*
* ========================== SPI DMA end =====================================
*/
*/
/*
* ========================== Crypto begin ====================================
@@ -259,28 +294,28 @@ const SPI_Config SPI_config[] = {
CryptoCC26XX_Object cryptoCC26XXObjects[BOOSTXL_CC2650MA_CRYPTOCOUNT];
/* Crypto configuration structure, describing which pins are to be used */
const CryptoCC26XX_HWAttrs cryptoCC26XXHWAttrs[BOOSTXL_CC2650MA_CRYPTOCOUNT] = {
{
.baseAddr = CRYPTO_BASE,
.powerMngrId = PowerCC26XX_PERIPH_CRYPTO,
.intNum = INT_CRYPTO_RESULT_AVAIL_IRQ,
.intPriority = ~0,
}
};
const CryptoCC26XX_HWAttrs cryptoCC26XXHWAttrs[BOOSTXL_CC2650MA_CRYPTOCOUNT] = {{
//
.baseAddr = CRYPTO_BASE,
.powerMngrId = PowerCC26XX_PERIPH_CRYPTO,
.intNum = INT_CRYPTO_RESULT_AVAIL_IRQ,
.intPriority = ~0,
//
}};
/* Crypto configuration structure */
const CryptoCC26XX_Config CryptoCC26XX_config[] = {
const CryptoCC26XX_Config CryptoCC26XX_config[] = { //
{
.object = &cryptoCC26XXObjects[0],
.hwAttrs = &cryptoCC26XXHWAttrs[0]
//
.object = &cryptoCC26XXObjects[0],
.hwAttrs = &cryptoCC26XXHWAttrs[0]
//
},
{NULL, NULL}
};
{NULL, NULL}};
/*
* ========================== Crypto end ======================================
*/
/*
* ========================= RF driver begin ==================================
*/
@@ -294,10 +329,12 @@ const CryptoCC26XX_Config CryptoCC26XX_config[] = {
/* RF hwi and swi priority */
const RFCC26XX_HWAttrs RFCC26XX_hwAttrs = {
//
.hwiCpe0Priority = ~0,
.hwiHwPriority = ~0,
.swiCpe0Priority = 5,
.swiHwPriority = 5,
.swiCpe0Priority = 5,
.swiHwPriority = 5,
//
};
/*
@@ -320,20 +357,21 @@ const RFCC26XX_HWAttrs RFCC26XX_hwAttrs = {
TRNGCC26XX_Object trngCC26XXObjects[BOOSTXL_CC2650MA_TRNGCOUNT];
/* TRNG configuration structure, describing which pins are to be used */
const TRNGCC26XX_HWAttrs TRNGCC26XXHWAttrs[BOOSTXL_CC2650MA_TRNGCOUNT] = {
{
.powerMngrId = PowerCC26XX_PERIPH_TRNG,
}
};
const TRNGCC26XX_HWAttrs TRNGCC26XXHWAttrs[BOOSTXL_CC2650MA_TRNGCOUNT] = {{
//
.powerMngrId = PowerCC26XX_PERIPH_TRNG,
//
}};
/* TRNG configuration structure */
const TRNGCC26XX_Config TRNGCC26XX_config[] = {
const TRNGCC26XX_Config TRNGCC26XX_config[] = { //
{
.object = &trngCC26XXObjects[0],
.hwAttrs = &TRNGCC26XXHWAttrs[0]
//
.object = &trngCC26XXObjects[0],
.hwAttrs = &TRNGCC26XXHWAttrs[0]
//
},
{NULL, NULL}
};
{NULL, NULL}};
/*
* ========================= TRNG end ====================================
@@ -351,14 +389,62 @@ const TRNGCC26XX_Config TRNGCC26XX_config[] = {
/* GPTimer hardware attributes, one per timer part (Timer 0A, 0B, 1A, 1B..) */
const GPTimerCC26XX_HWAttrs gptimerCC26xxHWAttrs[BOOSTXL_CC2650MA_GPTIMERPARTSCOUNT] = {
{ .baseAddr = GPT0_BASE, .intNum = INT_GPT0A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT0, .pinMux = GPT_PIN_0A, },
{ .baseAddr = GPT0_BASE, .intNum = INT_GPT0B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT0, .pinMux = GPT_PIN_0B, },
{ .baseAddr = GPT1_BASE, .intNum = INT_GPT1A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT1, .pinMux = GPT_PIN_1A, },
{ .baseAddr = GPT1_BASE, .intNum = INT_GPT1B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT1, .pinMux = GPT_PIN_1B, },
{ .baseAddr = GPT2_BASE, .intNum = INT_GPT2A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT2, .pinMux = GPT_PIN_2A, },
{ .baseAddr = GPT2_BASE, .intNum = INT_GPT2B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT2, .pinMux = GPT_PIN_2B, },
{ .baseAddr = GPT3_BASE, .intNum = INT_GPT3A, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT3, .pinMux = GPT_PIN_3A, },
{ .baseAddr = GPT3_BASE, .intNum = INT_GPT3B, .intPriority = (~0), .powerMngrId = PowerCC26XX_PERIPH_GPT3, .pinMux = GPT_PIN_3B, },
{
.baseAddr = GPT0_BASE,
.intNum = INT_GPT0A,
.intPriority = (~0),
.powerMngrId = PowerCC26XX_PERIPH_GPT0,
.pinMux = GPT_PIN_0A,
},
{
.baseAddr = GPT0_BASE,
.intNum = INT_GPT0B,
.intPriority = (~0),
.powerMngrId = PowerCC26XX_PERIPH_GPT0,
.pinMux = GPT_PIN_0B,
},
{
.baseAddr = GPT1_BASE,
.intNum = INT_GPT1A,
.intPriority = (~0),
.powerMngrId = PowerCC26XX_PERIPH_GPT1,
.pinMux = GPT_PIN_1A,
},
{
.baseAddr = GPT1_BASE,
.intNum = INT_GPT1B,
.intPriority = (~0),
.powerMngrId = PowerCC26XX_PERIPH_GPT1,
.pinMux = GPT_PIN_1B,
},
{
.baseAddr = GPT2_BASE,
.intNum = INT_GPT2A,
.intPriority = (~0),
.powerMngrId = PowerCC26XX_PERIPH_GPT2,
.pinMux = GPT_PIN_2A,
},
{
.baseAddr = GPT2_BASE,
.intNum = INT_GPT2B,
.intPriority = (~0),
.powerMngrId = PowerCC26XX_PERIPH_GPT2,
.pinMux = GPT_PIN_2B,
},
{
.baseAddr = GPT3_BASE,
.intNum = INT_GPT3A,
.intPriority = (~0),
.powerMngrId = PowerCC26XX_PERIPH_GPT3,
.pinMux = GPT_PIN_3A,
},
{
.baseAddr = GPT3_BASE,
.intNum = INT_GPT3B,
.intPriority = (~0),
.powerMngrId = PowerCC26XX_PERIPH_GPT3,
.pinMux = GPT_PIN_3B,
},
};
/* GPTimer objects, one per full-width timer (A+B) (Timer 0, Timer 1..) */
@@ -366,14 +452,15 @@ GPTimerCC26XX_Object gptimerCC26XXObjects[BOOSTXL_CC2650MA_GPTIMERCOUNT];
/* GPTimer configuration (used as GPTimer_Handle by driver and application) */
const GPTimerCC26XX_Config GPTimerCC26XX_config[BOOSTXL_CC2650MA_GPTIMERPARTSCOUNT] = {
{ &gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[0], GPT_A },
{ &gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[1], GPT_B },
{ &gptimerCC26XXObjects[1], &gptimerCC26xxHWAttrs[2], GPT_A },
{ &gptimerCC26XXObjects[1], &gptimerCC26xxHWAttrs[3], GPT_B },
{ &gptimerCC26XXObjects[2], &gptimerCC26xxHWAttrs[4], GPT_A },
{ &gptimerCC26XXObjects[2], &gptimerCC26xxHWAttrs[5], GPT_B },
{ &gptimerCC26XXObjects[3], &gptimerCC26xxHWAttrs[6], GPT_A },
{ &gptimerCC26XXObjects[3], &gptimerCC26xxHWAttrs[7], GPT_B },
//
{&gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[0], GPT_A},
{&gptimerCC26XXObjects[0], &gptimerCC26xxHWAttrs[1], GPT_B},
{&gptimerCC26XXObjects[1], &gptimerCC26xxHWAttrs[2], GPT_A},
{&gptimerCC26XXObjects[1], &gptimerCC26xxHWAttrs[3], GPT_B},
{&gptimerCC26XXObjects[2], &gptimerCC26xxHWAttrs[4], GPT_A},
{&gptimerCC26XXObjects[2], &gptimerCC26xxHWAttrs[5], GPT_B},
{&gptimerCC26XXObjects[3], &gptimerCC26xxHWAttrs[6], GPT_A},
{&gptimerCC26XXObjects[3], &gptimerCC26xxHWAttrs[7], GPT_B},
};
/*
@@ -391,14 +478,15 @@ const GPTimerCC26XX_Config GPTimerCC26XX_config[BOOSTXL_CC2650MA_GPTIMERPARTSCOU
#endif
/* PWM configuration, one per PWM output. */
PWMTimerCC26XX_HwAttrs pwmtimerCC26xxHWAttrs[BOOSTXL_CC2650MA_PWMCOUNT] = {
{ .pwmPin = Board_PWMPIN0, .gpTimerUnit = Board_GPTIMER0A },
{ .pwmPin = Board_PWMPIN1, .gpTimerUnit = Board_GPTIMER0B },
{ .pwmPin = Board_PWMPIN2, .gpTimerUnit = Board_GPTIMER1A },
{ .pwmPin = Board_PWMPIN3, .gpTimerUnit = Board_GPTIMER1B },
{ .pwmPin = Board_PWMPIN4, .gpTimerUnit = Board_GPTIMER2A },
{ .pwmPin = Board_PWMPIN5, .gpTimerUnit = Board_GPTIMER2B },
{ .pwmPin = Board_PWMPIN6, .gpTimerUnit = Board_GPTIMER3A },
{ .pwmPin = Board_PWMPIN7, .gpTimerUnit = Board_GPTIMER3B },
//
{.pwmPin = Board_PWMPIN0, .gpTimerUnit = Board_GPTIMER0A},
{.pwmPin = Board_PWMPIN1, .gpTimerUnit = Board_GPTIMER0B},
{.pwmPin = Board_PWMPIN2, .gpTimerUnit = Board_GPTIMER1A},
{.pwmPin = Board_PWMPIN3, .gpTimerUnit = Board_GPTIMER1B},
{.pwmPin = Board_PWMPIN4, .gpTimerUnit = Board_GPTIMER2A},
{.pwmPin = Board_PWMPIN5, .gpTimerUnit = Board_GPTIMER2B},
{.pwmPin = Board_PWMPIN6, .gpTimerUnit = Board_GPTIMER3A},
{.pwmPin = Board_PWMPIN7, .gpTimerUnit = Board_GPTIMER3B},
};
/* PWM object, one per PWM output */
@@ -408,17 +496,16 @@ extern const PWM_FxnTable PWMTimerCC26XX_fxnTable;
/* PWM configuration (used as PWM_Handle by driver and application) */
const PWM_Config PWM_config[BOOSTXL_CC2650MA_PWMCOUNT + 1] = {
{ &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[0], &pwmtimerCC26xxHWAttrs[0] },
{ &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[1], &pwmtimerCC26xxHWAttrs[1] },
{ &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[2], &pwmtimerCC26xxHWAttrs[2] },
{ &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[3], &pwmtimerCC26xxHWAttrs[3] },
{ &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[4], &pwmtimerCC26xxHWAttrs[4] },
{ &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[5], &pwmtimerCC26xxHWAttrs[5] },
{ &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[6], &pwmtimerCC26xxHWAttrs[6] },
{ &PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[7], &pwmtimerCC26xxHWAttrs[7] },
{ NULL, NULL, NULL }
};
//
{&PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[0], &pwmtimerCC26xxHWAttrs[0]},
{&PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[1], &pwmtimerCC26xxHWAttrs[1]},
{&PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[2], &pwmtimerCC26xxHWAttrs[2]},
{&PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[3], &pwmtimerCC26xxHWAttrs[3]},
{&PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[4], &pwmtimerCC26xxHWAttrs[4]},
{&PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[5], &pwmtimerCC26xxHWAttrs[5]},
{&PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[6], &pwmtimerCC26xxHWAttrs[6]},
{&PWMTimerCC26XX_fxnTable, &pwmtimerCC26xxObjects[7], &pwmtimerCC26xxHWAttrs[7]},
{NULL, NULL, NULL}};
/*
* ============================= PWM end ======================================
@@ -151,6 +151,11 @@ extern const PIN_Config BoardGpioInitTable[];
#define Board_SPI0_CLK Board_BP_SPI_CLK
#define Board_SPI0_CS Board_BP_SPI_CS_Wireless
#define Board_SPI1_MISO PIN_UNASSIGNED
#define Board_SPI1_MOSI PIN_UNASSIGNED
#define Board_SPI1_CLK PIN_UNASSIGNED
#define Board_SPI1_CS PIN_UNASSIGNED
/* Power Management Board */
#define Board_SRDY Board_BP_Pin_J2_19
#define Board_MRDY Board_BP_Pin_J1_2
@@ -170,10 +175,17 @@ extern const PIN_Config BoardGpioInitTable[];
* ==========================================================================*/
/* Generic SPI instance identifiers */
#define Board_SPI0 BOOSTXL_CC2650MA_SPI0
#ifdef HEADSTAGE_MA_USE_SPI2
#define Board_SPI1 BOOSTXL_CC2650MA_SPI1
#endif
/* Generic UART instance identifiers */
#define Board_UART BOOSTXL_CC2650MA_UART0
/* Generic TRNG instance identiifer */
#define Board_TRNG BOOSTXL_CC2650MA_TRNG0
/* Generic GPTimer instance identifiers */
#define Board_GPTIMER0A BOOSTXL_CC2650MA_GPTIMER0A
#define Board_GPTIMER0B BOOSTXL_CC2650MA_GPTIMER0B
@@ -183,6 +195,7 @@ extern const PIN_Config BoardGpioInitTable[];
#define Board_GPTIMER2B BOOSTXL_CC2650MA_GPTIMER2B
#define Board_GPTIMER3A BOOSTXL_CC2650MA_GPTIMER3A
#define Board_GPTIMER3B BOOSTXL_CC2650MA_GPTIMER3B
/* Generic PWM instance identifiers */
#define Board_PWM0 BOOSTXL_CC2650MA_PWM0
#define Board_PWM1 BOOSTXL_CC2650MA_PWM1
@@ -215,6 +228,10 @@ typedef enum BOOSTXL_CC2650MA_CryptoName {
typedef enum BOOSTXL_CC2650MA_SPIName {
BOOSTXL_CC2650MA_SPI0 = 0,
#ifdef HEADSTAGE_MA_USE_SPI2
BOOSTXL_CC2650MA_SPI1 ,
#endif
BOOSTXL_CC2650MA_SPICOUNT
} BOOSTXL_CC2650MA_SPIName;
@@ -294,6 +311,29 @@ typedef enum BOOSTXL_CC2650MA_PWM
BOOSTXL_CC2650MA_PWMCOUNT
} BOOSTXL_CC2650MA_PWM;
#ifdef HEADSTAGE_MA_USE_ADC
/*!
* @def BOOSTXL_CC2650MA_ADCName
* @brief Enum of ADCs
*/
typedef enum BOOSTXL_CC2650MA_ADCName {
BOOSTXL_CC2650MA_ADC0 = 0,
BOOSTXL_CC2650MA_ADC1,
BOOSTXL_CC2650MA_ADC2,
BOOSTXL_CC2650MA_ADC3,
BOOSTXL_CC2650MA_ADC4,
BOOSTXL_CC2650MA_ADC5,
BOOSTXL_CC2650MA_ADC6,
BOOSTXL_CC2650MA_ADC7,
BOOSTXL_CC2650MA_ADCDCOUPL,
BOOSTXL_CC2650MA_ADCVSS,
BOOSTXL_CC2650MA_ADCVDDS,
BOOSTXL_CC2650MA_ADCCOUNT
} BOOSTXL_CC2650MA_ADCName;
#endif
#ifdef __cplusplus
}
#endif
@@ -144,13 +144,17 @@ extern const PIN_Config BoardGpioInitTable[];
* ==========================================================================*/
/* Generic I2C instance identifiers */
#define Board_I2C CC2650_LAUNCHXL_I2C0
/* Generic SPI instance identifiers */
#define Board_SPI0 CC2650_LAUNCHXL_SPI0
#define Board_SPI1 CC2650_LAUNCHXL_SPI1
/* Generic UART instance identifiers */
#define Board_UART CC2650_LAUNCHXL_UART0
/* Generic Crypto instance identifiers */
#define Board_CRYPTO CC2650_LAUNCHXL_CRYPTO0
/* Generic GPTimer instance identifiers */
#define Board_GPTIMER0A CC2650_LAUNCHXL_GPTIMER0A
#define Board_GPTIMER0B CC2650_LAUNCHXL_GPTIMER0B
@@ -160,6 +164,7 @@ extern const PIN_Config BoardGpioInitTable[];
#define Board_GPTIMER2B CC2650_LAUNCHXL_GPTIMER2B
#define Board_GPTIMER3A CC2650_LAUNCHXL_GPTIMER3A
#define Board_GPTIMER3B CC2650_LAUNCHXL_GPTIMER3B
/* Generic PWM instance identifiers */
#define Board_PWM0 CC2650_LAUNCHXL_PWM0
#define Board_PWM1 CC2650_LAUNCHXL_PWM1
@@ -9,7 +9,7 @@
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2013-2018, Texas Instruments Incorporated
All rights reserved.
@@ -45,10 +45,11 @@
Release Date: 2018-04-02 18:03:35
*****************************************************************************/
/*********************************************************************
* INCLUDES
*/
/*================
==== include ====
===============*/
// clang-format off
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/hal/Hwi.h>
#include <ti/sysbios/knl/Clock.h>
@@ -71,7 +72,6 @@
#include "icall_apimsg.h"
#include "util.h"
#include <ti/mw/display/Display.h>
#include "inc/npi_ble.h"
#include "inc/npi_task.h"
@@ -88,13 +88,20 @@
#include "host_test_app.h"
#if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
#include <driverlib/ioc.h>
#endif // USE_FPGA | DEBUG_SW_TRACE
#include "master/cc2650_master.h"
/*********************************************************************
* CONSTANTS
// clang-format on
/*=================
==== constant ====
=================*/
// clang-format off
/*
* GAP GATT Attributes
*/
#define DEVICE_NAME "BioProController"
// LE Event Lengths
#define HCI_CMD_COMPLETE_EVENT_LEN 3
@@ -106,60 +113,38 @@
#define HTA_TASK_PRIORITY 1
#define HTA_TASK_STACK_SIZE 644
/*********************************************************************
* GLOBAL VARIABLES
*/
// data length extension
#define APP_SUGGESTED_PDU_SIZE 251
#define APP_SUGGESTED_TX_TIME 2120
// Display Interface
Display_Handle dispHandle = NULL;
// clang-format on
/*********************************************************************
* LOCAL VARIABLES
*/
// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID selfEntity;
static ICall_EntityID self;
// Semaphore globally used to post events to the application thread
static ICall_Semaphore sem;
static ICall_Semaphore semaphore;
// Task configuration
Task_Struct htaTask;
Char htaTaskStack[HTA_TASK_STACK_SIZE];
Char htaTaskStack[HTA_TASK_STACK_SIZE];
#if !defined ( GATT_DB_OFF_CHIP )
static uint8 deviceName[GAP_DEVICE_NAME_LEN] = { 0 };
static uint16 appearance = 17;
#endif
// Stack build revision
ICall_BuildRevision buildRev;
/*********************************************************************
* LOCAL FUNCTIONS
*/
/*=========================
==== function declare ====
========================*/
static void HostTestApp_init(void);
static void HostTestApp_taskFxn(UArg a0, UArg a1);
static void HostTestApp_processGapEvent(ICall_HciExtEvt *pMsg);
static void HostTestApp_processAttEvent(ICall_HciExtEvt *pMsg);
static void HostTestApp_processBLEEvent(ICall_HciExtEvt *pMsg);
static void sendCommandCompleteEvent(uint8 eventCode, uint16 opcode,
uint8 numParam, uint8 *param);
static void sendCommandStatusEvent(uint8_t eventCode, uint16_t status,
uint16_t opcode);
static void sendCommandCompleteEvent(uint8 eventCode, uint16 opcode, uint8 numParam, uint8 *param);
static void sendCommandStatusEvent(uint8_t eventCode, uint16_t status, uint16_t opcode);
static void sendBLECompleteEvent(uint8 eventLen, uint8 *pEvent);
/*********************************************************************
* EXTERN FUNCTIONS
*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
/**
* @fn HostTestApp_createTask
*
* @brief Task creation function for the Host Test App.
@@ -168,20 +153,19 @@ extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
*
* @return none
*/
void HostTestApp_createTask(void)
{
Task_Params taskParams;
void HostTestApp_createTask(void) {
Task_Params taskParams;
// Configure task
Task_Params_init(&taskParams);
taskParams.stack = htaTaskStack;
taskParams.stackSize = HTA_TASK_STACK_SIZE;
taskParams.priority = HTA_TASK_PRIORITY;
// Configure task
Task_Params_init(&taskParams);
taskParams.stack = htaTaskStack;
taskParams.stackSize = HTA_TASK_STACK_SIZE;
taskParams.priority = HTA_TASK_PRIORITY;
Task_construct(&htaTask, HostTestApp_taskFxn, &taskParams, NULL);
Task_construct(&htaTask, HostTestApp_taskFxn, &taskParams, NULL);
}
/*********************************************************************
/**
* @fn HostTestApp_init
*
* @brief Called during initialization and contains application
@@ -193,117 +177,34 @@ void HostTestApp_createTask(void)
*
* @return none
*/
static void HostTestApp_init(void)
{
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&selfEntity, &sem);
static void HostTestApp_init(void) {
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&self, &semaphore);
#if defined( USE_FPGA )
// configure RF Core SMI Data Link
IOCPortConfigureSet(IOID_12, IOC_PORT_RFC_GPO0, IOC_STD_OUTPUT);
IOCPortConfigureSet(IOID_11, IOC_PORT_RFC_GPI0, IOC_STD_INPUT);
// Set device's Sleep Clock Accuracy
// HCI_EXT_SetSCACmd(40);
// configure RF Core SMI Command Link
IOCPortConfigureSet(IOID_10, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_OUT, IOC_STD_OUTPUT);
IOCPortConfigureSet(IOID_9, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_IN, IOC_STD_INPUT);
#if defined(USE_RCOSC)
RCOSC_enableCalibration();
#endif // USE_RCOSC
// configure RF Core tracer IO
IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT);
#else // !USE_FPGA
#if defined( DEBUG_SW_TRACE )
// configure RF Core tracer IO
IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT | IOC_CURRENT_4MA | IOC_SLEW_ENABLE);
#endif // DEBUG_SW_TRACE
#endif // USE_FPGA
// Initialize GATT Client
VOID GATT_InitClient();
// Set device's Sleep Clock Accuracy
//HCI_EXT_SetSCACmd(40);
// Register to receive incoming ATT Indications or Notifications of attribute values.
GATT_RegisterForInd(self);
#if defined( USE_RCOSC )
RCOSC_enableCalibration();
#endif // USE_RCOSC
// Register for unprocessed HCI/Host event messages
GAP_RegisterForMsgs(self);
dispHandle = Display_open(Display_Type_LCD, NULL);
GGS_SetParameter(GGS_DEVICE_NAME_ATT, strlen(DEVICE_NAME), (void *)DEVICE_NAME);
// Register for unprocessed HCI/Host event messages
GAP_RegisterForMsgs(selfEntity);
// Initialize GATT Client
VOID GATT_InitClient();
// Get build revision
VOID Util_buildRevision(&buildRev);
#if !defined ( GATT_DB_OFF_CHIP )
#if defined ( GATT_QUAL )
VOID GATTQual_AddService( GATT_ALL_SERVICES ); // Includes GAP and GATT Services
#else
// Add our services to GATT Server
VOID GGS_AddService( GATT_ALL_SERVICES );
VOID GATTServApp_AddService( GATT_ALL_SERVICES );
#if defined ( GATT_TEST )
VOID GATTTest_AddService( GATT_ALL_SERVICES );
#endif
#endif
// Set device name
if ((buildRev.hostInfo & CENTRAL_CFG) && (buildRev.hostInfo & PERIPHERAL_CFG))
{
memcpy(deviceName, "TI BLE All", 10);
}
else if (buildRev.hostInfo & CENTRAL_CFG)
{
memcpy(deviceName, "TI BLE Central", 14);
}
else if (buildRev.hostInfo & PERIPHERAL_CFG)
{
memcpy(deviceName, "TI BLE Peripheral", 17);
}
else
{
memcpy(deviceName, "TI BLE Unknown", 14);
}
VOID GGS_SetParameter(GGS_DEVICE_NAME_ATT, strlen((char *)deviceName), deviceName);
VOID GGS_SetParameter(GGS_APPEARANCE_ATT, sizeof(uint16), (void*)&appearance);
#endif // GATT_DB_OFF_CHIP
Display_print0(dispHandle, 0, 0, "TI BLEv2.0");
Display_print0(dispHandle, 1, 0, "HostTestApp");
// Display Host build configuration
if ((buildRev.hostInfo & CENTRAL_CFG) && (buildRev.hostInfo & PERIPHERAL_CFG))
{
Display_print0(dispHandle, 2, 0, "All");
}
else if ((buildRev.hostInfo & CENTRAL_CFG) &&
(buildRev.hostInfo & BROADCASTER_CFG))
{
Display_print0(dispHandle, 2, 0, "Cent+Bcast");
}
else if ((buildRev.hostInfo & PERIPHERAL_CFG) &&
(buildRev.hostInfo & OBSERVER_CFG))
{
Display_print0(dispHandle, 2, 0, "Peri+Observ");
}
else if (buildRev.hostInfo & CENTRAL_CFG)
{
Display_print0(dispHandle, 2, 0, "Central");
}
else if (buildRev.hostInfo & PERIPHERAL_CFG)
{
Display_print0(dispHandle, 2, 0, "Peripheral");
}
else
{
Display_print1(dispHandle, 2, 0, "Unknown build cfg %d", buildRev.hostInfo);
}
// extend PDU size
HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
}
/*********************************************************************
/**
* @fn HostTestApp_taskFxn
*
* @brief Application task entry point for the Host Test App.
@@ -312,55 +213,54 @@ static void HostTestApp_init(void)
*
* @return none
*/
static void HostTestApp_taskFxn(UArg a0, UArg a1)
{
// Initialize application
HostTestApp_init();
static void HostTestApp_taskFxn(UArg a0, UArg a1) {
// Initialize application
HostTestApp_init();
master_init();
// Application main loop
for (;;)
{
// Waits for a signal to the semaphore associated with the calling thread.
// Note that the semaphore associated with a thread is signaled when a
// message is queued to the message receive queue of the thread or when
// ICall_signal() function is called onto the semaphore.
ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
// Application main loop
for (;;) {
// Waits for a signal to the semaphore associated with the calling thread.
// Note that the semaphore associated with a thread is signaled when a
// message is queued to the message receive queue of the thread or when
// ICall_signal() function is called onto the semaphore.
ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
if (errno == ICALL_ERRNO_SUCCESS)
{
ICall_EntityID dest;
ICall_ServiceEnum src;
ICall_HciExtEvt *pMsg = NULL;
if (errno == ICALL_ERRNO_SUCCESS) {
ICall_EntityID dest;
ICall_ServiceEnum src;
ICall_HciExtEvt * message = NULL;
if (ICall_fetchServiceMsg(&src, &dest,
(void **)&pMsg) == ICALL_ERRNO_SUCCESS)
{
bool dealloc = true;
if (ICall_fetchServiceMsg(&src, &dest, (void **)&message) == ICALL_ERRNO_SUCCESS) {
if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == self)) {
// Process incoming messages
switch (message->hdr.event) {
case HCI_GAP_EVENT_EVENT:
HostTestApp_processGapEvent(message);
break;
if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
{
// Process incoming messages
switch (pMsg->hdr.event)
{
case HCI_GAP_EVENT_EVENT:
HostTestApp_processGapEvent(pMsg);
break;
case GATT_MSG_EVENT:
HostTestApp_processAttEvent((gattMsgEvent_t *)message);
break;
default:
break;
}
default:
break;
}
}
if (message) {
ICall_freeMsg(message);
}
}
}
if (dealloc == true)
{
ICall_freeMsg(pMsg);
if (EVENT_MASK > 0) {
master_event_handle();
}
}
}
}
}
/*********************************************************************
/**
* @fn HostTestApp_processGapEvent
*
* @brief Process an incoming GAP Event.
@@ -369,96 +269,102 @@ static void HostTestApp_taskFxn(UArg a0, UArg a1)
*
* @return none
*/
static void HostTestApp_processGapEvent(ICall_HciExtEvt *pMsg)
{
switch(pMsg->hdr.status)
{
case HCI_COMMAND_COMPLETE_EVENT_CODE:
{
hciEvt_CmdComplete_t *pkt = (hciEvt_CmdComplete_t *)pMsg;
static void HostTestApp_processGapEvent(ICall_HciExtEvt *message) {
switch (message->hdr.status) {
case HCI_COMMAND_COMPLETE_EVENT_CODE: {
hciEvt_CmdComplete_t *pkt = (hciEvt_CmdComplete_t *)message;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
if (lastAppOpcodeSent == pkt->cmdOpcode) {
// app processes this as it was embedded message to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
} else {
osal_msg_hdr_t *msgHdr;
uint8 len;
msgHdr = (osal_msg_hdr_t *)message;
msgHdr--; // Backup to the message header
len = (uint8)(msgHdr->len - sizeof(hciEvt_CmdComplete_t));
sendCommandCompleteEvent(HCI_COMMAND_COMPLETE_EVENT_CODE, pkt->cmdOpcode, len, pkt->pReturnParam);
}
else
{
osal_msg_hdr_t *msgHdr;
uint8 len;
msgHdr = (osal_msg_hdr_t *)pMsg;
msgHdr--; // Backup to the msg header
len = (uint8)(msgHdr->len - sizeof ( hciEvt_CmdComplete_t ));
sendCommandCompleteEvent(HCI_COMMAND_COMPLETE_EVENT_CODE,
pkt->cmdOpcode, len, pkt->pReturnParam);
}
}
break;
break;
}
case HCI_DISCONNECTION_COMPLETE_EVENT_CODE:
break;
break;
case HCI_COMMAND_STATUS_EVENT_CODE:
{
hciEvt_CommandStatus_t *pkt = (hciEvt_CommandStatus_t *)pMsg;
case HCI_COMMAND_STATUS_EVENT_CODE: {
hciEvt_CommandStatus_t *pkt = (hciEvt_CommandStatus_t *)message;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
if (lastAppOpcodeSent == pkt->cmdOpcode) {
// app processes this as it was embedded msg to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
} else if (pkt->cmdOpcode == HCI_LE_SET_PHY) {
sendCommandStatusEvent(HCI_COMMAND_STATUS_EVENT_CODE, pkt->cmdStatus, pkt->cmdOpcode);
}
else if (pkt->cmdOpcode == HCI_LE_SET_PHY)
{
sendCommandStatusEvent(HCI_COMMAND_STATUS_EVENT_CODE, pkt->cmdStatus,
pkt->cmdOpcode);
}
}
break;
} break;
case HCI_LE_EVENT_CODE:
{
HostTestApp_processBLEEvent(pMsg);
}
break;
HostTestApp_processBLEEvent(message);
break;
case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
{
AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
}
break;
AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR, 0);
break;
case HCI_VE_EVENT_CODE:
{
hciEvt_VSCmdComplete_t *pkt = (hciEvt_VSCmdComplete_t *)pMsg;
case HCI_VE_EVENT_CODE: {
hciEvt_VSCmdComplete_t *pkt = (hciEvt_VSCmdComplete_t *)message;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
if (lastAppOpcodeSent == pkt->cmdOpcode) {
// app processes this as it was embedded msg to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
} else {
sendCommandCompleteEvent(HCI_VE_EVENT_CODE, pkt->cmdOpcode, pkt->length, pkt->pEventParam);
}
else
{
sendCommandCompleteEvent(HCI_VE_EVENT_CODE, pkt->cmdOpcode,
pkt->length, pkt->pEventParam);
}
}
break;
break;
}
default:
break;
}
break;
}
}
/*********************************************************************
/**
* @fn HostTestApp_processAttEvent
*
* @brief Process an incoming ATT Event.
* @param pMsg - message to process
*
* @return None.
*/
static void HostTestApp_processAttEvent(gattMsgEvent_t *message) {
uint8_t method = message->method;
if (message->hdr.status == blePending) {
// pass
} else if ((method == ATT_READ_RSP) || (method == ATT_ERROR_RSP && message->msg.errorRsp.reqOpcode == ATT_READ_REQ)) {
// pass
} else if ((method == ATT_WRITE_RSP) || (method == ATT_ERROR_RSP && message->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)) {
// pass
} else if (method == ATT_HANDLE_VALUE_NOTI) {
attHandleValueNoti_t *att_notify = (attHandleValueNoti_t *)(&message->msg);
master_handle_notify(att_notify->len, att_notify->pValue);
}
// Free message. Needed only for ATT Protocol messages
GATT_bm_free(&message->msg, message->method);
}
/**
* @fn HostTestApp_processBLEEvent
*
* @brief Process an incoming BLE Event.
@@ -467,210 +373,177 @@ static void HostTestApp_processGapEvent(ICall_HciExtEvt *pMsg)
*
* @return None.
*/
static void HostTestApp_processBLEEvent(ICall_HciExtEvt *pMsg)
{
hciEvt_BLEPhyUpdateComplete_t *pEvt = (hciEvt_BLEPhyUpdateComplete_t *)pMsg;
uint8 event[HCI_PHY_UPDATE_COMPLETE_EVENT_LEN];
uint8 eventLen;
static void HostTestApp_processBLEEvent(ICall_HciExtEvt *message) {
hciEvt_BLEPhyUpdateComplete_t *pEvt = (hciEvt_BLEPhyUpdateComplete_t *)message;
switch (pEvt->BLEEventCode)
{
case HCI_BLE_PHY_UPDATE_COMPLETE_EVENT:
{
event[0] = HCI_BLE_PHY_UPDATE_COMPLETE_EVENT; // event code
event[1] = pEvt->status; // status
event[2] = LO_UINT16(pEvt->connHandle); // connection handle (LSB)
event[3] = HI_UINT16(pEvt->connHandle); // connection handle (MSB)
event[4] = pEvt->txPhy; // TX PHY
event[5] = pEvt->rxPhy; // RX PHY
uint8 event[HCI_PHY_UPDATE_COMPLETE_EVENT_LEN];
uint8 eventLen = 0;
switch (pEvt->BLEEventCode) {
case HCI_BLE_PHY_UPDATE_COMPLETE_EVENT: {
event[0] = HCI_BLE_PHY_UPDATE_COMPLETE_EVENT; // event code
event[1] = pEvt->status; // status
event[2] = LO_UINT16(pEvt->connHandle); // connection handle (LSB)
event[3] = HI_UINT16(pEvt->connHandle); // connection handle (MSB)
event[4] = pEvt->txPhy; // TX PHY
event[5] = pEvt->rxPhy; // RX PHY
eventLen = HCI_PHY_UPDATE_COMPLETE_EVENT_LEN;
}
break;
break;
}
}
default:
eventLen = 0;
break;
}
if (eventLen > 0)
{
// Send BLE Complete Event
sendBLECompleteEvent(eventLen, event);
}
if (eventLen > 0) {
// Send BLE Complete Event
sendBLECompleteEvent(eventLen, event);
}
}
//*****************************************************************************
// the function prototypes
/*******************************************************************************
/**
* This generic function sends a Command Complete or a Vendor Specific Command
* Complete Event to the Host.
*
*/
static void sendCommandCompleteEvent(uint8_t eventCode, uint16_t opcode,
uint8_t numParam, uint8_t *param)
{
npiPkt_t *msg;
uint8_t totalLength;
uint8_t txLen = 0; // Length to transmit
static void sendCommandCompleteEvent(uint8_t eventCode, uint16_t opcode, uint8_t numParam, uint8_t *param) {
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Return Parameters (0..N)
uint8_t totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + numParam;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Return Parameters (0..N)
totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + numParam;
// adjust the size of the event packet based on event code
// Note: If not a vendor specific event, then the event includes:
// Command Complete Data: Number of HCI Commands Allowed(1) + Command Opcode(2)
// Note: If a vendor specific event, then the event includes:
// Vendor Specific Command Complete Data: Vendor Specific Event Opcode(2)
totalLength += ((eventCode != HCI_VE_EVENT_CODE) ? HCI_CMD_COMPLETE_EVENT_LEN : HCI_CMD_VS_COMPLETE_EVENT_LEN);
// adjust the size of the event packet based on event code
// Note: If not a vendor specific event, then the event includes:
// Command Complete Data: Number of HCI Commands Allowed(1) + Command Opcode(2)
// Note: If a vendor specific event, then the event includes:
// Vendor Specific Command Complete Data: Vendor Specific Event Opcode(2)
totalLength += ( (eventCode != HCI_VE_EVENT_CODE) ?
HCI_CMD_COMPLETE_EVENT_LEN :
HCI_CMD_VS_COMPLETE_EVENT_LEN );
// allocate memory for OSAL hdr + packet
npiPkt_t *message = (npiPkt_t *)ICall_allocMsg(totalLength);
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg)
{
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
msg->pData = (uint8*)(msg+1);
uint8_t txLen = 0; // Length to transmit
// fill in Command Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = eventCode;
if (message) {
// OSAL message event, status, and pointer to packet
message->hdr.event = HCI_EVENT_PACKET;
message->hdr.status = 0xFF;
message->pData = (uint8 *)(message + 1);
txLen += 2;
// fill in Command Complete Event data
message->pData[0] = HCI_EVENT_PACKET;
message->pData[1] = eventCode;
// check if this isn't a vendor specific event
if ( eventCode != HCI_VE_EVENT_CODE )
{
msg->pData[2] = numParam + HCI_CMD_COMPLETE_EVENT_LEN;
msg->pData[3] = 1;// hciCtrlCmdToken; // event parameter 1
msg->pData[4] = LO_UINT16( opcode ); // event parameter 2
msg->pData[5] = HI_UINT16( opcode ); // event parameter 2
txLen += 2;
txLen += 4;
// check if this isn't a vendor specific event
if (eventCode != HCI_VE_EVENT_CODE) {
message->pData[2] = numParam + HCI_CMD_COMPLETE_EVENT_LEN;
message->pData[3] = 1; // hciCtrlCmdToken; // event parameter 1
message->pData[4] = LO_UINT16(opcode); // event parameter 2
message->pData[5] = HI_UINT16(opcode); // event parameter 2
// remaining event parameters
(void)memcpy(&msg->pData[6], param, numParam);
txLen += 4;
txLen += numParam;
// remaining event parameters
(void)memcpy(&message->pData[6], param, numParam);
txLen += numParam;
} else {
// it is a vendor specific event
// less one byte as number of complete packets not used in vendor specific event
message->pData[2] = numParam + HCI_CMD_VS_COMPLETE_EVENT_LEN;
message->pData[3] = param[0]; // event parameter 0: event opcode LSB
message->pData[4] = param[1]; // event parameter 1: event opcode MSB
message->pData[5] = param[2]; // event parameter 2: status
message->pData[6] = LO_UINT16(opcode); // event parameter 3: command opcode LSB
message->pData[7] = HI_UINT16(opcode); // event parameter 3: command opcode MSB
txLen += 6;
// remaining event parameters
// Note: The event opcode and status were already placed in the msg packet.
(void)memcpy(&message->pData[8], &param[3], numParam - HCI_EVENT_MIN_LENGTH);
txLen += (numParam - HCI_EVENT_MIN_LENGTH);
}
message->pktLen = txLen;
NPITask_sendToHost((uint8_t *)message);
}
else // it is a vendor specific event
{
// less one byte as number of complete packets not used in vendor specific event
msg->pData[2] = numParam + HCI_CMD_VS_COMPLETE_EVENT_LEN;
msg->pData[3] = param[0]; // event parameter 0: event opcode LSB
msg->pData[4] = param[1]; // event parameter 1: event opcode MSB
msg->pData[5] = param[2]; // event parameter 2: status
msg->pData[6] = LO_UINT16( opcode ); // event parameter 3: command opcode LSB
msg->pData[7] = HI_UINT16( opcode ); // event parameter 3: command opcode MSB
txLen += 6;
// remaining event parameters
// Note: The event opcode and status were already placed in the msg packet.
(void)memcpy(&msg->pData[8], &param[3], numParam-HCI_EVENT_MIN_LENGTH);
txLen += (numParam-HCI_EVENT_MIN_LENGTH);
}
msg->pktLen = txLen;
NPITask_sendToHost((uint8_t *)msg);
}
}
/*******************************************************************************
/**
* This generic function sends a Command Complete or a Vendor Specific Command
* Complete Event to the Host.
*
*/
static void sendCommandStatusEvent(uint8_t eventCode, uint16_t status,
uint16_t opcode)
{
npiPkt_t *msg;
uint8_t totalLength;
static void sendCommandStatusEvent(uint8_t eventCode, uint16_t status, uint16_t opcode) {
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Command Status Event Data: Status (1) + Num HCI Cmd Pkt (1) + Cmd Opcode (2)
uint8_t totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + HCI_CMD_STATUS_EVENT_LEN;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Command Status Event Data: Status (1) + Num HCI Cmd Pkt (1) + Cmd Opcode (2)
totalLength = sizeof(npiPkt_t) +
HCI_EVENT_MIN_LENGTH +
HCI_CMD_STATUS_EVENT_LEN;
// allocate memory for OSAL hdr + packet
npiPkt_t *message = (npiPkt_t *)ICall_allocMsg(totalLength);
if (message) {
// OSAL message event, status, and pointer to packet
message->hdr.event = HCI_EVENT_PACKET;
message->hdr.status = 0xFF;
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg)
{
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
// fill in length and data pointer
message->pktLen = HCI_EVENT_MIN_LENGTH + HCI_CMD_STATUS_EVENT_LEN;
message->pData = (uint8 *)(message + 1);
// fill in length and data pointer
msg->pktLen = HCI_EVENT_MIN_LENGTH + HCI_CMD_STATUS_EVENT_LEN;
msg->pData = (uint8*)(msg+1);
// fill in Command Complete Event data
message->pData[0] = HCI_EVENT_PACKET;
message->pData[1] = eventCode;
message->pData[2] = HCI_CMD_STATUS_EVENT_LEN;
message->pData[3] = status;
message->pData[4] = 1; // number of HCI command packets
message->pData[5] = LO_UINT16(opcode); // opcode (LSB)
message->pData[6] = HI_UINT16(opcode); // opcode (MSB)
// fill in Command Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = eventCode;
msg->pData[2] = HCI_CMD_STATUS_EVENT_LEN;
msg->pData[3] = status;
msg->pData[4] = 1; // number of HCI command packets
msg->pData[5] = LO_UINT16(opcode); // opcode (LSB)
msg->pData[6] = HI_UINT16(opcode); // opcode (MSB)
NPITask_sendToHost((uint8_t *)msg);
}
NPITask_sendToHost((uint8_t *)message);
}
}
/*******************************************************************************
/**
* This is a generic function used to send BLE Complete Event to the
* Host processor.
*
*/
static void sendBLECompleteEvent(uint8 eventLen, uint8 *pEvent)
{
npiPkt_t *msg;
uint8_t totalLength;
static void sendBLECompleteEvent(uint8 eventLen, uint8 *pEvent) {
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Event Data: eventLen
uint8_t totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + eventLen;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Event Data: eventLen
totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + eventLen;
// allocate memory for OSAL hdr + packet
npiPkt_t *message = (npiPkt_t *)ICall_allocMsg(totalLength);
if (message) {
// OSAL message event, status, and pointer to packet
message->hdr.event = HCI_EVENT_PACKET;
message->hdr.status = 0xFF;
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg)
{
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
// fill in length and data pointer
message->pktLen = HCI_EVENT_MIN_LENGTH + eventLen;
message->pData = (uint8 *)(message + 1);
// fill in length and data pointer
msg->pktLen = HCI_EVENT_MIN_LENGTH + eventLen;
msg->pData = (uint8*)(msg+1);
// fill in BLE Complete Event data
message->pData[0] = HCI_EVENT_PACKET;
message->pData[1] = HCI_LE_EVENT_CODE;
message->pData[2] = eventLen;
// fill in BLE Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = HCI_LE_EVENT_CODE;
msg->pData[2] = eventLen;
// populate event data
if (eventLen > 0) {
memcpy(&message->pData[3], pEvent, eventLen);
}
// populate event data
if (eventLen > 0)
{
memcpy(&msg->pData[3], pEvent, eventLen);
NPITask_sendToHost((uint8_t *)message);
}
NPITask_sendToHost((uint8_t *)msg);
}
}
/*********************************************************************
*********************************************************************/
@@ -1,707 +0,0 @@
/******************************************************************************
@file host_test_app_pm.c
@brief This file contains the HostTest sample application for use with the
CC2650 Bluetooth Low Energy Protocol Stack.
Group: WCS, BTS
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2013-2018, Texas Instruments Incorporated
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Texas Instruments Incorporated nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************
Release Name: ble_sdk_2_02_02_25
Release Date: 2018-04-02 18:03:35
*****************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/hal/Hwi.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/drivers/UART.h> //For UART application
#include <icall.h>
#include <string.h>
#include "hal_types.h"
#include "hci_tl.h"
#include "gatt.h"
#include "hci.h"
#include "gapgattserver.h"
#include "gattservapp.h"
#include "gapbondmgr.h"
#include "osal_snv.h"
#include "icall_apimsg.h"
#include "util.h"
#include <ti/mw/display/Display.h>
#include "npi_pm.h"
#include <inc/hw_types.h>
#include "hal_defs.h"
#if defined ( GATT_TEST ) || defined ( GATT_QUAL )
#include "gatttest.h"
#endif
#include "host_test_app.h"
/*********************************************************************
* CONSTANTS
*/
// LE Event Lengths
#define HCI_CMD_COMPLETE_EVENT_LEN 3
#define HCI_CMD_VS_COMPLETE_EVENT_LEN 2
#define HCI_CMD_STATUS_EVENT_LEN 4
// Task configuration
#define HTA_TASK_PRIORITY 1
#define HTA_TASK_STACK_SIZE 644
// NPI Events
#define NPI_WRITECALLBACK_EVENT 0x0002
#define NPI_READ_EVENT 0x0004
#define NPI_MRDY_EVENT 0x0008
/*********************************************************************
* GLOBAL VARIABLES
*/
// Display Interface
Display_Handle dispHandle = NULL;
/*********************************************************************
* LOCAL VARIABLES
*/
// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID selfEntity;
// Semaphore globally used to post events to the application thread
static ICall_Semaphore sem;
// Queue object used for UART TX messages
static Queue_Struct uartTx;
static Queue_Handle uartTxQueue;
// Task configuration
Task_Struct htaTask;
Char htaTaskStack[HTA_TASK_STACK_SIZE];
#if !defined ( GATT_DB_OFF_CHIP )
static uint8 deviceName[GAP_DEVICE_NAME_LEN] = { 0 };
static uint16 appearance = 17;
#endif
// Pointer to last transmitted message
npiPkt_t *pMsgLastBuf = NULL;
// events for application
static uint16_t events = NPI_WRITECALLBACK_EVENT;
// Stack build revision
buildRevision_t buildRev;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void HostTestApp_init(void);
static void HostTestApp_taskFxn(UArg a0, UArg a1);
static void HostTestApp_processGapEvent(ICall_HciExtEvt *pMsg);
//RTOS queue functions
static void HostTestApp_sendMsg(npiPkt_t *pMsgBuf);
//UART callback
Void HostTestApp_writeCallBack(int size);
Void HostTestApp_readCallBack(int size);
static void sendCommandCompleteEvent(uint8 eventCode, uint16 opcode,
uint8 numParam, uint8 *param);
/*********************************************************************
* EXTERN FUNCTIONS
*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn HostTestApp_createTask
*
* @brief Task creation function for the Host Test App.
*
* @param none
*
* @return none
*/
void HostTestApp_createTask(void)
{
Task_Params taskParams;
// Configure task
Task_Params_init(&taskParams);
taskParams.stack = htaTaskStack;
taskParams.stackSize = HTA_TASK_STACK_SIZE;
taskParams.priority = HTA_TASK_PRIORITY;
Task_construct(&htaTask, HostTestApp_taskFxn, &taskParams, NULL);
}
/*********************************************************************
* @fn HostTestApp_init
*
* @brief Called during initialization and contains application
* specific initialization (ie. hardware initialization/setup,
* table initialization, power up notification, etc), and
* profile initialization/setup.
*
* @param none
*
* @return none
*/
static void HostTestApp_init(void)
{
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&selfEntity, &sem);
// Set device's Sleep Clock Accuracy
//HCI_EXT_SetSCACmd(40);
// Create an RTOS queue for messages from stack to be sent to UART
uartTxQueue = Util_constructQueue(&uartTx);
dispHandle = Display_open(Display_Type_LCD, NULL);
// Register for unwanted HCI messages
GAP_RegisterForMsgs(selfEntity);
// Initialize GATT Client
VOID GATT_InitClient();
// Get build revision
VOID Util_buildRevision(&buildRev);
#if !defined ( GATT_DB_OFF_CHIP )
#if defined ( GATT_QUAL )
VOID GATTQual_AddService( GATT_ALL_SERVICES ); // Includes GAP and GATT Services
#else
// Add our services to GATT Server
VOID GGS_AddService( GATT_ALL_SERVICES );
VOID GATTServApp_AddService( GATT_ALL_SERVICES );
#if defined ( GATT_TEST )
VOID GATTTest_AddService( GATT_ALL_SERVICES );
#endif
#endif
// Set device name
if ((buildRev.hostInfo & CENTRAL_CFG) && (buildRev.hostInfo & PERIPHERAL_CFG))
{
memcpy(deviceName, "TI BLE All", 10);
}
else if (buildRev.hostInfo & CENTRAL_CFG)
{
memcpy(deviceName, "TI BLE Central", 14);
}
else if (buildRev.hostInfo & PERIPHERAL_CFG)
{
memcpy(deviceName, "TI BLE Peripheral", 17);
}
else
{
memcpy(deviceName, "TI BLE Unknown", 14);
}
VOID GGS_SetParameter(GGS_DEVICE_NAME_ATT, strlen((char *)deviceName), deviceName);
VOID GGS_SetParameter(GGS_APPEARANCE_ATT, sizeof(uint16), (void*)&appearance);
#endif // GATT_DB_OFF_CHIP
#ifdef TI_DRIVERS_UART_INCLUDED
//Initialize the NPI layer
NPI_InitInterface(UART_INTERFACE, &HostTestApp_writeCallBack,
&HostTestApp_readCallBack);
#elif TI_DRIVERS_SPI_DMA_INCLUDED
//Initialize the NPI layer
NPI_InitInterface(SPI_INTERFACE, &HostTestApp_writeCallBack,
&HostTestApp_readCallBack);
#endif
//Register application with NPI for stack messages to be sent to UART
NPI_RegisterTask(selfEntity);
Display_print0(dispHandle, 0, 0, "TI BLEv2.0");
Display_print0(dispHandle, 1, 0, "HostTestApp");
// Display Host build configuration
if ((buildRev.hostInfo & CENTRAL_CFG) && (buildRev.hostInfo & PERIPHERAL_CFG))
{
Display_print0(dispHandle, 2, 0, "All");
}
else if ((buildRev.hostInfo & CENTRAL_CFG) &&
(buildRev.hostInfo & BROADCASTER_CFG))
{
Display_print0(dispHandle, 2, 0, "Cent+Bcast");
}
else if ((buildRev.hostInfo & PERIPHERAL_CFG) &&
(buildRev.hostInfo & OBSERVER_CFG))
{
Display_print0(dispHandle, 2, 0, "Peri+Observ");
}
else if (buildRev.hostInfo & CENTRAL_CFG)
{
Display_print0(dispHandle, 2, 0, "Central");
}
else if (buildRev.hostInfo & PERIPHERAL_CFG)
{
Display_print0(dispHandle, 2, 0, "Peripheral");
}
else
{
Display_print1(dispHandle, 2, 0, "Unknown build cfg %d", buildRev.hostInfo);
}
}
/*********************************************************************
* @fn HostTestApp_taskFxn
*
* @brief Application task entry point for the Host Test App.
*
* @param none
*
* @return none
*/
static void HostTestApp_taskFxn(UArg a0, UArg a1)
{
// Initialize application
HostTestApp_init();
// Application main loop
for (;;)
{
// Waits for a signal to the semaphore associated with the calling thread.
// Note that the semaphore associated with a thread is signaled when a
// message is queued to the message receive queue of the thread or when
// ICall_signal() function is called onto the semaphore.
ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);
if (errno == ICALL_ERRNO_SUCCESS)
{
ICall_EntityID dest;
ICall_ServiceEnum src;
ICall_HciExtEvt *pMsg = NULL;
if (ICall_fetchServiceMsg(&src, &dest,
(void **)&pMsg) == ICALL_ERRNO_SUCCESS)
{
bool dealloc = true;
if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
{
// Process incoming messages
switch (pMsg->hdr.event)
{
case HCI_GAP_EVENT_EVENT:
HostTestApp_processGapEvent(pMsg);
break;
case HCI_ACL_DATA_PACKET:
case HCI_SCO_DATA_PACKET:
case HCI_EVENT_PACKET:
{
HostTestApp_sendMsg((npiPkt_t *)pMsg);
dealloc = false;
}
break;
default:
break;
}
}
if (dealloc == true)
{
ICall_freeMsg(pMsg);
}
}
}
if (events & NPI_READ_EVENT )
{
events &= ~NPI_READ_EVENT;
NPI_serialPacketParser(); //Call the parser..
}
if (events & NPI_MRDY_EVENT )
{
// This read is initiated to read again and again till you run out of
// bytes. This read was initiated in the callback but is actually done in
// this application thread
events &= ~NPI_MRDY_EVENT;
#ifdef POWER_SAVING
NPI_MrdyEvent();
#endif
}
// Check if write is complete and free the last written buffer
if(events & NPI_WRITECALLBACK_EVENT)
{
if (pMsgLastBuf)
{
ICall_freeMsg(pMsgLastBuf); //Free the NPI/OSAL buffer which was sent
pMsgLastBuf = NULL; //Need to have this to avoid memory leak
}
// If queue is not empty, we did add some frames to it
if (!Queue_empty(uartTxQueue))
{
pMsgLastBuf = (npiPkt_t *)Util_dequeueMsg(uartTxQueue);
if (pMsgLastBuf)
{
// send dequeued element to UART
events &= ~NPI_WRITECALLBACK_EVENT;
NPI_WriteTransport(pMsgLastBuf->pData, pMsgLastBuf->pktLen);
}
}
}
}
}
/*********************************************************************
* @fn HostTestApp_processGapEvent
*
* @brief Process an incoming GAP Event.
*
* @param pMsg - message to process
*
* @return none
*/
static void HostTestApp_processGapEvent(ICall_HciExtEvt *pMsg)
{
switch(pMsg->hdr.status)
{
case HCI_COMMAND_COMPLETE_EVENT_CODE:
{
hciEvt_CmdComplete_t *pkt = (hciEvt_CmdComplete_t *)pMsg;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
}
else
{
osal_msg_hdr_t *msgHdr;
uint8 len;
msgHdr = (osal_msg_hdr_t *)pMsg;
msgHdr--; // Backup to the msg header
len = (uint8)(msgHdr->len - sizeof ( hciEvt_CmdComplete_t ));
sendCommandCompleteEvent(HCI_COMMAND_COMPLETE_EVENT_CODE,
pkt->cmdOpcode, len, pkt->pReturnParam);
}
}
break;
case HCI_DISCONNECTION_COMPLETE_EVENT_CODE:
break;
case HCI_COMMAND_STATUS_EVENT_CODE:
{
hciEvt_CommandStatus_t *pkt = (hciEvt_CommandStatus_t *)pMsg;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
}
// else - drop it for now
}
break;
case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
{
AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
}
break;
case HCI_LE_EVENT_CODE:
break;
case HCI_VE_EVENT_CODE:
{
hciEvt_VSCmdComplete_t *pkt = (hciEvt_VSCmdComplete_t *)pMsg;
if (lastAppOpcodeSent == pkt->cmdOpcode)
{
// app processes this as it was embedded msg to stack
// Reset last opcode sent
lastAppOpcodeSent = 0xFFFF;
}
else
{
sendCommandCompleteEvent(HCI_VE_EVENT_CODE, pkt->cmdOpcode,
pkt->length, pkt->pEventParam);
}
}
break;
default:
break;
}
}
/*********************************************************************
* @fn HostTestApp_writeCallBack
*
* @brief Callback for TX ISR
*
* @param none
*
* @return none
*/
Void HostTestApp_writeCallBack(int size)
{
events |= NPI_WRITECALLBACK_EVENT;
Semaphore_post(sem);
}
/*********************************************************************
* @fn HostTestApp_readCallBack
*
* @brief Callback for RX ISR
*
* @param none
*
* @return none
*/
Void HostTestApp_readCallBack(int size)
{
if ( size == 0xFF )
{
events |= NPI_MRDY_EVENT;
}
else
{
events |= NPI_READ_EVENT;
}
Semaphore_post(sem);
}
/*********************************************************************
* @fn HostTestApp_sendMsg
*
* @brief Sends packet to UART else queues it if not able to do so
*
* @param none
*
* @return none
*/
static void HostTestApp_sendMsg(npiPkt_t *pMsgBuf)
{
if ((events & NPI_WRITECALLBACK_EVENT) && (Queue_empty(uartTxQueue)))
{
events &= ~NPI_WRITECALLBACK_EVENT;
if (pMsgLastBuf)
{
ICall_freeMsg(pMsgLastBuf); //Free the NPI/OSAL buffer which was sent
pMsgLastBuf = NULL; //Need to have this to avoid memory leak
}
pMsgLastBuf = pMsgBuf;
NPI_WriteTransport(pMsgBuf->pData, pMsgBuf->pktLen);
return;
}
// Enqueue the message
Util_enqueueMsg(uartTxQueue, sem, (uint8*)pMsgBuf);
}
//*****************************************************************************
// the function prototypes
/*******************************************************************************
* This generic function sends a Command Complete or a Vendor Specific Command
* Complete Event to the Host.
*
*/
static void sendCommandCompleteEvent(uint8_t eventCode, uint16_t opcode,
uint8_t numParam, uint8_t *param)
{
npiPkt_t *msg;
uint8_t totalLength;
uint8_t txLen = 0; // Length to transmit
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Return Parameters (0..N)
totalLength = sizeof(npiPkt_t) + HCI_EVENT_MIN_LENGTH + numParam;
// adjust the size of the event packet based on event code
// Note: If not a vendor specific event, then the event includes:
// Command Complete Data: Number of HCI Commands Allowed(1) + Command Opcode(2)
// Note: If a vendor specific event, then the event includes:
// Vendor Specific Command Complete Data: Vendor Specific Event Opcode(2)
totalLength += ( (eventCode != HCI_VE_EVENT_CODE) ?
HCI_CMD_COMPLETE_EVENT_LEN :
HCI_CMD_VS_COMPLETE_EVENT_LEN );
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg)
{
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
msg->pData = (uint8*)(msg+1);
// fill in Command Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = eventCode;
txLen += 2;
// check if this isn't a vendor specific event
if ( eventCode != HCI_VE_EVENT_CODE )
{
msg->pData[2] = numParam + HCI_CMD_COMPLETE_EVENT_LEN;
msg->pData[3] = 1;// hciCtrlCmdToken; // event parameter 1
msg->pData[4] = LO_UINT16( opcode ); // event parameter 2
msg->pData[5] = HI_UINT16( opcode ); // event parameter 2
txLen += 4;
// remaining event parameters
(void)memcpy(&msg->pData[6], param, numParam);
txLen += numParam;
}
else // it is a vendor specific event
{
// less one byte as number of complete packets not used in vendor specific event
msg->pData[2] = numParam + HCI_CMD_VS_COMPLETE_EVENT_LEN;
msg->pData[3] = param[0]; // event parameter 0: event opcode LSB
msg->pData[4] = param[1]; // event parameter 1: event opcode MSB
msg->pData[5] = param[2]; // event parameter 2: status
msg->pData[6] = LO_UINT16( opcode ); // event parameter 3: command opcode LSB
msg->pData[7] = HI_UINT16( opcode ); // event parameter 3: command opcode MSB
txLen += 6;
// remaining event parameters
// Note: The event opcode and status were already placed in the msg packet.
(void)memcpy(&msg->pData[8], &param[3], numParam-HCI_EVENT_MIN_LENGTH);
txLen += (numParam-HCI_EVENT_MIN_LENGTH);
}
msg->pktLen = txLen;
HostTestApp_sendMsg((npiPkt_t *)msg);
}
}
/*******************************************************************************
* This generic function sends a Command Complete or a Vendor Specific Command
* Complete Event to the Host.
*
*/
void sendCommandStatusEvent(uint8_t eventCode, uint16_t status, uint16_t opcode)
{
npiPkt_t *msg;
uint8_t totalLength;
// The initial length will be:
// OSAL message header(4) - not part of packet sent to HCI Host!
// Minimum Event Data: Packet Type(1) + Event Code(1) + Length(1)
// Command Status Event Data: Status (1) + Num HCI Cmd Pkt (1) + Cmd Opcode (2)
totalLength = sizeof(npiPkt_t) +
HCI_EVENT_MIN_LENGTH +
HCI_CMD_STATUS_EVENT_LEN;
// allocate memory for OSAL hdr + packet
msg = (npiPkt_t *)ICall_allocMsg(totalLength);
if (msg)
{
// OSAL message event, status, and pointer to packet
msg->hdr.event = HCI_EVENT_PACKET;
msg->hdr.status = 0xFF;
// fill in length and data pointer
msg->pktLen = HCI_EVENT_MIN_LENGTH + HCI_CMD_STATUS_EVENT_LEN;
msg->pData = (uint8*)(msg+1);
// fill in Command Complete Event data
msg->pData[0] = HCI_EVENT_PACKET;
msg->pData[1] = eventCode;
msg->pData[2] = HCI_CMD_STATUS_EVENT_LEN;
msg->pData[3] = status;
msg->pData[4] = 1; // number of HCI command packets
msg->pData[5] = LO_UINT16(opcode); // opcode (LSB)
msg->pData[6] = HI_UINT16(opcode); // opcode (MSB)
HostTestApp_sendMsg((npiPkt_t *)msg);
}
}
/*********************************************************************
*********************************************************************/
@@ -8,7 +8,7 @@
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2013-2018, Texas Instruments Incorporated
All rights reserved.
@@ -44,17 +44,17 @@
Release Date: 2018-04-02 18:03:35
*****************************************************************************/
/*******************************************************************************
* INCLUDES
*/
/*================
==== include ====
===============*/
// clang-format off
#include <xdc/runtime/Error.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
#include <ti/sysbios/BIOS.h>
#include "icall.h"
#include "hal_assert.h"
#include "board.h"
#include "inc/npi_task.h"
@@ -63,78 +63,9 @@
/* Header files required to enable instruction fetch cache */
#include <inc/hw_memmap.h>
#include <driverlib/vims.h>
// clang-format on
#ifndef USE_DEFAULT_USER_CFG
#include "ble_user_config.h"
// BLE user defined configuration
bleUserCfg_t user0Cfg = BLE_USER_CFG;
#endif // USE_DEFAULT_USER_CFG
#include <ti/mw/display/Display.h>
#ifdef USE_FPGA
#include <inc/hw_prcm.h>
#endif // USE_FPGA
/*******************************************************************************
* MACROS
*/
/*******************************************************************************
* CONSTANTS
*/
#if defined( USE_FPGA )
#define RFC_MODE_BLE PRCM_RFCMODESEL_CURR_MODE1
#define RFC_MODE_ANT PRCM_RFCMODESEL_CURR_MODE4
#define RFC_MODE_EVERYTHING_BUT_ANT PRCM_RFCMODESEL_CURR_MODE5
#define RFC_MODE_EVERYTHING PRCM_RFCMODESEL_CURR_MODE6
//
#define SET_RFC_BLE_MODE(mode) HWREG( PRCM_BASE + PRCM_O_RFCMODESEL ) = (mode)
#endif // USE_FPGA
/*******************************************************************************
* TYPEDEFS
*/
/*******************************************************************************
* LOCAL VARIABLES
*/
/*******************************************************************************
* GLOBAL VARIABLES
*/
#ifdef CC1350_LAUNCHXL
#ifdef POWER_SAVING
// Power Notify Object for wake-up callbacks
Power_NotifyObj rFSwitchPowerNotifyObj;
static uint8_t rFSwitchNotifyCb(uint8_t eventType, uint32_t *eventArg,
uint32_t *clientArg);
#endif //POWER_SAVING
PIN_State radCtrlState;
PIN_Config radCtrlCfg[] =
{
Board_DIO1_RFSW | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* RF SW Switch defaults to 2.4GHz path*/
Board_DIO30_SWPWR | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* Power to the RF Switch */
PIN_TERMINATE
};
PIN_Handle radCtrlHandle;
#endif //CC1350_LAUNCHXL
/*******************************************************************************
* EXTERNS
*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
extern Display_Handle dispHandle;
/*******************************************************************************
/**
* @fn Main
*
* @brief Application Main
@@ -149,228 +80,30 @@ extern Display_Handle dispHandle;
*
* @return None.
*/
int main()
{
#if defined( USE_FPGA )
HWREG(PRCM_BASE + PRCM_O_PDCTL0) &= ~PRCM_PDCTL0_RFC_ON;
HWREG(PRCM_BASE + PRCM_O_PDCTL1) &= ~PRCM_PDCTL1_RFC_ON;
#endif // USE_FPGA
int main() {
PIN_init(BoardGpioInitTable);
/* Register Application callback to trap asserts raised in the Stack */
RegisterAssertCback(AssertHandler);
// Enable iCache prefetching
VIMSConfigure(VIMS_BASE, TRUE, TRUE);
PIN_init(BoardGpioInitTable);
// Enable cache
VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
#ifdef CC1350_LAUNCHXL
// Enable 2.4GHz Radio
radCtrlHandle = PIN_open(&radCtrlState, radCtrlCfg);
/* Initialize ICall module */
ICall_init();
#ifdef POWER_SAVING
Power_registerNotify(&rFSwitchPowerNotifyObj,
PowerCC26XX_ENTERING_STANDBY | PowerCC26XX_AWAKE_STANDBY,
(Power_NotifyFxn) rFSwitchNotifyCb, NULL);
#endif //POWER_SAVING
#endif //CC1350_LAUNCHXL
/* Start tasks of external images */
ICall_createRemoteTasks();
#if defined( USE_FPGA )
// set RFC mode to support BLE
// Note: This must be done before the RF Core is released from reset!
SET_RFC_BLE_MODE(RFC_MODE_BLE);
#endif // USE_FPGA
/* Kick off application */
HostTestApp_createTask();
// Enable iCache prefetching
VIMSConfigure(VIMS_BASE, TRUE, TRUE);
/* Kick off NPI */
NPITask_createTask(ICALL_SERVICE_CLASS_BLE);
// Enable cache
VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
/* enable interrupts and start SYS/BIOS */
BIOS_start();
#if !defined( POWER_SAVING ) || defined( USE_FPGA )
/* Set constraints for Standby, powerdown and idle mode */
// PowerCC26XX_SB_DISALLOW may be redundant
Power_setConstraint(PowerCC26XX_SB_DISALLOW);
Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
#endif // POWER_SAVING | USE_FPGA
/* Initialize ICall module */
ICall_init();
/* Start tasks of external images */
ICall_createRemoteTasks();
/* Kick off application */
HostTestApp_createTask();
/* Kick off NPI */
NPITask_createTask(ICALL_SERVICE_CLASS_BLE);
/* enable interrupts and start SYS/BIOS */
BIOS_start();
return 0;
return 0;
}
/*******************************************************************************
* @fn AssertHandler
*
* @brief This is the Application's callback handler for asserts raised
* in the stack. When EXT_HAL_ASSERT is defined in the Stack
* project this function will be called when an assert is raised,
* and can be used to observe or trap a violation from expected
* behavior.
*
* As an example, for Heap allocation failures the Stack will raise
* HAL_ASSERT_CAUSE_OUT_OF_MEMORY as the assertCause and
* HAL_ASSERT_SUBCAUSE_NONE as the assertSubcause. An application
* developer could trap any malloc failure on the stack by calling
* HAL_ASSERT_SPINLOCK under the matching case.
*
* An application developer is encouraged to extend this function
* for use by their own application. To do this, add hal_assert.c
* to your project workspace, the path to hal_assert.h (this can
* be found on the stack side). Asserts are raised by including
* hal_assert.h and using macro HAL_ASSERT(cause) to raise an
* assert with argument assertCause. the assertSubcause may be
* optionally set by macro HAL_ASSERT_SET_SUBCAUSE(subCause) prior
* to asserting the cause it describes. More information is
* available in hal_assert.h.
*
* input parameters
*
* @param assertCause - Assert cause as defined in hal_assert.h.
* @param assertSubcause - Optional assert subcause (see hal_assert.h).
*
* output parameters
*
* @param None.
*
* @return None.
*/
void AssertHandler(uint8 assertCause, uint8 assertSubcause)
{
// Open the display if the app has not already done so
if ( !dispHandle )
{
dispHandle = Display_open(Display_Type_LCD, NULL);
}
Display_print0(dispHandle, 0, 0, ">>>STACK ASSERT");
// check the assert cause
switch (assertCause)
{
// This assert is raised from the BLE Stack when a malloc failure occurs.
case HAL_ASSERT_CAUSE_OUT_OF_MEMORY:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> OUT OF MEMORY!");
break;
case HAL_ASSERT_CAUSE_INTERNAL_ERROR:
// check the subcause
if (assertSubcause == HAL_ASSERT_SUBCAUSE_FW_INERNAL_ERROR)
{
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> INTERNAL FW ERROR!");
}
else
{
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> INTERNAL ERROR!");
}
break;
// An assert originating from an ICall failure.
case HAL_ASSERT_CAUSE_ICALL_ABORT:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> ICALL ABORT!");
HAL_ASSERT_SPINLOCK;
break;
default:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> DEFAULT SPINLOCK!");
HAL_ASSERT_SPINLOCK;
}
return;
}
/*******************************************************************************
* @fn exceptionHandler
*
* @brief Generic spinlock to trap RTOS raised errors.
*
* input parameters
*
* @param None.
*
* output parameters
*
* @param None.
*
* @return None.
*/
void exceptionHandler( void )
{
volatile uint8 i = 1;
while(i);
}
/*******************************************************************************
* @fn smallErrorHook
*
* @brief Error handler to be hooked into TI-RTOS.
*
* input parameters
*
* @param eb - Pointer to Error Block.
*
* output parameters
*
* @param None.
*
* @return None.
*/
void smallErrorHook(Error_Block *eb)
{
for (;;);
}
#if defined (CC1350_LAUNCHXL) && defined (POWER_SAVING)
/*******************************************************************************
* @fn rFSwitchNotifyCb
*
* @brief Power driver callback to toggle RF switch on Power state
* transitions.
*
* input parameters
*
* @param eventType - The state change.
* @param eventArg - Not used.
* @param clientArg - Not used.
*
* @return Power_NOTIFYDONE to indicate success.
*/
static uint8_t rFSwitchNotifyCb(uint8_t eventType, uint32_t *eventArg,
uint32_t *clientArg)
{
if (eventType == PowerCC26XX_ENTERING_STANDBY)
{
// Power down RF Switch
PIN_setOutputValue(radCtrlHandle, Board_DIO30_SWPWR, 0);
}
else if (eventType == PowerCC26XX_AWAKE_STANDBY)
{
// Power up RF Switch
PIN_setOutputValue(radCtrlHandle, Board_DIO30_SWPWR, 1);
}
// Notification handled successfully
return Power_NOTIFYDONE;
}
#endif //CC1350_LAUNCHXL || POWER_SAVING
/*******************************************************************************
*/
@@ -0,0 +1,183 @@
#ifndef CC2650_MASTER_H
#define CC2650_MASTER_H
/*================
==== include ====
================*/
#include <ti/sysbios/knl/Semaphore.h>
#include "master_mem.h"
#include "master_pin.h"
#include "master_spi.h"
/*======================
==== event control ====
=====================*/
uint16_t EVENT_MASK = 0;
extern ICall_Semaphore semaphore;
#define EVT_PIN_RESET 0x0010
#define EVT_PIN_REQST 0x0020
/**
* test event [flag] has been enabled.
*/
#define flag_mask(flag) ((EVENT_MASK & (flag)) != 0)
/**
* enable event [flag].
*/
#define flag_enable(flag) \
do { \
uint8 __key = Hwi_disable(); \
EVENT_MASK |= (uint16_t)(flag); \
Hwi_restore(__key); \
} while (0)
/**
* disable event [flag].
*/
#define flag_disable(flag) \
do { \
uint8 __key = Hwi_disable(); \
EVENT_MASK &= ~((uint16_t)(flag)); \
Hwi_restore(__key); \
} while (0)
/**
* fire a event with [flag].
*/
#define flag_notify(flag) \
do { \
uint8 __key = Hwi_disable(); \
EVENT_MASK |= (uint16_t)(flag); \
Hwi_restore(__key); \
Semaphore_post(semaphore); \
} while (0)
/*======================
==== utility macro ====
=====================*/
#define unsafe_memcpy(p, src, len) \
do { \
memcpy(p, src, len); \
p += len; \
} while (0)
/*=========================
==== function declare ====
========================*/
static void master_init();
static void master_event_handle();
struct void master_handle_notify(uint16 length, uint8 *value);
struct void master_switch_memory();
/*========================
==== notify variable ====
=======================*/
#define MEM_META_LENGTH 4
static uint8 mem_sel = 0;
static uint16_t not_counter = 0; // writing counter, increase when notify
static uint16_t not_offset = 0; // writing pointer, current not writing index
/*===========================
==== function implement ====
==========================*/
#define master_reset() \
do { \
not_counter = 0; \
not_offset = MEM_META_LENGTH; \
mem_sel = 0; \
master_mem_select(mem_sel); \
} while (0)
static void master_init() {
master_pin_open();
master_spi_open();
master_mem_init();
master_reset();
}
static void master_event_handle() {}
static void master_pin_callback(PIN_Handle handle, PIN_Id pin) {
switch (pin) {
case PIN_MEM_RST:
// memory reset
flag_enable(EVT_PIN_RESET);
break;
case PIN_MEM_REQ:
// memory switch request
flag_enable(EVT_PIN_REQST);
break;
}
}
struct void master_handle_notify(uint16 length, uint8 *value) {
if (!master_pin_input(PIN_MEM_RST) || flag_mask(EVT_PIN_RESET)) {
// ignore all incoming notify;
flag_disable(EVT_PIN_RESET);
master_reset();
return;
}
uint8_t counter = not_counter++;
// localize current buffer
uint8_t *p = master_mem_buffer;
// update offset
uint32_t cnt_offset = not_offset;
not_offset = cnt_offset + 3 + length;
*p++ = MEM_INS_WRITE; // instruction
*p++ = (uint8_t)((cnt_offset >> 8) & 0xFF); // address
*p++ = (uint8_t)(cnt_offset & 0xFF); // address
*p++ = 0xFF; // data header
*p++ = counter; // data counter
*p++ = length; // data content length
unsafe_memcpy(p, value, length); // data content
master_mem_submit(p - master_mem_buffer);
if (master_pin_input(PIN_MEM_BZY) && //
(not_offset >= MEM_SWITCH_THRESHOLD || flag_mask(EVT_PIN_REQST))) {
flag_disable(EVT_PIN_REQST);
master_switch_memory();
}
master_pin_output(PIN_LED_GRN, not_counter & 0x10);
}
struct void master_switch_memory() {
uint16_t cnt_offset = not_offset;
not_offset = MEM_META_LENGTH;
// localize current buffer
uint8_t *p = spi_tx_buffer;
*p++ = MEM_INS_WRITE; // instruction
*p++ = 0; // address
*p++ = 0; // address
*p++ = (uint8_t)((cnt_offset >> 8) & 0xFF); // data: notify data length
*p++ = (uint8_t)(cnt_offset & 0xFF); // data: notify data length
*p++ = 0;
*p++ = 0;
master_mem_submit(p - master_mem_buffer);
// switch memory
master_mem_select((mem_sel++) & 0x01);
master_pin_output(PIN_LED_RED, mem_sel & 0x10);
}
#endif // CC2650_MASTER_H
@@ -0,0 +1,26 @@
#ifndef MASTER_PIN_LP_H
#define MASTER_PIN_LP_H
#ifndef CC2650_LAUNCHXL
#error "CC2650_LAUNCHXL not defined"
#endif
#define PIN_LED_RED IOID_6
#define PIN_LED_GRN IOID_6
#define PIN_MEM_RST IOID_10
#define PIN_MEM_BZY IOID_11
#define PIN_MEM_REQ IOID_12
#define PIN_MEM_SEL IOID_15
#define PIN_SPI_CS IOID_14
#define PIN_SPI_CK Board_SPI0_CLK
#define PIN_SPI_DI Board_SPI0_MISO
#define PIN_SPI_DO Board_SPI0_MOSI
#define PIN_DEBUG_1 IOID_4
#define PIN_DEBUG_2 IOID_5
#define PIN_DEBUG_3 IOID_21
#define PIN_DEBUG_4 IOID_22
#endif MASTER_PIN_LP_H
@@ -0,0 +1,26 @@
#ifndef MASTER_PIN_MA_H
#define MASTER_PIN_MA_H
#ifndef BOOSTXL_CC2650MA
#error "BOOSTXL_CC2650MA not defined"
#endif
#define PIN_LED_RED IOID_UNUSED
#define PIN_LED_GRN IOID_UNUSED
#define PIN_MEM_RST DIO4
#define PIN_MEM_SEL DIO8
#define PIN_MEM_BZY DIO13
#define PIN_MEM_REQ DIO14
#define PIN_SPI_CS DIO9
#define PIN_SPI_CK Board_SPI0_CLK // DIO10
#define PIN_SPI_DI Board_SPI0_MISO // DIO12
#define PIN_SPI_DO Board_SPI0_MOSI // DIO11
#define PIN_DEBUG_1 IOID_UNUSED
#define PIN_DEBUG_2 IOID_UNUSED
#define PIN_DEBUG_3 IOID_UNUSED
#define PIN_DEBUG_4 IOID_UNUSED
#endif MASTER_PIN_MA_H
@@ -0,0 +1,33 @@
#ifndef MASTER_MEM_H
#define MASTER_MEM_H
#include "master_pin.h"
#include "master_spi.h"
// clang-format off
#define MEM_BUFFER_SIZE SPI_TX_BUFFER_SIZE
#define MEM_SWITCH_THRESHOLD 0x1000
#define MSM_REG_WRITE 0x01
#define MEM_INS_WRITE 0x02
#define MEM_INS_READ 0x03
#define MEM_REG_READ 0x05
// clang-format on
#define master_mem_buffer master_tx_buffer
#define master_mem_select(value) master_pin_output(PIN_MEM_SEL, (value) ? 1 : 0)
#define master_mem_submit(len) master_spi_transaction(len)
#define master_mem_init() \
do { \
master_mem_buffer[0] = MSM_REG_WRITE; \
master_mem_buffer[1] = 0b01000011; \
master_mem_select(1); \
master_mem_submit(2); \
master_mem_select(0); \
master_mem_submit(2); \
} while (0)
#endif // MASTER_MEM_H
@@ -0,0 +1,63 @@
#ifndef MASTER_PIN_H
#define MASTER_PIN_H
#include <Board.h>
#include <ti/drivers/PIN.h>
#if defined(CC2650_LAUNCHXL)
#include "lp/master_pin.h"
#elif defined(BOOSTXL_CC2650MA)
#include "ma/master_pin.h"
#endif
static PIN_State master_pins_state;
static PIN_Handle master_pins_handle;
static PIN_Config master_pin_config_table[] = { //
// memory select
PIN_MEM_SEL | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
// master side is reading buffer.
PIN_MEM_BZY | PIN_INPUT_EN | PIN_PULLUP | PIN_HYSTERESIS,
// master side request to switch buffer
PIN_MEM_REQ | PIN_INPUT_EN | PIN_PULLUP | PIN_HYSTERESIS,
// memory reset reset
PIN_MEM_RST | PIN_INPUT_EN | PIN_PULLUP | PIN_HYSTERESIS,
// spi chip select, deprecate native CS pin
PIN_SPI_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,
// debug pin
PIN_DEBUG_1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,
PIN_DEBUG_2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,
PIN_DEBUG_3 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,
PIN_DEBUG_4 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,
// LED
PIN_LED_RED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_LED_GRN | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
//
PIN_TERMINATE};
static void master_pin_callback(PIN_Handle handle, PIN_Id pin);
#define master_pin_open() \
do { \
master_pins_handle = PIN_open(&master_pins_state, master_pin_config_table); \
PIN_registerIntCb(master_pins_handle, master_pin_callback); \
PIN_setInterrupt(master_pins_handle, HTA_MEM_RST | PIN_IRQ_NEGEDGE); \
PIN_setInterrupt(master_pins_handle, HTA_MEM_REQ | PIN_IRQ_NEGEDGE); \
} while (0)
#define master_pin_add(configuration) PIN_add(master_pins_handle, configuration)
#define master_pin_remove(pin) PIN_remove(master_pins_handle, pin)
#define master_pin_close() PIN_close(master_pins_handle)
#define master_pin_output(pin, value) PIN_setOutputValue(master_pins_handle, PIN_ID(pin), (value))
#define master_pin_input(pin) PIN_getInputValue(PIN_ID(pin))
#endif MASTER_PIN_H
@@ -0,0 +1,43 @@
#ifndef MASTER_SPI_H
#define MASTER_SPI_H
// clang-format off
#include <ti/drivers/SPI.h>
#include <ti/drivers/dma/UDMACC26XX.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
// clang-format on
#include "master_pin.h"
#define SPI_TX_BUFFER_SIZE 50
static uint8_t master_tx_buffer[SPI_TX_BUFFER_SIZE] = {0};
static SPI_Handle master_spi_handle;
static SPI_Transaction master_spi_transaction;
#define master_spi_open() \
do { \
SPI_init(); \
SPI_Params spi_parameter; \
SPI_Params_init(&spi_parameter); \
spi_parameter.transferMode = SPI_MODE_BLOCKING; \
spi_parameter.mode = SPI_MASTER; \
spi_parameter.bitRate = 12000000; \
spi_parameter.transferTimeout = 1000; \
spi_parameter.dataSize = 8; \
spi_parameter.frameFormat = SPI_POL0_PHA0; \
master_spi_handle = SPI_open(Board_SPI0, &spi_parameter); \
} while (0)
#define master_spi_transaction(len) \
do { \
master_spi_transaction.txBuf = master_tx_buffer; \
master_spi_transaction.rxBuf = NULL; \
master_spi_transaction.count = (len); \
master_pin_output(PIN_SPI_CS, 0); \
SPI_transfer(master_spi_handle, &master_spi_transaction); \
master_pin_output(PIN_SPI_CS, 1); \
} while (0)
#endif // MASTER_SPI_H
@@ -0,0 +1,443 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
/*
Characteristic
==============
file defined:
`simplelink/ble_sdk_2_02_02_25/src/profiles/simple_profile/cc26xx/simple_gatt_profile.c`
| char | UUID | handle | property | description |
| ==== | ==== | ====== | ======== | =========================== |
| 1 | FFF1 | 0x001E | ------r- | feature list |
| 2 | FFF2 | 0x0021 | ------r- | command return channel |
| 3 | FFF3 | 0x0024 | ----w--- | instruction input channel |
| 4 | FFF4 | 0x0027 | ---n---- | data notify channel |
| 5 | FFF5 | 0x002B | ----w-r- | debug use channel |
Instruction Specification
=========================
file defined:
Bio_Pro_Sci /  / Pi3/DataServer / CC2650 / CC2650誘銵
```
struct instruction {
unsigned int ins_type :4; // instruction type
unsigned int device_id :4; // device ID
unsigned int ins_oper :4; // instruction operator
unsigned int ins_len :4; // data length
char ins_data[ins_len]; // data content
};
```
instruction type
| ins_type | value | description |
| ============ | ===== | ========================== |
| INS_TYPE_RIS | 0x30 | real device instruction |
| INS_TYPE_VIS | 0xC0 | virtual device instruction |
| INS_TYPE_CIS | 0x70 | command instruction |
instruction operator
| ins_oper | value | description |
| ======== | ===== | ======================== |
| | 0x00 | not used |
| | 0x10 | not used |
| | 0x20 | not used |
| VIS_ASK | 0x30 | not used |
| | 0x40 | not used |
| | 0x50 | not used |
| VIS_INT | 0x60 | interrupt device |
| | 0x70 | not used |
| | 0x80 | not used |
| VIS_FUH | 0x90 | not used |
| VIS_CAL | 0xA0 | not used |
| | 0xB0 | not used |
| VIS_STI | 0xC0 | device start working |
| | 0xD0 | not used |
| | 0xE0 | not used |
| VIS_RST | 0xF0 | device reset |
| CIS_NOP | 0x00 | nothing (clean char2) |
| CIS_VOLT | 0x10 | report battery voltage |
| CIS_LED | 0x20 | control device LED |
| | 0x30 | not defined |
| | 0x40 | not defined |
| | 0x50 | not defined |
| | 0x60 | not defined |
| | 0x70 | not defined |
| | 0x80 | not defined |
| | 0x90 | not defined |
| | 0xA0 | not defined |
| | 0xB0 | not defined |
| | 0xC0 | not defined |
| | 0xD0 | not defined |
| | 0xE0 | not defined |
| | 0xF0 | not defined |
*/
#ifndef HEADSTAGE_H
#define HEADSTAGE_H
/*================
==== include ====
================*/
#include <ti/sysbios/knl/Semaphore.h>
#include "simple_gatt_profile.h"
/*======================
==== event control ====
=====================*/
uint16_t EVENT_MASK = 0;
static ICall_Semaphore semaphore;
// clang-format off
#define EVT_ALL 0xFFFF // all event mask
#define EVT_CONNECTED 0x4000 // event when device be connected
#define EVT_DISCONNECTED 0x8000 // event when device disconnected
#define EVT_PERIODIC_0 0x0100
#define EVT_PERIODIC_1 0x0200
#define EVT_PERIODIC_2 0x0400
#define EVT_PERIODIC_3 0x0800
// clang-format on
/**
* test event [flag] has been enabled.
*/
#define flag_mask(flag) ((EVENT_MASK & (flag)) != 0)
/**
* enable event [flag].
*/
#define flag_enable(flag) \
do { \
uint8 __key = Hwi_disable(); \
EVENT_MASK |= (uint16_t)(flag); \
Hwi_restore(__key); \
} while (0)
/**
* disable event [flag].
*/
#define flag_disable(flag) \
do { \
uint8 __key = Hwi_disable(); \
EVENT_MASK &= ~((uint16_t)(flag)); \
Hwi_restore(__key); \
} while (0)
/**
* fire a event with [flag].
*/
#define flag_notify(flag) \
do { \
uint8 __key = Hwi_disable(); \
EVENT_MASK |= (uint16_t)(flag); \
Hwi_restore(__key); \
Semaphore_post(semaphore); \
} while (0)
/*=======================
==== characteristic ====
=======================*/
// feature list characteristic
#define BLE_FLS_BUFF_CHAR SIMPLEPROFILE_CHAR1
#define BLE_FLS_BUFF_SIZE SIMPLEPROFILE_CHAR1_LEN
// command return characteristic
#define BLE_CDR_BUFF_CHAR SIMPLEPROFILE_CHAR2
#define BLE_CDR_BUFF_SIZE SIMPLEPROFILE_CHAR2_LEN
// instruction input characteristic
#define BLE_INS_BUFF_CHAR SIMPLEPROFILE_CHAR3
#define BLE_INS_BUFF_SIZE SIMPLEPROFILE_CHAR3_LEN
// data notify characteristic
#define BLE_NOT_BUFF_CHAR SIMPLEPROFILE_CHAR4
#define BLE_NOT_BUFF_SIZE SIMPLEPROFILE_CHAR4_LEN
// debug use characteristic
#define BLE_DEBUG_BUFF_CHAR SIMPLEPROFILE_CHAR5
#define BLE_DEBUG_BUFF_SIZE SIMPLEPROFILE_CHAR5_LEN
/*================================
==== command/operation macro ====
===============================*/
// clang-format off
// instruction type
#define INS_TYPE_RIS 0x30
#define INS_TYPE_VIS 0xC0
#define INS_TYPE_CIS 0x70
// VIS operator
#define VIS_ASK 0x30
#define VIS_INT 0x60
#define VIS_FUH 0x90
#define VIS_CAL 0xA0
#define VIS_STI 0xC0
#define VIS_RST 0xF0
// CIS operator
#define CIS_NOP 0x00
#define CIS_VOLT 0x10
#define CIS_LED 0x20
// CIS return status code
#define CDR_SUCCESS 0x0
#define CDR_FAILURE 0x1
#define CDR_INV_PAR 0x2
#define CDR_EOD 0xF
// clang-format on
/*======================
==== utility macro ====
=====================*/
#define _B_4b4b(a, b) ((((a) << 4) & 0xF0) | ((b)&0x0F))
#define _B_flip2(a) \
({ \
uint8_t _a = (a)&0x03; \
((_a & 0x02) >> 1) | ((_a & 0x01) << 1); \
})
#define _B_flip3(a) \
({ \
uint8_t _a = (a)&0x07; \
((_a & 0x04) >> 2) | (_a & 0x02) | ((_a & 0x01) << 2); \
})
#define _B_flip4(a) \
({ \
uint8_t _a = (a)&0x0F; \
((_a & 0x08) >> 3) | ((_a & 0x04) >> 1) | ((_a & 0x02) << 1) | ((_a & 0x01) << 3); \
})
#define _B_flip5(a) \
({ \
uint8_t _a = (a)&0x1F; \
((_a & 0x10) >> 4) | ((_a & 0x08) >> 2) | (_a & 0x04) | ((_a & 0x02) << 2) | ((_a & 0x01) << 4); \
})
#define unsafe_memcpy(p, src, len) \
do { \
memcpy(p, src, len); \
p += len; \
} while (0)
/**
* make task sleep in certain [ms].
* count with cpu tick.
*/
#define headstage_cpu_delay_ms(ms) CPUdelay(ms * 16000)
/**
* make task sleep in certain [us].
* count with cpu tick.
*/
#define headstage_cpu_delay_us(ms) CPUdelay(ms * 16)
/*======================================
==== abstract function declaration ====
=====================================*/
/**
* initialize.
*/
static void headstage_init();
/**
* decoding RIS.
*
* @param ins_len: instruction length
* @param instruction: instruction content
*/
static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t *instruction);
/**
* decoding VIS.
*
* @param vis_oper: VIS operator.
*/
static void headstage_update_vis_instruction(uint8_t vis_oper);
/*========================
==== global property ====
========================*/
/**
* device/chip ID. updated by system.
*/
static uint8_t CHIP_ID = 0;
/**
* connection handle. updated by system.
*/
static uint16_t CONNECT_HANDLE = 0;
/*====================
==== event table ====
====================*/
/**
* event table entry.
*/
typedef struct {
/**
* event mask.
*/
uint16_t event_mask;
/**
* event callback. invoked by system when system [EVENT_MASK] set with
* [event_mask] bits.
*/
void (*event_callback)();
} EventTableEntry;
/*==========================================
==== device implement implement header ====
=========================================*/
#include "headstage_zm.h"
/*======================
==== main function ====
======================*/
static EventTableEntry EVENT_TABLE[] = { //
#ifdef HEADSTAGE_TNI_H
{EVT_ALL, &headstage_tni_event},
#endif
#ifdef HEADSTAGE_UNI_H
{EVT_ALL, &headstage_uni_event},
#endif
#ifdef HEADSTAGE_ZM_H
{EVT_ALL, &headstage_zm_event},
#endif
#ifdef HEADSTAGE_STI_H
{EVT_ALL, &headstage_sti_event},
#endif
// terminated
{0, NULL}};
/**
* system event handle. It go through [EVENT_TABLE] and invoke event callback
* if event_mask bits set.
*/
static void headstage_event_handle() {
for (EventTableEntry *entry = EVENT_TABLE; EVENT_MASK && entry->event_mask; entry++) {
if (entry->event_callback && flag_mask(entry->event_mask)) {
entry->event_callback();
}
}
// remove system one-shot flag
flag_disable(0xF0000000);
}
/**
* system handle for instruction input.
*/
static void headstage_update_instruction(uint8_t *instruction) {
static uint8_t cdr_buf[BLE_CDR_BUFF_SIZE] = {0};
uint8_t ins_type = instruction[0] & 0xF0;
CHIP_ID = instruction[0] & 0x0F;
uint8_t ins_oper = instruction[1] & 0xF0;
uint8_t ins_len = instruction[1] & 0x0F;
switch (ins_type) {
case INS_TYPE_RIS: {
headstage_update_ris_instruction(ins_len, instruction + 2);
break;
}
case INS_TYPE_VIS: {
headstage_update_vis_instruction(ins_oper);
break;
}
case INS_TYPE_CIS: {
switch (ins_oper) {
case CIS_NOP: {
// nothing
cdr_buf[0] = _B_4b4b(CIS_NOP, CHIP_ID);
cdr_buf[1] = _B_4b4b(CDR_SUCCESS, 0);
SimpleProfile_SetParameter(BLE_CDR_BUFF_CHAR, 2, cdr_buf);
break;
}
#ifdef HEADSTAGE_CIS_VOLT_H
case CIS_VOLT: {
uint8_t status = headstage_update_vis_volt(ins_len, instruction + 2, cdr_buf + 2);
cdr_buf[0] = _B_4b4b(CIS_VOLT, CHIP_ID);
cdr_buf[1] = status;
SimpleProfile_SetParameter(BLE_CDR_BUFF_CHAR, BLE_CDR_BUFF_SIZE, cdr_buf);
break;
}
#endif
#ifdef HEADSTAGE_CIS_LED_H
case CIS_LED: {
uint8_t status = headstage_update_vis_led(ins_len, instruction + 2, cdr_buf + 2);
cdr_buf[0] = _B_4b4b(CIS_LED, CHIP_ID);
cdr_buf[1] = status;
SimpleProfile_SetParameter(BLE_CDR_BUFF_CHAR, BLE_CDR_BUFF_SIZE, cdr_buf);
break;
}
#endif
default: {
cdr_buf[0] = _B_4b4b(ins_oper, CHIP_ID);
cdr_buf[1] = _B_4b4b(CDR_FAILURE, 0);
SimpleProfile_SetParameter(BLE_CDR_BUFF_CHAR, BLE_CDR_BUFF_SIZE, cdr_buf);
break;
}
}
}
}
}
/**
* system handle for characteristic updated.
*/
static void headstage_characteristic_updated(uint8_t characteristic) {
static uint8_t ins_buf[BLE_INS_BUFF_SIZE] = {0};
static uint8_t dbg_buf[BLE_DEBUG_BUFF_SIZE] = {0};
switch (characteristic) {
case BLE_INS_BUFF_CHAR:
SimpleProfile_GetParameter(BLE_INS_BUFF_CHAR, ins_buf);
headstage_update_instruction(ins_buf);
break;
#ifdef HEADSTAGE_DEBUG_H
case BLE_DEBUG_BUFF_CHAR: {
SimpleProfile_GetParameter(BLE_DEBUG_BUFF_CHAR, dbg_buf);
uint8_t data_length = headstage_debug_instruction(dbg_buf);
if (data_length) {
SimpleProfile_SetParameter(BLE_DEBUG_BUFF_CHAR, data_length, dbg_buf);
}
break;
}
#endif
}
}
#endif // HEADSTAGE_H
@@ -0,0 +1,17 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_ARM_H
#define HEADSTAGE_ARM_H
static void headstage_arm_append_ramp_data(uint8_t *buff) {
static uint16_t headstage_ramp_data_counter = 0;
uint16_t v = headstage_ramp_data_counter++;
buff[0] = 0xB0 | (0x0F & (uint8_t)(v >> 6));
buff[1] = (uint8_t)(v << 2);
}
// HEADSTAGE_ARM_H
#endif
@@ -0,0 +1,101 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_LED_H
#error "headstage_led.h not included"
#endif
#ifndef HEADSTAGE_CIS_LED_H
#define HEADSTAGE_CIS_LED_H
// clang-format off
#define CIS_LED_DISABLE 0x00
#define CIS_LED_ENABLE 0x01
#define CIS_LED_PATTERN 0x10
#define CIS_LED_SET 0x20
// clang-format on
#define LED_PATTERN_SIZE 0
// static LEDParameter LED_PATTERN_TABLE[] = {};
static void headstage_cis_led_enable(uint8_t enable);
/**
* @return: CDR_SUCCESS
*/
static uint8_t headstage_cis_led_set_pattern(uint8_t pattern);
/**
* @para pattern: pattern number
* @para parameter: led parameter, NULL to unset
* @return: CDR_SUCCESS
*/
static uint8_t headstage_cis_led_set_value(uint8_t pattern, //
LEDParameter *parameter);
/*
* @return: _B_4b4b(CDR_SUCCESS, length), or others,
*/
static uint8_t headstage_update_vis_led(uint8_t ins_len, //
uint8_t *instruction,
uint8_t *cdr_buf) {
uint8_t led_oper = instruction[0];
switch (led_oper) {
case CIS_LED_DISABLE:
case CIS_LED_ENABLE:
if (ins_len == 1) {
headstage_cis_led_enable(led_oper);
return _B_4b4b(CDR_SUCCESS, 0);
} else {
break;
}
case CIS_LED_PATTERN:
if (ins_len == 1) {
cdr_buf[0] = LED_PATTERN_SIZE;
return _B_4b4b(CDR_SUCCESS, 1);
} else if (ins_len == 2) {
uint8_t pattern = instruction[1];
uint8_t status = headstage_cis_led_set_pattern(pattern);
return _B_4b4b(status, 0);
} else {
break;
}
case CIS_LED_SET:
if (ins_len == 2) {
uint8_t pattern = instruction[1];
uint8_t status = headstage_cis_led_set_value(pattern, NULL);
return _B_4b4b(status, 0);
} else if (ins_len == 7) {
uint8_t pattern = instruction[1];
LEDParameter parameter = {
// clang-format off
.luminance = instruction[2],
.red = instruction[3],
.green = instruction[4],
.blue = instruction[5],
.duration = (instruction[6] >> 4) & 0xF,
.duty_cycle = instruction[6] & 0xF
// clang-format on
};
uint8_t status = headstage_cis_led_set_value(pattern, &parameter);
return _B_4b4b(status, 0);
} else {
break;
}
}
return _B_4b4b(CDR_INV_PAR, 0);
}
/*===========================
==== function implement ====
==========================*/
#endif // HEADSTAGE_CIS_LED_H
@@ -0,0 +1,37 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_CIS_VOLT_H
#define HEADSTAGE_CIS_VOLT_H
static void headstage_cis_volt(uint8_t second);
/*
* @return: _B_4b4b(CDR_SUCCESS, length), or others,
*/
static uint8_t headstage_update_vis_volt(uint8_t ins_len, //
uint8_t *instruction,
uint8_t *cdr_buf) {
if (ins_len == 0) {
uint16_t volt_value = headstage_cis_volt(0);
cdr_buf[0] = (volt_value)&0xFF;
cdr_buf[1] = (volt_value >> 8)&0xFF;
return _B_4b4b(CDR_SUCCESS, 2);
} else if (ins_len == 1) {
headstage_cis_volt(instruction[0]);
return _B_4b4b(CDR_SUCCESS, 0);
} else {
return _B_4b4b(CDR_INV_PAR, 0);
}
}
/*===========================
==== function implement ====
==========================*/
#endif // HEADSTAGE_CIS_VOLT_H
@@ -0,0 +1,54 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
/**
* ref: http://dev.ti.com/tirex/content/tirtos_cc13xx_cc26xx_2_21_00_06/products/bios_6_46_01_37/docs/cdoc/ti/sysbios/knl/Clock.html
*/
#ifndef HRADSTAGE_CLOCK_H
#define HRADSTAGE_CLOCK_H
#include <ti/sysbios/knl/Clock.h>
#define EVT_PERIODIC_CLOCK EVT_PERIODIC_0
static Clock_Handle clock_handle = NULL;
static void headstage_clock_callback(UArg arg) {
flag_notify(EVT_PERIODIC_CLOCK);
}
#define headstage_clock_start() Clock_start(clock_handle)
#define headstage_clock_stop() Clock_stop(clock_handle)
#define headstage_clock_active() (clock_handle && Clock_isActive(clock_handle))
#define headstage_clock_close() \
do { \
Clock_delete(&clock_handle); \
clock_handle = NULL; \
} while (0)
// XXX function not tested
// period in mini second
#define headstage_clock_open(_period) \
do { \
Clock_Params param; \
Clock_Params_init(&param); \
param.period = 48000*(_period); \
param.startFlag = false; \
clock_handle = Clock_create(headstage_clock_callback, 1, &param, NULL); \
} while (0)
#define headstage_clock_set_frequency(frequency) \
do { \
uint32_t _frequency = (uint32_t)(frequency); \
Types_FreqHz _cpu_freq; \
BIOS_getCpuFreq(&_cpu_freq); \
uint32_t _load = _cpu_freq.lo / _frequency; \
bool is_active = Clock_isActive(clock_handle); \
if (is_active) Clock_stop(clock_handle); \
Clock_setPeriod(clock_handle, _load); \
if (is_active) Clock_start(clock_handle); \
} while (0)
#endif // HRADSTAGE_CLOCK_H
@@ -0,0 +1,13 @@
#ifndef HEADSTAGE_DEBUG_H
#define HEADSTAGE_DEBUG_H
/**
* declare debug instruction handle.
*
* @param ins_buf: debug instruction buffer
* @return: size of data length.
* non-zero position value for write [ins_buf] back to debug characteristic.
*/
static uint8_t headstage_debug_instruction(uint8_t ins_buf);
#endif // HEADSTAGE_DEBUG_H
@@ -0,0 +1,116 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
/*
device implement header template
================================
How to create a device header
-----------------------------
1. copy this and rename
2. update device information.
1. DEVICE_NAME
2. MAJOR/MINOR_PRODUCT/VERSION_NUMBER
3. replace @REPLACE@ with device nick name.
4. write your code
5. do not remember update the device document below.
*/
/*
Device Document
===============
Real instruction format
-----------------------
TODO
*/
#ifndef HEADSTAGE_H
#error "headstage.h not include"
#endif
#ifndef HEADSTAGE_@REPLACE@_H
#define HEADSTAGE_@REPLACE@_H
/*============================
==== product information ====
===========================*/
#define DEVICE_NAME "Device Name"
#define MAJOR_PRODUCT_NUMBER 0
#define MINOR_PRODUCT_NUMBER 0
#define MAJOR_VERSION_NUMBER 0
#define MINOR_VERSION_NUMBER 0
/*=================
==== constant ====
=================*/
// TODO define constant macro
/*================
==== include ====
================*/
// TODO include other headstage header
/*=================================
==== constant parameter table ====
================================*/
// TODO define device relative parameter table
/*========================
==== parameter table ====
========================*/
struct HEADSTAGE_PARAMETER_TABLE {
} INSTRUCTION = {0};
#define reset_parameter_table() memset(&INSTRUCTION, 0, sizeof(struct HEADSTAGE_PARAMETER_TABLE));
/*=============================
==== function declaration ====
============================*/
static void headstage_@REPLACE@_init();
/*=======================
==== event dispatch ====
=======================*/
static void headstage_@REPLACE@_event() {
if (flag_mask(EVT_DISCONNECTED)) {
headstage_update_vis_instruction(VIS_INT);
}
}
/*===========================
==== function implement ====
==========================*/
static void headstage_init() {
// TODO
}
static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t *instruction) {
// TODO
}
static void headstage_update_vis_instruction(uint8_t vis_oper) {
// TODO
}
/*========================
==== device function ====
=======================*/
#endif // HEADSTAGE_@REPLACE@_H
@@ -0,0 +1,45 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_GPTIMER_H
#define HEADSTAGE_GPTIMER_H
#include <Board.h>
#include <ti/drivers/timer/GPTimerCC26XX.h>
#include <ti/sysbios/BIOS.h>
#include <xdc/runtime/Types.h>
#define EVT_PERIODIC_GPTIMER EVT_PERIODIC_0
static GPTimerCC26XX_Handle gptimer_handle;
static void headstage_gptimer_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
flag_notify(EVT_PERIODIC_GPTIMER);
}
#define headstage_gptimer_start() GPTimerCC26XX_start(gptimer_handle)
#define headstage_gptimer_stop() GPTimerCC26XX_stop(gptimer_handle)
#define headstage_gptimer_close() GPTimerCC26XX_close(gptimer_handle)
#define headstage_gptimer_open() \
do { \
GPTimerCC26XX_Params params; \
GPTimerCC26XX_Params_init(&params); \
params.width = GPT_CONFIG_16BIT; \
params.mode = GPT_MODE_PERIODIC_DOWN; \
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF; \
gptimer_handle = GPTimerCC26XX_open(Board_GPTIMER0A, &params); \
GPTimerCC26XX_setLoadValue(gptimer_handle, 0xFFFFFF); \
GPTimerCC26XX_registerInterrupt(gptimer_handle, headstage_gptimer_callback, GPT_INT_TIMEOUT); \
} while (0)
#define headstage_gptimer_set_frequency(frequency) \
do { \
uint32_t _frequency = (uint32_t)(frequency); \
Types_FreqHz _cpu_freq; \
BIOS_getCpuFreq(&_cpu_freq); \
GPTimerCC26XX_Value _load = _cpu_freq.lo / _frequency - 1; \
_load = (_load < 0xFFFF) ? _load : ((0xFA0000 | (_load / 250)) - 1); \
GPTimerCC26XX_setLoadValue(gptimer_handle, _load); \
} while (0)
#endif // HEADSTAGE_GPTIMER_H
@@ -0,0 +1,202 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_LED_H
#define HEADSTAGE_LED_H
typedef struct {
uint8_t luminance;
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t duration;
uint8_t duty_cycle;
} LEDParameter;
static void headstage_led_open();
static void headstage_led_close();
static void headstage_led_send(LEDParameter *led);
static void headstage_led_color(uint8_t color);
static uint16_t headstage_led_set_dark(uint16_t *ins_buf, uint8_t repeat) {
uint16_t *p = ins_buf;
*p++ = 0;
*p++ = 0;
if (repeat > 0) {
for (uint8_t j = 0; j < repeat; j++) {
*p++ = 0xE000;
*p++ = 0x0000;
}
}
*p++ = 0xFFFF;
*p++ = 0xFFFF;
return p - ins_buf;
}
static uint16_t headstage_led_set_bright(uint16_t *ins_buf, uint8_t repeat) {
uint16_t *p = ins_buf;
*p++ = 0;
*p++ = 0;
if (repeat > 0) {
for (uint8_t j = 0; j < repeat; j++) {
*p++ = 0xFEFF;
*p++ = 0xFFFF;
}
}
*p++ = 0xFFFF;
*p++ = 0xFFFF;
return p - ins_buf;
}
static uint16_t headstage_led_set_buffer(uint16_t *ins_buf, uint8_t repeat, LEDParameter *parameter) {
uint16_t *p = ins_buf;
*p++ = 0;
*p++ = 0;
if (parameter && repeat > 0) {
uint16_t a = 0xE000 | ((uint16_t)(parameter->luminance & 0x1F) << 8) | (uint16_t)(parameter->blue & 0xFF);
uint16_t b = ((uint16_t)(parameter->green & 0xFF) << 8) | (uint16_t)(parameter->red & 0xFF);
for (uint8_t j = 0; j < repeat; j++) {
*p++ = a;
*p++ = b;
}
}
*p++ = 0xFFFF;
*p++ = 0xFFFF;
return p - ins_buf;
}
// clang-format off
#define COLOR_BLACK 0
#define COLOR_RED 1
#define COLOR_ORANGE 2
#define COLOR_YELLOW 3
#define COLOR_GREEN 4
#define COLOR_BLUE 5
#define COLOR_CYAN 6
#define COLOR_MAGENTA 7
#define COLOR_WHITE 9
// clang-format on
static uint8_t headstage_led_set_color(uint16_t *ins_buf, uint8_t repeat, uint8_t color) {
LEDParameter parameter;
switch (color) {
case COLOR_RED:
parameter = (LEDParameter){.luminance = 0xFF, .red = 0xFF, .green = 0x00, .blue = 0x00};
break;
case COLOR_ORANGE:
parameter = (LEDParameter){.luminance = 0xFF, .red = 0xFF, .green = 0x03, .blue = 0x00};
break;
case COLOR_YELLOW:
parameter = (LEDParameter){.luminance = 0xFF, .red = 0x0F, .green = 0x0F, .blue = 0x00};
break;
case COLOR_GREEN:
parameter = (LEDParameter){.luminance = 0xFF, .red = 0x00, .green = 0xFF, .blue = 0x00};
break;
case COLOR_BLUE:
parameter = (LEDParameter){.luminance = 0xFF, .red = 0x00, .green = 0x00, .blue = 0xFF};
break;
case COLOR_CYAN:
parameter = (LEDParameter){.luminance = 0xFF, .red = 0x00, .green = 0xFF, .blue = 0xFF};
break;
case COLOR_MAGENTA:
parameter = (LEDParameter){.luminance = 0xFF, .red = 0xFF, .green = 0x00, .blue = 0xFF};
break;
case COLOR_WHITE:
parameter = (LEDParameter){.luminance = 0xFF, .red = 0x0F, .green = 0x7F, .blue = 0x1F};
break;
default:
case COLOR_BLACK:
parameter = (LEDParameter){.luminance = 0x00, .red = 0x00, .green = 0x00, .blue = 0x00};
break;
}
return headstage_led_set_buffer(ins_buf, repeat, &parameter);
}
/*============================
==== LED implement (SPI) ====
===========================*/
#ifdef HEADSTAGE_LED_USE_SPI
#include <Board.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/dma/UDMACC26XX.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
#if defined(BOOSTXL_CC2650MA) && !defined(HEADSTAGE_MA_USE_SPI2)
#error "HEADSTAGE_MA_USE_SPI2 not predefine if use SPI1"
#endif
#define HEADSTAGE_LED_USE_SPI_BOARD Board_SPI1
#define SPI_LED_BUFF_SIZE 20
#define SPI_LED_REPEAT 8
static uint16_t headstage_spi_led_txbuf[SPI_LED_BUFF_SIZE];
static SPI_Handle led_handle;
static SPI_Transaction led_transaction;
static void headstage_led_open() {
// SPI parameters initialize
SPI_init();
SPI_Params spi_parameter;
SPI_Params_init(&spi_parameter);
spi_parameter.transferMode = SPI_MODE_BLOCKING;
spi_parameter.mode = SPI_MASTER;
spi_parameter.bitRate = 2500;
spi_parameter.dataSize = 16;
spi_parameter.frameFormat = SPI_POL0_PHA1;
led_handle = SPI_open(HEADSTAGE_LED_USE_SPI_BOARD, &spi_parameter);
}
static void headstage_led_close() {
SPI_close(led_handle);
}
static void headstage_led_send(LEDParameter *led) {
headstage_led_set_buffer(headstage_spi_led_txbuf, SPI_LED_REPEAT, led);
led_transaction.txBuf = headstage_spi_led_txbuf;
led_transaction.rxBuf = NULL;
led_transaction.count = SPI_LED_BUFF_SIZE;
SPI_transfer(led_handle, &led_transaction);
}
static void headstage_led_color(uint8_t color) {
headstage_led_set_color(headstage_spi_led_txbuf, SPI_LED_REPEAT, color);
led_transaction.txBuf = headstage_spi_led_txbuf;
led_transaction.rxBuf = NULL;
led_transaction.count = SPI_LED_BUFF_SIZE;
SPI_transfer(led_handle, &led_transaction);
}
#endif // HEADSTAGE_LED_USE_SPI
/*=============================
==== LED implement (GPIO) ====
============================*/
#ifdef HEADSTAGE_LED_USE_GPIO
// XXX not implement
#endif // HEADSTAGE_LED_USE_GPIO
#endif // HEADSTAGE_LED_H
@@ -0,0 +1,76 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
/*
Headstage notify utility
========================
optional predefined
-------------------
* `HEADSTAGE_NOTIFY_USE_ATT`
send notify through ATT instead characteristic.
[reference](https://github.com/ti-simplelink/ble_examples/blob/ble_examples-2.2/src/examples/throughput_example_peripheral/cc26xx/app/throughput_example_peripheral.c)
optional implement
* `tni/headstage_notify.h`
implement `TDC4VAF2` format
*. `sti/headstage_notify.h`
implement `TDC4VC3` format.
*/
#ifndef HEADSTAGE_NOTIFY_H
#define HEADSTAGE_NOTIFY_H
#include <xdc/runtime/Timestamp.h>
#define headstage_time_stamp_us() (32 * Timestamp_get32())
#define headstage_time_stamp_ms() (Timestamp_get32() / 32)
/*========================
==== notify function ====
=======================*/
static uint8_t headstage_notify_buffer[BLE_NOT_BUFF_SIZE] = {0};
/**
* send notify.
*
*/
static void headstage_notify_send() {
#ifdef HEADSTAGE_NOTIFY_USE_ATT
uint16_t buffer_size = BLE_NOT_BUFF_SIZE;
uint8_t *value = (uint8 *)GATT_bm_alloc(CONNECT_HANDLE, ATT_HANDLE_VALUE_NOTI, GATT_MAX_MTU, &buffer_size);
if (value != NULL) {
memcpy(value, headstage_notify_buffer, buffer_size);
attHandleValueNoti_t notify = {
// clang-format off
.handle = 0x1E,
.len = buffer_size,
.pValue = value
// clang-format on
};
if (GATT_Notification(CONNECT_HANDLE, &notify, GATT_NO_AUTHENTICATION) != SUCCESS) {
// notify not send
GATT_bm_free((gattMsg_t *)&notify, ATT_HANDLE_VALUE_NOTI);
}
}
#else
SimpleProfile_SetParameter(BLE_NOT_BUFF_CHAR, BLE_NOT_BUFF_SIZE, headstage_notify_buffer);
#endif
}
#endif // HEADSTAGE_NOTIFY_H
@@ -0,0 +1,40 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_PIN_H
#define HEADSTAGE_PIN_H
#include <Board.h>
#include <ti/drivers/PIN.h>
static PIN_State headstage_pins_state;
static PIN_Handle headstage_pins_handle;
#if defined(CC2650_LAUNCHXL)
#define PIN_LED_R Board_RLED
#define PIN_LED_G Board_GLED
#endif
static PIN_Config headstage_pin_configuration[] = { //
// LED
#if defined(CC2650_LAUNCHXL)
PIN_LED_R | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_LED_G | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
#endif
//
PIN_TERMINATE};
#define headstage_pin_add(configuration) PIN_add(headstage_pins_handle, configuration)
#define headstage_pin_remove(pin) PIN_remove(headstage_pins_handle, pin)
#define headstage_pin_close() PIN_close(headstage_pins_handle)
#define headstage_pin_open() \
do { \
headstage_pins_handle = PIN_open(&headstage_pins_state, headstage_pin_configuration); \
} while (0)
#define headstage_pin_output(pin, value) PIN_setOutputValue(headstage_pins_handle, PIN_ID(pin), (value))
#define headstage_pin_input(pin) PIN_getInputValue(PIN_ID(pin))
#endif // HEADSTAGE_PIN_H
@@ -0,0 +1,9 @@
#ifndef HEADSTAGE_POWER_H
#define HEADSTAGE_POWER_H
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
#define headstage_power_shutdown() Power_shutdown(0, 0)
#endif // HEADSTAGE_POWER_H
@@ -0,0 +1,28 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_PWM_H
#define HEADSTAGE_PWM_H
#include <Board.h>
#include <ti/drivers/PWM.h>
static PWM_Handle headstage_pwm_handle;
#define headstage_pwm_open() \
do { \
PWM_init(); \
PWM_Params params; \
PWM_Params_init(&params); \
params.idleLevel = PWM_IDLE_LOW; \
params.periodUnits = PWM_PERIOD_HZ; \
params.periodValue = UMC_SYS_CLK; \
params.dutyUnits = PWM_DUTY_FRACTION; \
params.dutyValue = PWM_DUTY_FRACTION_MAX / 2; \
headstage_pwm_handle = PWM_open(Board_PWM0, &params); \
} while (0);
#define headstage_pwm_start() PWM_start(headstage_pwm_handle)
#define headstage_pwm_stop() PWM_stop(headstage_pwm_handle)
#define headstage_pwm_close() PWM_close(headstage_pwm_handle)
#endif // HEADSTAGE_PWM_H
@@ -0,0 +1,43 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_SPI_H
#define HEADSTAGE_SPI_H
#include <Board.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/dma/UDMACC26XX.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
/*
* SPI parameter and function declaration
*/
static SPI_Handle spi_handle;
static SPI_Transaction spi_transaction;
#define headstage_spi_close() SPI_close(spi_handle)
#define headstage_spi_transaction_cancel() SPI_transferCancel(spi_handle)
// SPI parameters initialize
#define headstage_spi_open() \
do { \
SPI_init(); \
SPI_Params spi_parameter; \
SPI_Params_init(&spi_parameter); \
spi_parameter.transferMode = SPI_MODE_BLOCKING; \
spi_parameter.mode = SPI_MASTER; \
spi_parameter.bitRate = 12000000; \
spi_parameter.transferTimeout = 1000; \
spi_parameter.dataSize = 8; \
spi_parameter.frameFormat = SPI_POL0_PHA0; \
spi_handle = SPI_open(Board_SPI0, &spi_parameter); \
} while (0)
#define headstage_spi_transaction(len, tx, rx) \
({ \
spi_transaction.txBuf = (tx); \
spi_transaction.rxBuf = (rx); \
spi_transaction.count = (len); \
SPI_transfer(spi_handle, &spi_transaction); \
})
#endif // HEADSTAGE_SPI_H
@@ -0,0 +1,532 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
/*
Device Document
===============
Real instruction format
-----------------------
TODO
*/
#ifndef HEADSTAGE_H
#error "headstage.h not include"
#endif
#ifndef HEADSTAGE_STI_H
#define HEADSTAGE_STI_H
/*============================
==== product information ====
===========================*/
#define DEVICE_NAME "NeuliveSTI-M0.1"
#define MAJOR_PRODUCT_NUMBER 1
#define MINOR_PRODUCT_NUMBER 2
#define MAJOR_VERSION_NUMBER 0
#define MINOR_VERSION_NUMBER 1
/*=================
==== constant ====
=================*/
// clang-format off
#define CHANNEL_BATTERY 0
#define CHANNEL_STI_0 1
#define CHANNEL_STI_1 2
#define TOTAL_CHANNEL_NUMBER 3
#define RIS_GLOBAL 0x20
#define RIS_LOCAL 0x40
#define RIS_CHANNEL 0x80
#define DEBUG_INS_SLEEP 0x50
#define STI_POS 0x00
#define STI_NEG 0x01
#define STI_P2N 0x02
#define STI_N2P 0x03
// clang-format on
/*================
==== include ====
================*/
#include "headstage_debug.h"
#include "headstage_power.h"
#include "sti/headstage_adc.h"
#include "sti/headstage_gptimer.h"
#include "sti/headstage_pin.h"
#include "sti/headstage_pwm.h"
/*=================================
==== constant parameter table ====
================================*/
/*========================
==== parameter table ====
========================*/
typedef struct {
uint8_t enable;
uint8_t mode;
uint8_t precision;
uint16_t frequency;
uint16_t pulse_width;
uint16_t pw_ipi;
uint16_t times;
/**
* low frequency counter.
*/
int low_freq_counter;
} NeuLiveStiChanelParameter;
struct HEADSTAGE_PARAMETER_TABLE {
uint32_t duty_cycle;
NeuLiveStiChanelParameter channel[TOTAL_CHANNEL_NUMBER];
} INSTRUCTION = {0};
#define reset_parameter_table() memset(&INSTRUCTION, 0, sizeof(struct HEADSTAGE_PARAMETER_TABLE));
#define actual_channel_frequency(p) (p->frequency / (p->precision ? 10 : 1))
#define is_low_frequency(p) ((p->frequency < 4 && p->precision == 0) || (p->frequency < 2000 && p->precision == 1))
static GPTimerCC26XX_Handle headstage_gptimer_handle[] = {
//
gptimer_handle_2,
gptimer_handle_0,
gptimer_handle_1,
//
};
static ADC_Handle headstage_adc_handle[] = {
//
headstage_adc_handle_2,
headstage_adc_handle_0,
headstage_adc_handle_1,
//
};
/*=============================
==== function declaration ====
============================*/
static void headstage_sti_pulse_event(uint8_t channel);
static void headstage_sti_collect_recording_data(uint8_t channel);
static void headstage_sti_collect_stimulation_information();
/*=======================
==== event dispatch ====
=======================*/
static void headstage_sti_event() {
if (flag_mask(EVT_PERIODIC_GPTIMER_0)) {
flag_disable(EVT_PERIODIC_GPTIMER_0);
headstage_sti_pulse_event(CHANNEL_STI_0);
}
if (flag_mask(EVT_PERIODIC_GPTIMER_1)) {
flag_disable(EVT_PERIODIC_GPTIMER_1);
headstage_sti_pulse_event(CHANNEL_STI_1);
}
if (flag_mask(EVT_PERIODIC_GPTIMER_2)) {
flag_disable(EVT_PERIODIC_GPTIMER_2);
headstage_sti_collect_recording_data(CHANNEL_BATTERY);
headstage_sti_collect_stimulation_information();
}
if (EVENT_MASK == 0) {
// fast return
return;
}
if (flag_mask(EVT_DISCONNECTED)) {
headstage_update_vis_instruction(VIS_INT);
}
}
/*===========================
==== function implement ====
==========================*/
static void headstage_init() {
headstage_pin_open();
headstage_gptimer_open();
headstage_pwm_open();
headstage_adc_open();
headstage_gptimer_set_frequency(headstage_gptimer[CHANNEL_BATTERY], 200);
headstage_pwm_start();
headstage_pin_output(PIN_STI_0, 0);
headstage_pin_output(PIN_SET_1, 0);
headstage_pin_output(PIN_SET_3, 1);
headstage_pin_output(PIN_SET_5, 0);
headstage_pin_output(PIN_SET_6, 0);
headstage_pin_output(PIN_SET_10, 0);
headstage_pin_output(PIN_SET_11, 0);
}
static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t *instruction) {
uint8_t ins_oper = instruction[0] & 0xE0;
switch (ins_oper) {
case RIS_GLOBAL: {
// 5b11111#header;2b0#GV;12bCURRENT
// --------------------
// 3b001#header#;1bx;12bCURRENT
uint16_t a = (uint16_t)(instruction[0]) && 0x0F;
uint16_t b = (uint16_t)(instruction[1]) && 0xFF;
uint16_t current = (a << 8) | b; // actual current output(mA) in 1mA mode (2019/03)
INSTRUCTION.duty_cycle = current;
headstage_pwm_set(MAX_DUTY, current);
break;
}
case RIS_LOCAL: {
// 5b11111#header;2b01#LV
// 3b>channel
// 1b>PRECISION[channel]
// 3b>STI_MODE[channel]
// 12b>STI_FREQ[channel]
// 10b>STI_PW[channel]
// 10b>STI_PW_IPI[channel]
// 10b>STI_NUM[channel]
// --------------------
// 3b010#header;1bx
// 4b>channel
// 3b>STI_MODE[channel]
// 1b>PRECISION[channel]
// 12b>STI_FREQ[channel]
// 10b>STI_PW[channel]
// 10b>STI_PW_IPI[channel]
// 10b>STI_NUM[channel]
uint8_t channel = (instruction[0] & 0x0F);
uint8_t mode = (instruction[1] & 0xE0) >> 5;
uint8_t prec = (instruction[1] & 0x10) >> 4;
uint16_t freq_a = (uint16_t)(instruction[1]) & 0x0F;
uint16_t freq_b = (uint16_t)(instruction[2]) & 0xFF;
uint16_t freq = (freq_a << 8) | freq_b;
uint16_t width_a = (uint16_t)(instruction[3]) & 0xFF;
uint16_t width_b = (uint16_t)(instruction[4]) & 0xC0;
uint16_t width = (width_a << 2) | (width_b >> 6);
uint16_t ipi_a = (uint16_t)(instruction[4]) & 0x3F;
uint16_t ipi_b = (uint16_t)(instruction[5]) & 0xF0;
uint16_t ipi = (ipi_a << 4) | (ipi_b >> 4);
uint16_t times_a = (uint16_t)(instruction[5]) & 0x0F;
uint16_t times_b = (uint16_t)(instruction[6]) & 0xFC;
uint16_t times = (times_a << 6) | (times_b >> 2);
if (channel < TOTAL_CHANNEL_NUMBER - 1) {
NeuLiveStiChanelParameter *p = &INSTRUCTION.channel + 1 + channel;
uint16_t adjust_value = (channel == 0) ? 3 : 5;
if (width > 0) {
// error when output 100us
width += (width * adjust_value / 100) - 1;
}
if (ipi > 0) {
// error when output 100us
ipi += (ipi * adjust_value / 100) - 1;
}
p->mode = mode;
p->precision = prec;
p->frequency = freq;
p->pulse_width = width;
p->pulse_width = width;
p->pw_ipi = ipi;
p->times = times;
}
break;
}
case RIS_CHANNEL: {
// 5b11111#header;2b10#CE
// a0;a1;a2;a3;a4;a5;a6;a7;a8;a9;aa;ab;ac;ad;ae;af
// --------------------
// 3b100#header;5bx;
// a0;a1;a2;a3;a4;a5;a6;a7;a8;a9;aa;ab;ac;ad;ae;af
if (INSTRUCTION.duty_cycle == 0) {
break;
}
for (uint8_t channel = 1; channel < TOTAL_CHANNEL_NUMBER; i++) {
NeuLiveStiChanelParameter *p = &INSTRUCTION.channel + channel;
uint8_t index = 1 + (channel - 1) % 8;
uint8_t mask = 1 << (7 - (channel - 1) / 8);
p->enable = 0;
if ((instruction[index] & mask) != 0) {
uint16_t frequency = actual_channel_frequency(p);
if (is_low_frequency(p)) {
frequency *= 100;
}
if (frequency != 0 && p->pulse_width != 0) {
p->enable = 1;
headstage_gptimer_set_frequency(headstage_gptimer_handle[channel], frequency);
}
}
}
break;
}
}
}
static void headstage_update_vis_instruction(uint8_t vis_oper) {
switch (vis_oper) {
case VIS_STI:
headstage_gptimer_start(gptimer_handle_0);
headstage_gptimer_start(gptimer_handle_1);
headstage_gptimer_start(gptimer_handle_2);
break;
case VIS_RST:
headstage_gptimer_stop(gptimer_handle_0);
headstage_gptimer_stop(gptimer_handle_1);
headstage_gptimer_stop(gptimer_handle_2);
reset_parameter_table();
break;
case VIS_INT:
headstage_gptimer_stop(gptimer_handle_0);
headstage_gptimer_stop(gptimer_handle_1);
headstage_gptimer_stop(gptimer_handle_2);
break;
}
}
static uint8_t headstage_debug_instruction(uint8_t ins_buf) {
uint8_t ins_oper = ins_buf[0] & 0xF0;
switch (ins_oper) {
case DEBUG_INS_SLEEP:
headstage_pin_output(IOID_3, 0);
headstage_power_shutdown();
break;
}
}
/*========================
==== device function ====
=======================*/
static void headstage_sti_pulse_event(uint8_t channel) {
NeuLiveStiChanelParameter *p;
switch (channel) {
case CHANNEL_STI_0:
case CHANNEL_STI_1:
p = &INSTRUCTION.channel + channel;
break;
case CHANNEL_BATTERY:
default:
return;
}
if (!(p->enable && p->times > 0)) {
return;
}
uint8_t p0, p1, p2;
switch (channel) {
case CHANNEL_STI_0:
p0 = PIN_STI_0;
p1 = PIN_SET_10;
p2 = PIN_SET_11;
break;
case CHANNEL_STI_1:
p0 = PIN_STI_1;
p1 = PIN_SET_6;
p2 = PIN_SET_5;
break;
}
switch (p->mode) {
case STI_POS:
headstage_pin_output(p1, 0);
headstage_pin_output(p2, 1);
headstage_pin_output(p0, 1);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p2, 0);
break;
case STI_NEG:
headstage_pin_output(p1, 1);
headstage_pin_output(p2, 1);
headstage_pin_output(p0, 1);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p2, 0);
break;
case STI_P2N:
if (p->pw_ipi == 0) {
headstage_pin_output(p1, 0);
headstage_pin_output(p2, 1);
headstage_pin_output(p0, 1);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p1, 1);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p2, 0);
} else {
headstage_pin_output(p1, 0);
headstage_pin_output(p2, 1);
headstage_pin_output(p0, 1);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p2, 0);
headstage_cpu_delay_us(p->pw_ipi);
headstage_pin_output(p2, 1);
headstage_pin_output(p1, 1);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p2, 0);
}
break;
case STI_N2P:
if (p->pw_ipi == 0) {
headstage_pin_output(p1, 1);
headstage_pin_output(p2, 1);
headstage_pin_output(p0, 1);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p1, 0);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p2, 0);
} else {
headstage_pin_output(p1, 1);
headstage_pin_output(p2, 1);
headstage_pin_output(p0, 1);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p2, 0);
headstage_cpu_delay_us(p->pw_ipi);
headstage_pin_output(p2, 1);
headstage_pin_output(p1, 0);
headstage_cpu_delay_us(p->pulse_width);
headstage_pin_output(p2, 0);
}
break;
}
headstage_sti_collect_recording_data(channel);
}
// XXX move code to headstage_sti_event and keep interrupt handle clean?
static void headstage_gptimer_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
NeuLiveStiChanelParameter *p = &INSTRUCTION.channel;
uint16_t evt_flag = 0;
if (handle == gptimer_handle_0) {
p += CHANNEL_STI_0;
evt_flag = EVT_PERIODIC_GPTIMER_0;
goto sti_channel_event;
} else if (handle == gptimer_handle_1) {
p += CHANNEL_STI_1;
evt_flag = EVT_PERIODIC_GPTIMER_1;
goto sti_channel_event;
} else if (handle == gptimer_handle_2) {
if (p->low_freq_counter > 0) {
p->low_freq_counter--;
} else {
p->low_freq_counter = 9;
evt_flag = EVT_PERIODIC_GPTIMER_2;
goto fire_event;
}
}
return;
sti_channel_event:
if (is_low_frequency(p)) {
if (p->low_freq_counter > 0) {
p->low_freq_counter--;
} else {
p->low_freq_counter = 99;
if (p->enable && p->times > 0) {
p->times--;
goto fire_event;
}
}
} else {
if (p->enable && p->times > 0) {
p->times--;
goto fire_event;
}
}
return;
fire_event:
if (evt_flag) {
flag_notify(evt_flag);
}
}
static void headstage_sti_collect_recording_data(uint16_t channel) {
uint16_t adc_value;
headstage_adc_convert(headstage_adc_handle[channel], &adc_value);
uint8_t not_size = headstage_notify_append_data(channel, adc_value);
if (not_size >= BLE_DATA_BUFF_SIZE) {
headstage_notify_send();
}
}
static void headstage_sti_collect_stimulation_information() {
// flush remind data in notify buffer
if (not_buf_offset > NOT_BUF_OFFSET_INIT) {
headstage_notify_flip_buffer();
headstage_notify_send();
}
//
headstage_notify_set_timestamp();
uint16_t sti_times_0 = INSTRUCTION.channel[CHANNEL_STI_0].times;
uint16_t sti_times_1 = INSTRUCTION.channel[CHANNEL_STI_1].times;
uint8_t *p = headstage_notify_buffer + NOT_BUF_OFFSET_INIT;
*p++ = (sti_times_0 >> 8) && 0xFF;
*p++ = sti_times_0 && 0xFF;
*p++ = (sti_times_1 >> 8) && 0xFF;
*p++ = sti_times_1 && 0xFF;
not_buf_offset = p - headstage_notify_buffer;
headstage_notify_flip_buffer();
headstage_notify_send();
}
#endif // HEADSTAGE_STI_H
@@ -0,0 +1,702 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
/*
Headstage TNI Document
======================
Although this file and correspond device do not used anymore,
this header could be a example to implement a driver.
Real instruction format
-----------------------
*/
#ifndef HEADSTAGE_TNI_H
#define HEADSTAGE_TNI_H
/*============================
==== product information ====
===========================*/
#define DEVICE_NAME "Elite-v0.2"
#define MAJOR_PRODUCT_NUMBER 0
#define MINOR_PRODUCT_NUMBER 1
#define MAJOR_VERSION_NUMBER 0
#define MINOR_VERSION_NUMBER 1
/*================
==== include ====
================*/
#include "headstage_arm.h"
#include "headstage_gptimer.h"
#include "headstage_notify.h"
#include "tni/headstage_notify.h"
#include "tni/headstage_pin.h"
#include "tni/headstage_spi.h"
/*=================================
==== constant parameter table ====
================================*/
// clang-format off
#define RIS_ART 0x60 // amplifier reset
#define RIS_ARM 0x80
#define RIS_DIR 0xA0
#define RIS_REC 0xC0
#define RIS_STI 0xE0
#define FREQ_MODE_INDEX 0
#define FREQ_MODE_VALUE 1
#define STI_MODE_DISABLE 0
#define STI_MODE_POS 1
#define STI_MODE_NEG 2
#define STI_MODE_P2N 3
#define STI_MODE_N2P 4
#define STI_MODE_AWF 5
#define ARM_MODE_RAMP 8
// clang-format on
#define IS_REC_MODE(mode) (STI_MODE_DISABLE == (mode))
#define IS_STI_MODE(mode) (STI_MODE_DISABLE < (mode) && (mode) <= STI_MODE_AWF)
#define IS_ARM_MODE(mode) (ARM_MODE_RAMP == (mode))
#define REC_CHANNEL_COUNT 16
/**
* stimulation frequency fixed-value table.
*/
static uint32_t sti_freq_table[] = {
15,
25,
40,
50,
100,
250,
400,
500,
1000,
2500,
4000,
5000,
5000, // 12
5000, // 13
5000, // 14
5000, // 15
};
/**
* ADC clock/sampling rate fixed-value table
*/
static uint32_t adc_clock_table[] = {
30,
50,
80,
100,
200,
500,
800,
1000,
2000,
5000,
8000,
10000,
10000, // 12
10000, // 13
10000, // 14
10000, // 15
};
/*========================
==== parameter table ====
========================*/
struct HEADSTAGE_PARAMETER_TABLE {
/**
* MODE
*/
uint8_t mode;
uint8_t channel_table[REC_CHANNEL_COUNT];
/**
* indicate the value frequency is a index (to a mapper table) or a value
*/
uint8_t frequency_mode;
/**
* RATE. ADC clock/sampling rate value
* FREQ. the stimulation frequency value.
*/
uint32_t frequency;
uint8_t amp_gain;
uint8_t amp_low_band_freq;
uint8_t chopper;
uint8_t fast_settle;
uint8_t sti_channel_pmos;
uint8_t sti_channel_nmos;
uint8_t sti_volt;
uint8_t flag_start;
/**
* ADC clock switch signal.
*/
bool adc_clock_signal;
/*
* amplifier reset
*/
bool amp_rst;
int8_t channel_pointer;
uint8_t data_channel;
} INSTRUCTION = {0};
#define reset_parameter_table() memset(&INSTRUCTION, 0, sizeof(struct HEADSTAGE_PARAMETER_TABLE));
#define actual_frequency() ((INSTRUCTION.frequency_mode == FREQ_MODE_INDEX) ? (adc_clock_table[INSTRUCTION.frequency]) : (INSTRUCTION.frequency))
/*=============================
==== function declaration ====
============================*/
static void headstage_tni_periodic();
static void update_ins_buffer();
/*=======================
==== event dispatch ====
=======================*/
static void headstage_tni_event() {
if (flag_mask(EVT_PERIODIC_GPTIMER)) {
flag_disable(EVT_PERIODIC_GPTIMER);
headstage_tni_periodic();
}
if (EVENT_MASK == 0) {
// fast return
return;
}
if (flag_mask(EVT_DISCONNECTED)) {
headstage_update_vis_instruction(VIS_INT);
}
}
/*===========================
==== function implement ====
==========================*/
static void headstage_init() {
headstage_pin_open();
headstage_spi_open();
headstage_gptimer_open();
headstage_pin_output(PIN_S2P_RST, 0);
headstage_pin_output(PIN_P2S_RST, 0);
}
static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t *instruction) {
uint8_t header = instruction[0] & 0xE0;
switch (header) {
// direct instruction
case RIS_DIR: {
uint8_t amp_gain = (instruction[0] & 0b00011000) >> 3;
uint8_t amp_lbf = (instruction[0] & 0b00000111);
uint8_t channel = (instruction[1] & 0b11110000) >> 4;
uint8_t chopper = (instruction[1] & 0b00001000) >> 3;
uint8_t fast_settle = (instruction[1] & 0b00000100) >> 2;
uint8_t mode = (instruction[1] == 0b00000010) ? STI_MODE_POS : STI_MODE_DISABLE;
uint8_t sti_volt_h = (instruction[1] & 0b00000001);
uint8_t sti_volt_l = (instruction[2] & 0b11110000) >> 4;
uint8_t sti_volt = (sti_volt_h << 4) | sti_volt_l;
uint8_t sti_chp = (instruction[2] & 0b00001111);
uint8_t sti_chn = (instruction[3] & 0b11110000) >> 4;
uint8_t frequency = (instruction[3] & 0b00001111);
INSTRUCTION.mode = mode;
INSTRUCTION.channel_table[channel] = TRUE;
INSTRUCTION.frequency_mode = FREQ_MODE_INDEX;
INSTRUCTION.frequency = frequency;
INSTRUCTION.amp_gain = amp_gain;
INSTRUCTION.amp_low_band_freq = amp_lbf;
INSTRUCTION.chopper = chopper;
INSTRUCTION.fast_settle = fast_settle;
INSTRUCTION.sti_volt = sti_volt;
INSTRUCTION.sti_channel_pmos = sti_chp;
INSTRUCTION.sti_channel_nmos = sti_chn;
break;
}
// recording instruction
case RIS_REC: {
uint8_t amp_gain = (instruction[0] & 0b00011000) >> 3;
uint8_t amp_lbf = (instruction[0] & 0b00000111);
uint8_t frequency = (instruction[1] & 0b11110000) >> 4;
INSTRUCTION.mode = STI_MODE_DISABLE;
INSTRUCTION.amp_gain = amp_gain;
INSTRUCTION.amp_low_band_freq = amp_lbf;
INSTRUCTION.frequency_mode = FREQ_MODE_INDEX;
INSTRUCTION.frequency = frequency;
uint8_t cha = (instruction[2] & 0b11110000) >> 4;
uint8_t chb = (instruction[2] & 0b00001111);
uint8_t chc = (instruction[3] & 0b11110000) >> 4;
uint8_t chd = (instruction[3] & 0b00001111);
if (instruction[1] & 0b1000) INSTRUCTION.channel_table[cha] = TRUE;
if (instruction[1] & 0b0100) INSTRUCTION.channel_table[chb] = TRUE;
if (instruction[1] & 0b0010) INSTRUCTION.channel_table[chc] = TRUE;
if (instruction[1] & 0b0001) INSTRUCTION.channel_table[chd] = TRUE;
break;
}
// artifact recording instruction
case RIS_ARM: {
uint8_t arm_mode = (instruction[0] & 0b00000111);
uint8_t frequency = (instruction[1] & 0b11110000) >> 4;
INSTRUCTION.mode = STI_MODE_DISABLE;
INSTRUCTION.amp_gain = arm_mode;
INSTRUCTION.amp_low_band_freq = 0;
INSTRUCTION.frequency_mode = FREQ_MODE_INDEX;
INSTRUCTION.frequency = frequency;
uint8_t cha = (instruction[2] & 0b11110000) >> 4;
uint8_t chb = (instruction[2] & 0b00001111);
uint8_t chc = (instruction[3] & 0b11110000) >> 4;
uint8_t chd = (instruction[3] & 0b00001111);
if (instruction[1] & 0b1000) INSTRUCTION.channel_table[cha] = TRUE;
if (instruction[1] & 0b0100) INSTRUCTION.channel_table[chb] = TRUE;
if (instruction[1] & 0b0010) INSTRUCTION.channel_table[chc] = TRUE;
if (instruction[1] & 0b0001) INSTRUCTION.channel_table[chd] = TRUE;
switch (arm_mode) {
case 1:
INSTRUCTION.mode = ARM_MODE_RAMP;
break;
}
break;
}
// stimulating instruction
case RIS_STI: {
uint8 mode = (instruction[0] & 0b00011000) >> 3;
switch (mode) {
// simple instruction
case 0: {
uint8_t mode = (instruction[0] & 0b00000111);
uint8_t sti_freq = (instruction[1] & 0b11110000) >> 4;
uint8_t chopper = (instruction[1] & 0b00001000);
uint8_t fast_settle = (instruction[1] & 0b00000100);
uint8_t sti_chp = (instruction[2] & 0b11110000) >> 4;
uint8_t sti_chn = (instruction[2] & 0b00001111);
uint8_t sti_volt = (instruction[3] & 0b11111000) >> 3;
INSTRUCTION.mode = mode;
INSTRUCTION.chopper = chopper;
INSTRUCTION.fast_settle = fast_settle;
INSTRUCTION.sti_volt = sti_volt;
INSTRUCTION.frequency_mode = FREQ_MODE_INDEX;
INSTRUCTION.frequency = sti_freq;
switch (mode) {
case STI_MODE_POS:
case STI_MODE_P2N: {
INSTRUCTION.sti_channel_pmos = sti_chp;
INSTRUCTION.sti_channel_nmos = sti_chn;
break;
}
case STI_MODE_NEG:
case STI_MODE_N2P: {
INSTRUCTION.sti_channel_pmos = sti_chn;
INSTRUCTION.sti_channel_nmos = sti_chp;
break;
}
}
break;
}
// continuous frequency
case 1: {
uint8_t prec = (instruction[0] & 0b00000111);
uint32_t freq = (instruction[1] << 16) | (instruction[2] << 8) | (instruction[3]);
// XXX consider precision
INSTRUCTION.frequency_mode = FREQ_MODE_VALUE;
INSTRUCTION.frequency = freq;
break;
}
// reserved
case 2:
case 3:
default:
break;
}
break;
}
case RIS_ART: {
break;
}
}
// update gptimer frequency
uint32_t frequency = 0;
if (INSTRUCTION.frequency_mode == FREQ_MODE_INDEX) {
if (IS_REC_MODE(INSTRUCTION.mode) || IS_ARM_MODE(INSTRUCTION.mode)) {
// recording mode
frequency = adc_clock_table[INSTRUCTION.frequency];
} else if (IS_STI_MODE(INSTRUCTION.mode)) {
// stimulation mode
frequency = sti_freq_table[INSTRUCTION.frequency];
}
} else {
frequency = INSTRUCTION.frequency;
}
if (frequency > 0) {
headstage_gptimer_set_frequency(frequency);
}
// update instruction buffer
update_ins_buffer();
}
static void headstage_update_vis_instruction(uint8_t vis_oper) {
switch (vis_oper) {
case VIS_STI:
INSTRUCTION.flag_start = TRUE;
headstage_gptimer_start();
break;
// reset
case VIS_RST:
// stop gptimer
headstage_gptimer_stop();
// reset. reset all variable
reset_parameter_table();
memset(spi_txbuf, 0, SPI_BUFFER_SIZE);
not_buf_offset = NOT_BUF_OFFSET_INIT;
INSTRUCTION.channel_pointer = -1;
break;
// interrupt
case VIS_INT:
// stop gptimer
headstage_gptimer_stop();
// stop. reset channel table
memset(&INSTRUCTION.channel_table, 0, REC_CHANNEL_COUNT);
memset(spi_txbuf, 0, SPI_BUFFER_SIZE);
not_buf_offset = NOT_BUF_OFFSET_INIT;
INSTRUCTION.channel_pointer = -1;
break;
default:
break;
// nothing
}
}
/*======================
==== notify buffer ====
=====================*/
/**
* move data to not_buf. If not_buf is full, then send notify.
*/
static void headstage_tni_data_append_notify_buffer(uint8_t *dat_buf) {
uint8_t channel = INSTRUCTION.data_channel;
uint16_t data_value = 0;
uint8_t data_size;
if ((dat_buf[0] & 0xF0) == 0xB0) {
// valid value
data_value = (((uint16_t)dat_buf[0] & 0x0F) << 6) | ((dat_buf[1] & 0xFC) >> 2);
data_size = headstage_notify_append_data(channel, &data_value);
} else {
data_size = headstage_notify_append_data(channel, NULL);
}
// check buffer full or not
// check whether has more place to append data into notify buffer
if (data_size >= BLE_NOT_BUFF_SIZE) {
headstage_notify_send();
}
}
/*===========================
==== instruction buffer ====
===========================*/
/**
* change the recording clock bit in the instruction buffer.
*/
static void update_ins_rec_clock(uint8_t *ins_buf, bool adc_clock_signal) {
ins_buf[3] = (ins_buf[3] & 0b11110000) | ((adc_clock_signal) ? 0b1000 : 0);
}
/**
* change the recording channel bit in the instruction buffer.
*/
static void update_ins_rec_channel(uint8_t *ins_buf, uint8 channel) {
ins_buf[1] = (ins_buf[1] & 0b00001111) | (_B_flip4(channel) << 4);
}
/**
* change the stimulation enable bit in the instruction buffer.
*/
static void update_ins_sti_enable(uint8_t *ins_buf, bool enable) {
ins_buf[1] = (ins_buf[1] & 0b11111101) | ((enable) ? 0b10 : 0);
}
/**
* change the stimulating channel bit in the instruction buffer.
*/
static void update_ins_sti_channel(uint8_t *ins_buf, uint8 sti_chp, uint8 sti_chn) {
ins_buf[2] = (ins_buf[2] & 0b11110000) | (_B_flip4(sti_chp));
ins_buf[3] = (ins_buf[3] & 0b00001111) | (_B_flip4(sti_chn) << 4);
}
static void update_ins_buffer() {
uint8 header = 0b10100000;
uint8 amp_gain = (_B_flip2(INSTRUCTION.amp_gain) & 0b11) << 3;
uint8 amp_lbf = _B_flip3(INSTRUCTION.amp_low_band_freq) & 0b111;
uint8 channel = 0; // should be call update_ins_channel to modify this value
uint8 chopper = (INSTRUCTION.chopper) ? 0b00001000 : 0;
uint8 fast_settle = (INSTRUCTION.fast_settle) ? 0b00000100 : 0;
uint8 sti_enable = (INSTRUCTION.mode != STI_MODE_DISABLE) ? 0b00000010 : 0;
uint8 sti_volt = _B_flip5(INSTRUCTION.sti_volt);
uint8 sti_volt_l = (sti_volt & 0b10000) >> 4;
uint8 sti_volt_h = (sti_volt & 0b01111) << 4;
uint8 sti_chp = INSTRUCTION.sti_channel_pmos & 0b1111;
uint8 sti_chn = (INSTRUCTION.sti_channel_nmos & 0b1111) << 4;
uint8 clk_signal = 0; // updated by update_ins_rec_clock to modify this value
if (INSTRUCTION.amp_rst) {
INSTRUCTION.amp_rst = 0;
fast_settle = 0b0001000;
}
spi_txbuf[0] = header | amp_gain | amp_lbf;
spi_txbuf[1] = channel | chopper | fast_settle | sti_enable | sti_volt_l;
spi_txbuf[2] = sti_volt_h | sti_chp;
spi_txbuf[3] = sti_chn | clk_signal;
}
/**
* find next enable channel
*/
static int8_t next_active_channel(int8_t channel_pointer) {
channel_pointer++;
while (channel_pointer < REC_CHANNEL_COUNT && !INSTRUCTION.channel_table[channel_pointer]) {
channel_pointer++;
}
if (channel_pointer >= REC_CHANNEL_COUNT) {
// channel to to the end of the channel_table, set to the beginning and re-search enable channel.
channel_pointer = 0;
while (channel_pointer < REC_CHANNEL_COUNT && !INSTRUCTION.channel_table[channel_pointer]) {
channel_pointer++;
}
if (channel_pointer >= REC_CHANNEL_COUNT) {
// no channel enable, return directly
return -1;
}
}
return channel_pointer;
}
static bool update_ins_rec_buffer() {
int8_t channel_pointer = INSTRUCTION.channel_pointer;
update_ins_rec_clock(spi_txbuf, INSTRUCTION.adc_clock_signal);
if (channel_pointer >= 0) {
// store previous channel
INSTRUCTION.data_channel = (uint8_t)channel_pointer;
}
// change to next channel
channel_pointer = next_active_channel(channel_pointer);
if (channel_pointer >= 0) {
update_ins_rec_channel(spi_txbuf, channel_pointer);
} else {
// no channel active
return false;
}
return true;
}
/**
* Change the instruction content for SPI buffer, which is depended on the
* work_mode. Expend the remind instruction according to the base instruction
* which allocated at the beginning 4 bytes of the SPI buffer.
*
* ========= ===========
* work_mode ins pattern
* ========= ===========
* POS, NEG 4 F D 0
* P2N, N2P 4 4' F D
* AWF not impl
* ========= ===========
*
* pattern *4*
* stimulation instruction.
*
* pattern *F*
* set pmos channel to 0xF, release the remain voltage in the capacitance.
*
* pattern *D*
* disable stimulation
*
* pattern *0*
* nop.
*
* @param: buf: pointer of the SPI buffer.
*/
static void update_ins_sti_buffer() {
switch (INSTRUCTION.mode) {
case STI_MODE_POS:
case STI_MODE_NEG:
// copy [4:7]
spi_txbuf[4] = spi_txbuf[0];
spi_txbuf[5] = spi_txbuf[1];
spi_txbuf[6] = spi_txbuf[2];
spi_txbuf[7] = spi_txbuf[3];
// copy [8:B]
spi_txbuf[8] = spi_txbuf[0];
spi_txbuf[9] = spi_txbuf[1];
spi_txbuf[10] = spi_txbuf[2];
spi_txbuf[11] = spi_txbuf[3];
// reset [C:F]
spi_txbuf[12] = 0;
spi_txbuf[13] = 0;
spi_txbuf[14] = 0;
spi_txbuf[15] = 0;
// change content
update_ins_sti_enable(spi_txbuf, TRUE);
// ins buf [4:7]
update_ins_sti_enable(spi_txbuf + 4, TRUE);
update_ins_sti_channel(spi_txbuf + 4, 0xF, INSTRUCTION.sti_channel_pmos);
// ins buf [8:B]
update_ins_sti_enable(spi_txbuf + 8, FALSE);
break;
case STI_MODE_P2N:
case STI_MODE_N2P:
// copy [4:7]
spi_txbuf[4] = spi_txbuf[0];
spi_txbuf[5] = spi_txbuf[1];
spi_txbuf[6] = spi_txbuf[2];
spi_txbuf[7] = spi_txbuf[3];
// copy [8:B]
spi_txbuf[8] = spi_txbuf[0];
spi_txbuf[9] = spi_txbuf[1];
spi_txbuf[10] = spi_txbuf[2];
spi_txbuf[11] = spi_txbuf[3];
// copy [C:F]
spi_txbuf[12] = spi_txbuf[0];
spi_txbuf[13] = spi_txbuf[1];
spi_txbuf[14] = spi_txbuf[2];
spi_txbuf[15] = spi_txbuf[3];
// change content
update_ins_sti_enable(spi_txbuf + 0, TRUE);
update_ins_sti_channel(spi_txbuf + 0, INSTRUCTION.sti_channel_pmos, INSTRUCTION.sti_channel_nmos);
// ins buf [4:7]
update_ins_sti_enable(spi_txbuf + 4, TRUE);
update_ins_sti_channel(spi_txbuf + 4, INSTRUCTION.sti_channel_nmos, INSTRUCTION.sti_channel_pmos);
// ins buf [8:B]
update_ins_sti_enable(spi_txbuf + 8, TRUE);
update_ins_sti_channel(spi_txbuf + 8, 0xF, INSTRUCTION.sti_channel_nmos);
// ins buf [C:F]
update_ins_sti_enable(spi_txbuf + 12, FALSE);
break;
case STI_MODE_AWF:
// XXX define the voltage change
break;
default:
// do nothing
break;
}
}
static void headstage_tni_periodic() {
if (!INSTRUCTION.flag_start) return;
bool adc_clock_signal = (INSTRUCTION.adc_clock_signal) ? FALSE : TRUE; // flip adc_clock_signal
INSTRUCTION.adc_clock_signal = adc_clock_signal;
if (IS_REC_MODE(INSTRUCTION.mode)) {
// recording mode
if (adc_clock_signal && update_ins_rec_buffer()) {
headstage_pin_output(PIN_P2S_RST, 1); // DBS_P2S turn on
headstage_spi_transaction(SPI_BUFFER_SIZE, spi_txbuf, spi_rxbuf);
headstage_pin_output(PIN_P2S_RST, 0); // DBS_P2S turn off
}
goto collect_data;
} else if (IS_ARM_MODE(INSTRUCTION.mode)) {
// artifact recording mode
if (adc_clock_signal && update_ins_rec_buffer()) {
headstage_arm_append_ramp_data(spi_rxbuf);
}
goto collect_data;
} else if (IS_STI_MODE(INSTRUCTION.mode)) {
// stimulation mode
update_ins_sti_buffer();
headstage_spi_transaction(SPI_BUFFER_SIZE, spi_txbuf, NULL);
}
return;
collect_data:
if (!adc_clock_signal) {
headstage_tni_data_append_notify_buffer(spi_rxbuf);
headstage_pin_output(PIN_S2P_RST, 1);
if (actual_frequency() < 1000) {
// low sampling rate data
// append 0 at end of the data
headstage_notify_buffer[not_buf_offset] = 0;
headstage_notify_buffer[not_buf_offset + 1] = 0;
// prepare to send notify
headstage_notify_flip_buffer();
headstage_notify_send();
}
}
return;
}
#endif // HEADSTAGE_TNI_H
@@ -0,0 +1,412 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_H
#error "headstage.h not include"
#endif
#ifndef HEADSTAGE_ZM_H
#define HEADSTAGE_ZM_H
// product information
#define DEVICE_NAME "Elite-ZM-v1.2-30"
#define MAJOR_PRODUCT_NUMBER 0
#define MINOR_PRODUCT_NUMBER 2
#define MAJOR_VERSION_NUMBER 1
#define MINOR_VERSION_NUMBER 2
#define HEADSTAGE_LED_USE_SPI
#include "headstage_arm.h"
#include "headstage_clock.h"
#include "headstage_notify.h"
#include "zm/headstage_pin.h"
#include "zm/headstage_spi.h"
#include "headstage_led.h"
/*=================================
==== constant parameter table ====
================================*/
// clang-format off
#define RIS_DAC 0x10
#define RIS_ADC 0x20
#define RIS_MODE 0x30
// clang-format on
// clang-format off
#define MODE_IV 0x01
#define MODE_CV 0x02
#define MODE_GEN 0x03
#define MODE_ZT 0x04
#define MODE_VT 0x05
#define MODE_IT 0x06
#define MODE_POWER_ON 0x10
#define MODE_READY 0x20
// clang-format on
#define COLOR_POWER_ON COLOR_GREEN
/*========================
==== parameter table ====
========================*/
struct HEADSTAGE_PARAMETER_TABLE {
uint8_t mode;
void (*headstage_zm_periodic)();
/** RATE. ADC clock/sampling rate value*/
uint32_t adc_clock_rate;
/** CS **/
uint8_t chip_select;
// DAC
// uint8_t register_address;
//
// uint8_t clear_voltage_selection;
//
// uint8_t overrange;
//
// uint8_t bipolar_range;
//
// uint8_t thermal_shutdown_alert;
//
// /** I **/
// uint8_t internal_ref;
//
// /** PV **/
// uint8_t power_up_voltage;
//
// /** RA **/
// uint8_t output_range;
// ADC
/** SS **/
uint8_t single_short;
/** MUX **/
uint8_t multi_config;
/** PGA **/
uint8_t gain_amp_config;
/** M **/
uint8_t operating_mode;
/** DR **/
uint8_t adc_data_rate;
uint8_t temp_sensor;
uint8_t pullup_R_enable;
uint8_t no_operation;
uint8_t reserved;
} INSTRUCTION = {0};
/*=============================
==== function declaration ====
============================*/
static void headstage_zm_mode_init();
static void headstage_zm_mode_IV();
static void headstage_zm_mode_CV();
static void headstage_zm_mode_func_gen();
static void headstage_zm_mode_ZT();
static void headstage_zm_mode_VT();
static void headstage_zm_mode_IT();
static void headstage_zm_turn(uint8_t on_off);
static void headstage_zm_switch(uint8_t hold);
/*=======================
==== event dispatch ====
=======================*/
// clang-format off
#define EVT_MODE_CHANGE 0x0001
#define EVT_SWITCH_MASK 0x0030
// clang-format on
// clang-format off
#define SWITCH_PRESSED 0x0010
#define SWITCH_HOLDING 0x0020
#define SWITCH_FUNCTION 0x0030
// clang-format on
static void headstage_zm_event() {
uint16_t switch_state = (EVENT_MASK & EVT_SWITCH_MASK);
if (flag_mask(EVT_PERIODIC_CLOCK)) {
flag_disable(EVT_PERIODIC_CLOCK);
if (switch_state == SWITCH_HOLDING) {
headstage_zm_switch(1);
}
if (INSTRUCTION.headstage_zm_periodic) {
INSTRUCTION.headstage_zm_periodic();
}
}
if (EVENT_MASK == 0) {
// fast return
return;
}
if (switch_state == SWITCH_FUNCTION) {
flag_disable(EVT_SWITCH_MASK);
headstage_zm_turn((INSTRUCTION.mode & MODE_READY) == 0);
} else if (switch_state == SWITCH_PRESSED) {
headstage_zm_switch(0);
}
if (flag_mask(EVT_MODE_CHANGE)) {
flag_disable(EVT_MODE_CHANGE);
headstage_zm_mode_init();
}
if (flag_mask(EVT_DISCONNECTED)) {
headstage_update_vis_instruction(VIS_INT);
}
}
static void headstage_zm_pin_callback(PIN_Handle handle, PIN_Id pin) {
switch (pin) {
case PIN_SWITCH_ON:
flag_notify(SWITCH_PRESSED);
break;
}
}
/*=====================
==== ADC function ====
=====================*/
/*=====================
==== DAC function ====
=====================*/
#define DAC_CMD_W_IN_REG 0x00
#define DAC_CMD_W_DAC_REG 0x10
#define DAC_CMD_WRITE_REG 0x30
#define DAC_CMD_POWER_ON 0x40
#define DAC_CMD_REF_INT 0x60
#define DAC_CMD_REF_EXT 0x70
static uint8_t build_dac_instruction(uint8_t* ins_buf, uint8_t command, uint8_t p1, uint8_t p2) {
uint8_t* p = ins_buf;
*p++ = command;
*p++ = p1;
*p++ = p2;
return p - ins_buf;
}
static void headstage_dac_send(uint8_t command, uint8_t p1, uint8_t p2) {
build_dac_instruction(headstage_spi_dac_txbuf, command, p1, p2);
headstage_pin_output(PIN_DAC_CS, 0);
headstage_dac_transaction();
headstage_pin_output(PIN_DAC_CS, 1);
}
/*===========================
==== function implement ====
==========================*/
static void headstage_init() {
headstage_pin_open();
headstage_led_open();
headstage_spi_open();
PIN_registerIntCb(headstage_pins_handle, &headstage_zm_pin_callback);
PIN_setInterrupt(headstage_pins_handle, PIN_SWITCH_ON | PIN_IRQ_NEGEDGE);
headstage_pin_output(PIN_SHUTDOWN_6994, 1);
headstage_pin_output(PIN_ENABLE_V05, 1);
headstage_pin_output(PIN_ENABLE_V10, 1);
headstage_pin_output(PIN_ADC_CS, 1);
headstage_pin_output(PIN_DAC_CS, 1);
INSTRUCTION.mode = MODE_POWER_ON;
}
static void headstage_zm_turn(uint8_t on_off) {
if (on_off) {
// turn on
headstage_led_color(COLOR_POWER_ON);
INSTRUCTION.mode = MODE_READY;
} else {
// shutdown
headstage_pin_output(PIN_ENABLE_V05, 0);
}
}
static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t* instruction) {
uint8_t header = instruction[0] & 0xF0;
switch (header) {
case RIS_MODE:
INSTRUCTION.mode = (INSTRUCTION.mode & 0xF0) | (instruction[1] & 0x0F);
flag_notify(EVT_MODE_CHANGE);
break;
case RIS_ADC:
case RIS_DAC:
default:
break;
}
}
static void headstage_update_vis_instruction(uint8_t vis_oper) {
switch (vis_oper) {
case VIS_ASK:{
break;
}
case VIS_INT:{
break;
}
case VIS_FUH:{
break;
}
case VIS_CAL:{
break;
}
case VIS_STI:{
break;
}
case VIS_RST:{
break;
}
default :{
break;
}
}
}
static void headstage_zm_switch(uint8_t hold) {
static uint32_t time_stamp = 0;
bool working = (INSTRUCTION.mode & MODE_READY) != 0;
if (!hold) {
// button just pressed
time_stamp = headstage_time_stamp_ms();
if (!headstage_clock_active()) {
// TODO clock period
headstage_clock_open(250);
headstage_clock_start();
}
flag_disable(EVT_SWITCH_MASK);
flag_enable(SWITCH_HOLDING);
} else if (headstage_pin_input(PIN_SWITCH_ON)) {
// button released
if (!working) {
headstage_clock_stop();
headstage_clock_close();
}
flag_disable(EVT_SWITCH_MASK);
} else {
// button still pressing
uint32_t current = headstage_time_stamp_ms();
if (current - time_stamp >= ((working) ? 3000 : 1000)) { // 3 sec
headstage_clock_stop();
headstage_clock_close();
flag_notify(SWITCH_FUNCTION);
}
}
return;
}
/*====================================
==== Elite ZM function implement ====
===================================*/
static void headstage_zm_mode_init() {
switch (INSTRUCTION.mode) {
case MODE_READY | MODE_IV:
headstage_led_color(COLOR_RED);
INSTRUCTION.headstage_zm_periodic = &headstage_zm_mode_IV;
break;
case MODE_READY | MODE_CV:
headstage_led_color(COLOR_ORANGE);
INSTRUCTION.headstage_zm_periodic = &headstage_zm_mode_CV;
break;
case MODE_READY | MODE_GEN:
headstage_led_color(COLOR_YELLOW);
INSTRUCTION.headstage_zm_periodic = &headstage_zm_mode_func_gen;
break;
case MODE_READY | MODE_ZT:
headstage_led_color(COLOR_GREEN);
INSTRUCTION.headstage_zm_periodic = &headstage_zm_mode_ZT;
break;
case MODE_READY | MODE_VT:
headstage_led_color(COLOR_BLUE);
INSTRUCTION.headstage_zm_periodic = &headstage_zm_mode_VT;
break;
case MODE_READY | MODE_IT:
headstage_led_color(COLOR_CYAN);
INSTRUCTION.headstage_zm_periodic = &headstage_zm_mode_IT;
break;
default:
headstage_led_color(COLOR_BLACK);
INSTRUCTION.mode = MODE_READY;
INSTRUCTION.headstage_zm_periodic = NULL;
return;
}
headstage_clock_open(500);
}
static void headstage_zm_mode_IV() {
// TODO
}
static void headstage_zm_mode_CV() {
// TODO
}
static void headstage_zm_mode_func_gen() {
// TODO
}
static void headstage_zm_mode_ZT() {
// TODO
}
static void headstage_zm_mode_VT() {
// TODO
}
static void headstage_zm_mode_IT() {
// TODO
}
#endif // HEADSTAGE_ZM_H
@@ -0,0 +1,23 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef POPULATION_H
#define POPULATION_H
static uint32_t pop_count(uint32_t value) {
value -= ((value >> 1) & 0x55555555);
value = (((value >> 2) & 0x33333333) + (value & 0x33333333));
value = (((value >> 4) + value) & 0x0f0f0f0f);
value += (value >> 8);
value += (value >> 16);
return (value & 0x0000003f);
}
static uint32_t bit_reverse(uint32_t value) {
value = (((value & 0xaaaaaaaa) >> 1) | ((value & 0x55555555) << 1));
value = (((value & 0xcccccccc) >> 2) | ((value & 0x33333333) << 2));
value = (((value & 0xf0f0f0f0) >> 4) | ((value & 0x0f0f0f0f) << 4));
value = (((value & 0xff00ff00) >> 8) | ((value & 0x00ff00ff) << 8));
return ((value >> 16) | (value << 16));
}
#endif // POPULATION_H
@@ -0,0 +1,40 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_ADC_H
#define HEADSTAGE_ADC_H
#if defined(BOOSTXL_CC2650MA) && !defined(HEADSTAGE_MA_USE_ADC)
#error "put HEADSTAGE_MA_USE_ADC in predefined"
#endif
#include <Board.h>
#include <ti/drivers/ADC.h>
#if defined(CC2650_LAUNCHXL)
#define CC2650_ADC0 CC2650_LAUNCHXL_ADC0
#define CC2650_ADC1 CC2650_LAUNCHXL_ADC1
#define CC2650_ADC2 CC2650_LAUNCHXL_ADC2
#elif defined(BOOSTXL_CC2650MA)
#define CC2650_ADC0 BOOSTXL_CC2650MA_ADC0
#define CC2650_ADC1 BOOSTXL_CC2650MA_ADC1
#define CC2650_ADC2 BOOSTXL_CC2650MA_ADC2
#endif
static ADC_Handle headstage_adc_handle_0;
static ADC_Handle headstage_adc_handle_1;
static ADC_Handle headstage_adc_handle_2;
#define headstage_adc_close(handle) ADC_close(handle)
#define headstage_adc_convert(handle, value) ADC_convert(handle, value)
#define headstage_adc_open() \
do { \
ADC_init(); \
ADC_Params param; \
ADC_Params_init(&params); \
headstage_adc_handle_0 = ADC_open(CC2650_ADC0, &param); \
headstage_adc_handle_1 = ADC_open(CC2650_ADC1, &param); \
headstage_adc_handle_2 = ADC_open(CC2650_ADC2, &param); \
} while (0)
#endif // HEADSTAGE_ADC_H
@@ -0,0 +1,53 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_GPTIMER_H
#define HEADSTAGE_GPTIMER_H
#include <Board.h>
#include <ti/drivers/timer/GPTimerCC26XX.h>
#include <ti/sysbios/BIOS.h>
#include <xdc/runtime/Types.h>
#define EVT_PERIODIC_GPTIMER_0 EVT_PERIODIC_0
#define EVT_PERIODIC_GPTIMER_1 EVT_PERIODIC_1
#define EVT_PERIODIC_GPTIMER_2 EVT_PERIODIC_2
static GPTimerCC26XX_Handle gptimer_handle_0;
static GPTimerCC26XX_Handle gptimer_handle_1;
static GPTimerCC26XX_Handle gptimer_handle_2;
static void headstage_gptimer_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
#define headstage_gptimer_start(gptimer_handle) GPTimerCC26XX_start(gptimer_handle)
#define headstage_gptimer_stop(gptimer_handle) GPTimerCC26XX_stop(gptimer_handle)
#define headstage_gptimer_close(gptimer_handle) GPTimerCC26XX_close(gptimer_handle)
#define headstage_gptimer_open() \
do { \
GPTimerCC26XX_Params params; \
GPTimerCC26XX_Params_init(&params); \
params.width = GPT_CONFIG_16BIT; \
params.mode = GPT_MODE_PERIODIC_DOWN; \
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF; \
gptimer_handle_0 = GPTimerCC26XX_open(Board_GPTIMER0A, &params); \
gptimer_handle_1 = GPTimerCC26XX_open(Board_GPTIMER1A, &params); \
gptimer_handle_2 = GPTimerCC26XX_open(Board_GPTIMER2A, &params); \
GPTimerCC26XX_setLoadValue(gptimer_handle_0, 0xFFFFFF); \
GPTimerCC26XX_setLoadValue(gptimer_handle_1, 0xFFFFFF); \
GPTimerCC26XX_setLoadValue(gptimer_handle_2, 0xFFFFFF); \
GPTimerCC26XX_registerInterrupt(gptimer_handle_0, headstage_gptimer_callback, GPT_INT_TIMEOUT); \
GPTimerCC26XX_registerInterrupt(gptimer_handle_1, headstage_gptimer_callback, GPT_INT_TIMEOUT); \
GPTimerCC26XX_registerInterrupt(gptimer_handle_2, headstage_gptimer_callback, GPT_INT_TIMEOUT); \
} while (0)
#define headstage_gptimer_set_frequency(gptimer_handle, frequency) \
do { \
uint32_t _frequency = (uint32_t)(frequency); \
Types_FreqHz _cpu_freq; \
BIOS_getCpuFreq(&_cpu_freq); \
GPTimerCC26XX_Value _load = _cpu_freq.lo / _frequency - 1; \
_load = (_load < 0xFFFF) ? _load : ((0xFA0000 | (_load / 250)) - 1); \
GPTimerCC26XX_setLoadValue(gptimer_handle, _load); \
} while (0)
#endif // HEADSTAGE_GPTIMER_H
@@ -0,0 +1,58 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_NOTIFY_TDC4VC3_H
#define HEADSTAGE_NOTIFY_TDC4VC3_H
#ifndef HEADSTAGE_NOTIFY_H
#error "headstage/headstage_notify.h not included"
#endif
#define NOT_BUF_OFFSET_INIT 6
static uint32_t not_buf_offset = NOT_BUF_OFFSET_INIT;
static uint32_t not_time_stamp = 0;
static void headstage_notify_set_timestamp() {
not_time_stamp = headstage_time_stamp_us();
headstage_notify_buffer[2] = not_time_stamp & 0xFF;
headstage_notify_buffer[3] = (not_time_stamp >> 8) & 0xFF;
headstage_notify_buffer[4] = (not_time_stamp >> 16) & 0xFF;
headstage_notify_buffer[5] = (not_time_stamp >> 24) & 0xFF;
}
static void headstage_notify_flip_buffer() {
uint8_t data_count = not_buf_offset;
headstage_notify_buffer[0] = CHIP_ID;
headstage_notify_buffer[1] = data_count;
not_buf_offset = NOT_BUF_OFFSET_INIT;
}
static uint8_t headstage_notify_append_data(uint8_t channel, uint16_t data_value) {
if (not_buf_offset <= NOT_BUF_OFFSET_INIT) {
headstage_notify_set_timestamp();
not_buf_offset = NOT_BUF_OFFSET_INIT;
}
if (not_buf_offset >= BLE_NOT_BUFF_SIZE) {
return not_buf_offset;
}
headstage_notify_buffer[not_buf_offset++] = ((channel & 0x0F) << 4) | ((data_value >> 8) & 0x0F);
headstage_notify_buffer[not_buf_offset++] = (data_value & 0xFF);
uint8_t ret = not_buf_offset;
if (not_buf_offset >= BLE_NOT_BUFF_SIZE) {
headstage_notify_flip_buffer();
}
return ret;
}
#endif // HEADSTAGE_NOTIFY_TDC4VC3_H
@@ -0,0 +1,60 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_PIN_H
#define HEADSTAGE_PIN_H
#include <Board.h>
#include <ti/drivers/PIN.h>
static PIN_State headstage_pins_state;
static PIN_Handle headstage_pins_handle;
// clang-format off
// XXX name those pin with its propose
#define PIN_STI_0 IOID_0
#define PIN_STI_1 IOID_1
#define PIN_STI_3 IOID_3
#define PIN_STI_5 IOID_5
#define PIN_STI_6 IOID_6
#define PIN_STI_7 IOID_7
#define PIN_STI_10 IOID_10
#define PIN_STI_11 IOID_11
// clang-format on
#if defined(CC2650_LAUNCHXL)
#define PIN_LED_R Board_RLED
#define PIN_LED_G Board_GLED
#endif
static PIN_Config headstage_pin_configuration[] = { //
PIN_STI_0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_STI_1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_STI_3 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_STI_5 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_STI_6 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_STI_7 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_STI_10 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_STI_11 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
// LED
#if defined(CC2650_LAUNCHXL)
PIN_LED_R | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_LED_G | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
#endif
//
PIN_TERMINATE};
#define headstage_pin_add(configuration) PIN_add(headstage_pins_handle, configuration)
#define headstage_pin_remove(pin) PIN_remove(headstage_pins_handle, pin)
#define headstage_pin_close() PIN_close(headstage_pins_handle)
#define headstage_pin_open() \
do { \
headstage_pins_handle = PIN_open(&headstage_pins_state, headstage_pin_configuration); \
} while (0)
#define headstage_pin_output(pin, value) PIN_setOutputValue(headstage_pins_handle, PIN_ID(pin), (value))
#define headstage_pin_input(pin) PIN_getInputValue(PIN_ID(pin))
#endif // HEADSTAGE_PIN_H
@@ -0,0 +1,41 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_PWM_H
#define HEADSTAGE_PWM_H
#include <Board.h>
#include <ti/drivers/PWM.h>
#define MAX_DUTY 6900
static PWM_Handle headstage_pwm_handle;
#define headstage_pwm_open() \
do { \
PWM_init(); \
PWM_Params params; \
PWM_Params_init(&params); \
params.idleLevel = PWM_IDLE_LOW; \
params.periodUnits = PWM_PERIOD_COUNTS; \
params.periodValue = MAX_DUTY; \
params.dutyUnits = PWM_DUTY_COUNTS; \
params.dutyValue = 1; \
headstage_pwm_handle = PWM_open(Board_PWM7, &params); \
} while (0);
#define headstage_pwm_start() PWM_start(headstage_pwm_handle)
#define headstage_pwm_stop() PWM_stop(headstage_pwm_handle)
#define headstage_pwm_close() PWM_close(headstage_pwm_handle)
#define headstage_pwm_set(frequency, duty_cycle) \
do { \
int status = PWM_setPeriod(headstage_pwm_handle, frequency); \
if (status < 0) { \
PWM_stop(headstage_pwm_handle); \
PWM_setPeriod(headstage_pwm_handle, frequency); \
} \
PWM_setDuty(headstage_pwm_handle, duty_cycle); \
if (status < 0) PWM_start(headstage_pwm_handle); \
} while (0)
#endif // HEADSTAGE_PWM_H
@@ -0,0 +1,68 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_NOTIFY_TDC4VAF2_H
#define HEADSTAGE_NOTIFY_TDC4VAF2_H
#ifndef HEADSTAGE_NOTIFY_H
#error "headstage/headstage_notify.h not included"
#endif
#define NOT_BUF_OFFSET_INIT 8
static uint32_t not_buf_offset = NOT_BUF_OFFSET_INIT;
static uint32_t not_time_stamp = 0;
static void headstage_notify_set_timestamp() {
not_time_stamp = headstage_time_stamp_us();
headstage_notify_buffer[2] = not_time_stamp & 0xFF;
headstage_notify_buffer[3] = (not_time_stamp >> 8) & 0xFF;
headstage_notify_buffer[4] = (not_time_stamp >> 16) & 0xFF;
headstage_notify_buffer[5] = (not_time_stamp >> 24) & 0xFF;
}
static void headstage_notify_flip_buffer() {
uint8_t data_count = (not_buf_offset - NOT_BUF_OFFSET_INIT) / 2;
headstage_notify_buffer[0] = CHIP_ID;
headstage_notify_buffer[1] = data_count;
not_buf_offset = NOT_BUF_OFFSET_INIT;
}
static uint8_t headstage_notify_append_data(uint8_t channel, uint16_t *data_value) {
if (not_buf_offset <= NOT_BUF_OFFSET_INIT) {
headstage_notify_set_timestamp();
not_buf_offset = NOT_BUF_OFFSET_INIT;
}
if (not_buf_offset >= BLE_NOT_BUFF_SIZE) {
return not_buf_offset;
}
if (data_value == NULL) {
headstage_notify_buffer[not_buf_offset++] = ((channel & 0x0F) << 4);
headstage_notify_buffer[not_buf_offset++] = 0x03;
} else {
headstage_notify_buffer[not_buf_offset++] = ((channel & 0x0F) << 4) | ((*data_value >> 6) & 0x0F);
headstage_notify_buffer[not_buf_offset++] = ((*data_value << 2) & 0xFC);
}
uint8_t ret = not_buf_offset;
if (not_buf_offset >= BLE_NOT_BUFF_SIZE) {
uint32_t current = headstage_time_stamp_us();
uint32_t time_delta = (current - not_time_stamp) & 0xFFFF;
headstage_notify_buffer[6] = time_delta & 0xFF;
headstage_notify_buffer[7] = (time_delta >> 8) & 0xFF;
headstage_notify_flip_buffer();
}
return ret;
}
#endif // HEADSTAGE_NOTIFY_TDC4VAF2_H
@@ -0,0 +1,46 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_PIN_H
#define HEADSTAGE_PIN_H
#include <Board.h>
#include <ti/drivers/PIN.h>
#if defined(CC2650_LAUNCHXL)
#define PIN_LED_R IOID_6
#define PIN_LED_G IOID_7
#endif
#define PIN_P2S_RST IOID_6
#define PIN_S2P_RST IOID_7
static PIN_State headstage_pins_state;
static PIN_Handle headstage_pins_handle;
static PIN_Config headstage_pin_configuration[] = { //
// LED
#if defined(CC2650_LAUNCHXL)
PIN_LED_R | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_LED_G | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
#else
PIN_P2S_RST | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_S2P_RST | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
#endif
//
PIN_TERMINATE};
#define headstage_pin_add(configuration) PIN_add(headstage_pins_handle, configuration)
#define headstage_pin_remove(pin) PIN_remove(headstage_pins_handle, pin)
#define headstage_pin_close() PIN_close(headstage_pins_handle)
#define headstage_pin_open() \
do { \
headstage_pins_handle = PIN_open(&headstage_pins_state, headstage_pin_configuration); \
} while (0)
#define headstage_pin_output(pin, value) PIN_setOutputValue(headstage_pins_handle, PIN_ID(pin), (value))
#define headstage_pin_input(pin) PIN_getInputValue(PIN_ID(pin))
#endif // HEADSTAGE_PIN_H
@@ -0,0 +1,47 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_SPI_H
#define HEADSTAGE_SPI_H
#include <Board.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/dma/UDMACC26XX.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
/*
* SPI parameter and function declaration
*/
static SPI_Handle spi_handle;
static SPI_Transaction spi_transaction;
#define headstage_spi_close() SPI_close(spi_handle)
#define headstage_spi_transaction_cancel() SPI_transferCancel(spi_handle)
// SPI parameters initialize
#define headstage_spi_open() \
do { \
SPI_init(); \
SPI_Params spi_parameter; \
SPI_Params_init(&spi_parameter); \
spi_parameter.transferMode = SPI_MODE_BLOCKING; \
spi_parameter.mode = SPI_MASTER; \
spi_parameter.bitRate = 12000000; \
spi_parameter.dataSize = 8; \
spi_parameter.frameFormat = SPI_POL0_PHA1; \
spi_handle = SPI_open(Board_SPI0, &spi_parameter); \
} while (0)
#define headstage_spi_transaction(len, tx, rx) \
({ \
spi_transaction.txBuf = (tx); \
spi_transaction.rxBuf = (rx); \
spi_transaction.count = (len); \
SPI_transfer(spi_handle, &spi_transaction); \
})
#define SPI_BUFFER_SIZE 16
static uint8_t spi_txbuf[SPI_BUFFER_SIZE] = {0};
static uint8_t spi_rxbuf[SPI_BUFFER_SIZE] = {0};
#endif // HEADSTAGE_SPI_H
@@ -0,0 +1,5 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_ADC_H
#define HEADSTAGE_ADC_H
#endif // HEADSTAGE_ADC_H
@@ -0,0 +1,45 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_GPTIMER_H
#define HEADSTAGE_GPTIMER_H
#include <Board.h>
#include <ti/drivers/timer/GPTimerCC26XX.h>
#include <ti/sysbios/BIOS.h>
#include <xdc/runtime/Types.h>
#define EVT_PERIODIC_GPTIMER EVT_PERIODIC_0
static GPTimerCC26XX_Handle gptimer_handle;
static void headstage_gptimer_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
flag_notify(EVT_PERIODIC_GPTIMER);
}
#define headstage_gptimer_start() GPTimerCC26XX_start(gptimer_handle)
#define headstage_gptimer_stop() GPTimerCC26XX_stop(gptimer_handle)
#define headstage_gptimer_close() GPTimerCC26XX_close(gptimer_handle)
#define headstage_gptimer_open() \
do { \
GPTimerCC26XX_Params params; \
GPTimerCC26XX_Params_init(&params); \
params.width = GPT_CONFIG_16BIT; \
params.mode = GPT_MODE_PERIODIC_DOWN; \
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF; \
gptimer_handle = GPTimerCC26XX_open(Board_GPTIMER0A, &params); \
GPTimerCC26XX_setLoadValue(gptimer_handle, 0xFFFFFF); \
GPTimerCC26XX_registerInterrupt(gptimer_handle, headstage_gptimer_callback, GPT_INT_TIMEOUT); \
} while (0)
#define headstage_gptimer_set_frequency(frequency) \
do { \
uint32_t _frequency = (uint32_t)(frequency); \
Types_FreqHz _cpu_freq; \
BIOS_getCpuFreq(&_cpu_freq); \
GPTimerCC26XX_Value _load = _cpu_freq.lo / _frequency - 1; \
_load = (_load < 0xFFFF) ? _load : ((0xFA0000 | (_load / 250)) - 1); \
GPTimerCC26XX_setLoadValue(gptimer_handle, _load); \
} while (0)
#endif // HEADSTAGE_GPTIMER_H
@@ -0,0 +1,44 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_PIN_H
#define HEADSTAGE_PIN_H
#include <Board.h>
#include <ti/drivers/PIN.h>
// TODO
#define PIN_RESET PIN_UNASSIGNED
#define PIN_TRIGGER PIN_UNASSIGNED
#if defined(CC2650_LAUNCHXL)
#define PIN_LED_R IOID_6
#define PIN_LED_G IOID_7
#endif
static PIN_State headstage_pins_state;
static PIN_Handle headstage_pins_handle;
static PIN_Config headstage_pin_configuration[] = { //
// LED
#if defined(CC2650_LAUNCHXL)
PIN_LED_R | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_LED_G | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
#endif
//
PIN_TERMINATE};
#define headstage_pin_add(configuration) PIN_add(headstage_pins_handle, configuration)
#define headstage_pin_remove(pin) PIN_remove(headstage_pins_handle, pin)
#define headstage_pin_close() PIN_close(headstage_pins_handle)
#define headstage_pin_open() \
do { \
headstage_pins_handle = PIN_open(&headstage_pins_state, headstage_pin_configuration); \
} while (0)
#define headstage_pin_output(pin, value) PIN_setOutputValue(headstage_pins_handle, PIN_ID(pin), (value))
#define headstage_pin_input(pin) PIN_getInputValue(PIN_ID(pin))
#endif // HEADSTAGE_PIN_H
@@ -0,0 +1,36 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_PWM_H
#define HEADSTAGE_PWM_H
#include <Board.h>
#include <ti/drivers/PWM.h>
static PWM_Handle headstage_system_pwm_handle;
static PWM_Handle headstage_poly_r_pwm_handle; // poly-R adjustment clock
#define headstage_pwm_open() \
do { \
PWM_init(); \
PWM_Params params; \
PWM_Params_init(&params); \
params.idleLevel = PWM_IDLE_LOW; \
params.periodUnits = PWM_PERIOD_HZ; \
params.periodValue = UMC_SYS_CLK; \
params.dutyUnits = PWM_DUTY_FRACTION; \
params.dutyValue = PWM_DUTY_FRACTION_MAX / 2; \
headstage_system_pwm_handle = PWM_open(Board_PWM2, &params); \
PWM_Params_init(&params); \
params.idleLevel = PWM_IDLE_LOW; \
params.periodUnits = PWM_PERIOD_HZ; \
params.periodValue = UMC_POLY_R_CLK; \
params.dutyUnits = PWM_DUTY_FRACTION; \
params.dutyValue = PWM_DUTY_FRACTION_MAX / 2; \
headstage_poly_r_pwm_handle = PWM_open(Board_PWM0, &params); \
} while (0);
#define headstage_pwm_start(handle) PWM_start(handle)
#define headstage_pwm_stop(handle) PWM_stop(handle)
#define headstage_pwm_close(handle) PWM_close(handle)
#endif // HEADSTAGE_PWM_H
@@ -0,0 +1,93 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_SPI_H
#define HEADSTAGE_SPI_H
#if defined(BOOSTXL_CC2650MA) && !defined(HEADSTAGE_MA_USE_SPI2)
#error "put HEADSTAGE_MA_USE_SPI2 in predefined"
#endif
#include <Board.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/dma/UDMACC26XX.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
#define SPI_BUFFER_SIZE 20
static uint8_t spi_txbuf[SPI_BUFFER_SIZE] = {0};
static uint8_t spi_rxbuf[SPI_BUFFER_SIZE] = {0};
static SPI_Handle headstage_spi_ask_handle = NULL;
static SPI_Handle headstage_spi_lsk_handle = NULL;
static SPI_Transaction headstage_ask_transaction;
static SPI_Transaction headstage_lsk_transaction;
static void headstage_spi_ask_callback(SPI_Handle handle, SPI_Transaction* transaction);
static void headstage_spi_lsk_callback(SPI_Handle handle, SPI_Transaction* transaction);
// SPI parameters initialize
// TODO update board.h
#define headstage_spi_open() \
do { \
SPI_init(); \
SPI_Params spi_parameter; \
SPI_Params_init(&spi_parameter); \
spi_parameter.transferMode = SPI_MODE_CALLBACK; \
spi_parameter.mode = SPI_MASTER; \
spi_parameter.bitRate = UMC_ASK_FREQ; \
spi_parameter.dataSize = 8; \
spi_parameter.frameFormat = SPI_POL0_PHA1; \
spi_parameter.transferCallbackFxn = headstage_spi_ask_callback; \
headstage_spi_ask_handle = SPI_open(Board_SPI0, &spi_parameter); \
SPI_Params_init(&spi_parameter); \
spi_parameter.transferMode = SPI_MODE_CALLBACK; \
spi_parameter.mode = SPI_SLAVE; \
spi_parameter.bitRate = UMC_LSK_FREQ; \
spi_parameter.dataSize = 8; \
spi_parameter.frameFormat = SPI_POL0_PHA1; \
spi_parameter.transferCallbackFxn = headstage_spi_lsk_callback; \
headstage_spi_lsk_handle = SPI_open(Board_SPI1, &spi_parameter); \
} while (0)
#define headstage_spi_transaction(handle, length, tx, rx) \
({ \
SPI_Transaction transaction = (handle == headstage_spi_ask_handle) ? headstage_ask_transaction : headstage_lsk_transaction; \
transaction.count = (length); \
transaction.txBuf = (tx); \
transaction.rxBuf = (rx); \
SPI_transfer(handle, &transaction); \
})
#define headstage_spi_ask_transaction(length) \
({ \
headstage_ask_transaction.count = (length); \
headstage_ask_transaction.txBuf = (spi_txbuf); \
headstage_ask_transaction.rxBuf = NULL; \
SPI_transfer(headstage_spi_ask_handle, &headstage_ask_transaction); \
})
#define headstage_spi_lsk_transaction(length) \
({ \
headstage_lsk_transaction.count = (length); \
headstage_lsk_transaction.txBuf = NULL; \
headstage_lsk_transaction.rxBuf = (spi_rxbuf); \
SPI_transfer(headstage_spi_lsk_handle, &headstage_lsk_transaction); \
})
#define headstage_spi_close(spi_handle) \
do { \
if (spi_handle != NULL) { \
SPI_close(spi_handle); \
spi_handle = NULL; \
} \
} while (0)
#define headstage_spi_transaction_cancel(spi_handle) \
do { \
if (spi_handle != NULL) { \
SPI_transferCancel(spi_handle); \
} \
} while (0)
#endif // HEADSTAGE_SPI_H
@@ -0,0 +1,60 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_PIN_H
#define HEADSTAGE_PIN_H
#include <Board.h>
#include <ti/drivers/PIN.h>
// clang-format off
#define PIN_ADC_CS IOID_2
#define PIN_DAC_CS IOID_4
#define PIN_SWITCH_ON IOID_10
#define PIN_SHUTDOWN_6994 IOID_11
#define PIN_ENABLE_V10 IOID_12
#define PIN_ENABLE_V05 IOID_14
// clang-format on
#if defined(CC2650_LAUNCHXL)
#define PIN_LED_R IOID_6
#define PIN_LED_G IOID_7
#endif
static PIN_State headstage_pins_state;
static PIN_Handle headstage_pins_handle;
static PIN_Config headstage_pin_configuration[] = { //
PIN_ADC_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_DAC_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_ENABLE_V05 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_ENABLE_V10 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
// turn off power
PIN_SHUTDOWN_6994 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
PIN_SWITCH_ON | PIN_INPUT_EN | PIN_PULLDOWN,
// LED
#if defined(CC2650_LAUNCHXL)
PIN_LED_R | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_LED_G | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX,
#endif
//
PIN_TERMINATE};
#define headstage_pin_add(configuration) PIN_add(headstage_pins_handle, configuration)
#define headstage_pin_remove(pin) PIN_remove(headstage_pins_handle, pin)
#define headstage_pin_close() PIN_close(headstage_pins_handle)
#define headstage_pin_open() \
do { \
headstage_pins_handle = PIN_open(&headstage_pins_state, headstage_pin_configuration); \
} while (0)
#define headstage_pin_output(pin, value) PIN_setOutputValue(headstage_pins_handle, PIN_ID(pin), (value))
#define headstage_pin_input(pin) PIN_getInputValue(PIN_ID(pin))
#endif // HEADSTAGE_PIN_H
@@ -0,0 +1,65 @@
/* Copyright (c) 2019. BioPro. Scientific.
*/
#ifndef HEADSTAGE_SPI_H
#define HEADSTAGE_SPI_H
#include <ti/drivers/SPI.h>
#include <ti/drivers/dma/UDMACC26XX.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
#define SPI_DAC_BUFF_SIZE 3
#define SPI_ADC_BUFF_SIZE 2
static uint8_t headstage_spi_dac_txbuf[SPI_DAC_BUFF_SIZE];
static uint8_t headstage_spi_dac_rxbuf[SPI_DAC_BUFF_SIZE];
static uint16_t headstage_spi_adc_txbuf[SPI_ADC_BUFF_SIZE];
static uint16_t headstage_spi_adc_rxbuf[SPI_ADC_BUFF_SIZE];
/*
* SPI parameter and function declaration
*/
static SPI_Handle headstage_spi_dac_handle = NULL;
static SPI_Transaction headstage_spi_dac_transaction;
#ifdef HEADSTAGE_LED_USE_SPI
#define headstage_spi_adc_handle led_handle
#define headstage_spi_adc_transaction led_transaction
#else
static SPI_Handle headstage_spi_adc_handle = NULL;
static SPI_Transaction headstage_spi_adc_transaction;
#endif
#define headstage_spi_close(handle) SPI_close(handle)
#define headstage_spi_transaction_cancel(handle) SPI_transferCancel(handle)
// SPI parameters initialize
#define headstage_spi_open() \
do { \
SPI_init(); \
SPI_Params spi_parameter; \
SPI_Params_init(&spi_parameter); \
spi_parameter.transferMode = SPI_MODE_BLOCKING; \
spi_parameter.mode = SPI_MASTER; \
spi_parameter.bitRate = 12000000; \
spi_parameter.dataSize = 8; \
spi_parameter.frameFormat = SPI_POL0_PHA0; \
headstage_spi_dac_handle = SPI_open(Board_SPI0, &spi_parameter); \
} while (0)
#define headstage_dac_transaction() \
({ \
headstage_spi_dac_transaction.txBuf = (headstage_spi_dac_txbuf); \
headstage_spi_dac_transaction.rxBuf = (headstage_spi_dac_rxbuf); \
headstage_spi_dac_transaction.count = (SPI_DAC_BUFF_SIZE); \
SPI_transfer(headstage_spi_dac_handle, &headstage_spi_dac_transaction); \
})
#define headstage_adc_transaction() \
({ \
headstage_spi_adc_transaction.txBuf = (headstage_spi_adc_txbuf); \
headstage_spi_adc_transaction.rxBuf = (headstage_spi_adc_rxbuf); \
headstage_spi_adc_transaction.count = (SPI_ADC_BUFF_SIZE); \
SPI_transfer(headstage_spi_adc_handle, &headstage_spi_adc_transaction); \
})
#endif // HEADSTAGE_SPI_H
@@ -8,7 +8,7 @@
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2013-2018, Texas Instruments Incorporated
All rights reserved.
@@ -44,29 +44,28 @@
Release Date: 2018-04-02 18:03:35
*****************************************************************************/
/*******************************************************************************
* INCLUDES
*/
/*================
==== include ====
===============*/
// clang-format off
#include <xdc/runtime/Error.h>
#include <ti/drivers/PIN.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
#include <ti/sysbios/BIOS.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
#include <ti/drivers/dma/UDMACC26XX.h>
#include "icall.h"
#include "hal_assert.h"
#include "bcomdef.h"
#include "peripheral.h"
#include "simple_peripheral.h"
/* Header files required to enable instruction fetch cache */
#include <inc/hw_memmap.h>
#include <driverlib/vims.h>
// clang-format on
#ifndef USE_DEFAULT_USER_CFG
@@ -77,68 +76,9 @@ bleUserCfg_t user0Cfg = BLE_USER_CFG;
#endif // USE_DEFAULT_USER_CFG
#include <ti/mw/display/Display.h>
extern const PIN_Config BoardGpioInitTable[];
#ifdef USE_FPGA
#include <inc/hw_prcm.h>
#endif // USE_FPGA
/*******************************************************************************
* MACROS
*/
/*******************************************************************************
* CONSTANTS
*/
#if defined( USE_FPGA )
#define RFC_MODE_BLE PRCM_RFCMODESEL_CURR_MODE1
#define RFC_MODE_ANT PRCM_RFCMODESEL_CURR_MODE4
#define RFC_MODE_EVERYTHING_BUT_ANT PRCM_RFCMODESEL_CURR_MODE5
#define RFC_MODE_EVERYTHING PRCM_RFCMODESEL_CURR_MODE6
//
#define SET_RFC_BLE_MODE(mode) HWREG( PRCM_BASE + PRCM_O_RFCMODESEL ) = (mode)
#endif // USE_FPGA
/*******************************************************************************
* TYPEDEFS
*/
/*******************************************************************************
* LOCAL VARIABLES
*/
/*******************************************************************************
* GLOBAL VARIABLES
*/
#ifdef CC1350_LAUNCHXL
#ifdef POWER_SAVING
// Power Notify Object for wake-up callbacks
Power_NotifyObj rFSwitchPowerNotifyObj;
static uint8_t rFSwitchNotifyCb(uint8_t eventType, uint32_t *eventArg,
uint32_t *clientArg);
#endif //POWER_SAVING
PIN_State radCtrlState;
PIN_Config radCtrlCfg[] =
{
Board_DIO1_RFSW | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* RF SW Switch defaults to 2.4GHz path*/
Board_DIO30_SWPWR | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* Power to the RF Switch */
PIN_TERMINATE
};
PIN_Handle radCtrlHandle;
#endif //CC1350_LAUNCHXL
/*******************************************************************************
* EXTERNS
*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
extern Display_Handle dispHandle;
/*******************************************************************************
/**
* @fn Main
*
* @brief Application Main
@@ -153,205 +93,28 @@ extern Display_Handle dispHandle;
*
* @return None.
*/
int main()
{
#if defined( USE_FPGA )
HWREG(PRCM_BASE + PRCM_O_PDCTL0) &= ~PRCM_PDCTL0_RFC_ON;
HWREG(PRCM_BASE + PRCM_O_PDCTL1) &= ~PRCM_PDCTL1_RFC_ON;
#endif // USE_FPGA
int main() {
PIN_init(BoardGpioInitTable);
/* Register Application callback to trap asserts raised in the Stack */
RegisterAssertCback(AssertHandler);
// Enable iCache prefetching
VIMSConfigure(VIMS_BASE, TRUE, TRUE);
PIN_init(BoardGpioInitTable);
// Enable cache
VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
#ifdef CC1350_LAUNCHXL
// Enable 2.4GHz Radio
radCtrlHandle = PIN_open(&radCtrlState, radCtrlCfg);
/* Initialize ICall module */
ICall_init();
#ifdef POWER_SAVING
Power_registerNotify(&rFSwitchPowerNotifyObj,
PowerCC26XX_ENTERING_STANDBY | PowerCC26XX_AWAKE_STANDBY,
(Power_NotifyFxn) rFSwitchNotifyCb, NULL);
#endif //POWER_SAVING
#endif //CC1350_LAUNCHXL
/* Start tasks of external images - Priority 5 */
ICall_createRemoteTasks();
#if defined( USE_FPGA )
// set RFC mode to support BLE
// Note: This must be done before the RF Core is released from reset!
SET_RFC_BLE_MODE(RFC_MODE_BLE);
#endif // USE_FPGA
/* Kick off profile - Priority 3 */
GAPRole_createTask();
// Enable iCache prefetching
VIMSConfigure(VIMS_BASE, TRUE, TRUE);
SimpleBLEPeripheral_createTask();
// Enable cache
VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
/* enable interrupts and start SYS/BIOS */
BIOS_start();
#if !defined( POWER_SAVING ) || defined( USE_FPGA )
/* Set constraints for Standby, powerdown and idle mode */
// PowerCC26XX_SB_DISALLOW may be redundant
Power_setConstraint(PowerCC26XX_SB_DISALLOW);
Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
#endif // POWER_SAVING | USE_FPGA
/* Initialize ICall module */
ICall_init();
/* Start tasks of external images - Priority 5 */
ICall_createRemoteTasks();
/* Kick off profile - Priority 3 */
GAPRole_createTask();
SimpleBLEPeripheral_createTask();
/* enable interrupts and start SYS/BIOS */
BIOS_start();
return 0;
return 0;
}
/*******************************************************************************
* @fn AssertHandler
*
* @brief This is the Application's callback handler for asserts raised
* in the stack. When EXT_HAL_ASSERT is defined in the Stack
* project this function will be called when an assert is raised,
* and can be used to observe or trap a violation from expected
* behavior.
*
* As an example, for Heap allocation failures the Stack will raise
* HAL_ASSERT_CAUSE_OUT_OF_MEMORY as the assertCause and
* HAL_ASSERT_SUBCAUSE_NONE as the assertSubcause. An application
* developer could trap any malloc failure on the stack by calling
* HAL_ASSERT_SPINLOCK under the matching case.
*
* An application developer is encouraged to extend this function
* for use by their own application. To do this, add hal_assert.c
* to your project workspace, the path to hal_assert.h (this can
* be found on the stack side). Asserts are raised by including
* hal_assert.h and using macro HAL_ASSERT(cause) to raise an
* assert with argument assertCause. the assertSubcause may be
* optionally set by macro HAL_ASSERT_SET_SUBCAUSE(subCause) prior
* to asserting the cause it describes. More information is
* available in hal_assert.h.
*
* input parameters
*
* @param assertCause - Assert cause as defined in hal_assert.h.
* @param assertSubcause - Optional assert subcause (see hal_assert.h).
*
* output parameters
*
* @param None.
*
* @return None.
*/
void AssertHandler(uint8 assertCause, uint8 assertSubcause)
{
// Open the display if the app has not already done so
if ( !dispHandle )
{
dispHandle = Display_open(Display_Type_LCD, NULL);
}
Display_print0(dispHandle, 0, 0, ">>>STACK ASSERT");
// check the assert cause
switch (assertCause)
{
case HAL_ASSERT_CAUSE_OUT_OF_MEMORY:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> OUT OF MEMORY!");
break;
case HAL_ASSERT_CAUSE_INTERNAL_ERROR:
// check the subcause
if (assertSubcause == HAL_ASSERT_SUBCAUSE_FW_INERNAL_ERROR)
{
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> INTERNAL FW ERROR!");
}
else
{
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> INTERNAL ERROR!");
}
break;
case HAL_ASSERT_CAUSE_ICALL_ABORT:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> ICALL ABORT!");
HAL_ASSERT_SPINLOCK;
break;
default:
Display_print0(dispHandle, 0, 0, "***ERROR***");
Display_print0(dispHandle, 2, 0, ">> DEFAULT SPINLOCK!");
HAL_ASSERT_SPINLOCK;
}
return;
}
/*******************************************************************************
* @fn smallErrorHook
*
* @brief Error handler to be hooked into TI-RTOS.
*
* input parameters
*
* @param eb - Pointer to Error Block.
*
* output parameters
*
* @param None.
*
* @return None.
*/
void smallErrorHook(Error_Block *eb)
{
for (;;);
}
#if defined (CC1350_LAUNCHXL) && defined (POWER_SAVING)
/*******************************************************************************
* @fn rFSwitchNotifyCb
*
* @brief Power driver callback to toggle RF switch on Power state
* transitions.
*
* input parameters
*
* @param eventType - The state change.
* @param eventArg - Not used.
* @param clientArg - Not used.
*
* @return Power_NOTIFYDONE to indicate success.
*/
static uint8_t rFSwitchNotifyCb(uint8_t eventType, uint32_t *eventArg,
uint32_t *clientArg)
{
if (eventType == PowerCC26XX_ENTERING_STANDBY)
{
// Power down RF Switch
PIN_setOutputValue(radCtrlHandle, Board_DIO30_SWPWR, 0);
}
else if (eventType == PowerCC26XX_AWAKE_STANDBY)
{
// Power up RF Switch
PIN_setOutputValue(radCtrlHandle, Board_DIO30_SWPWR, 1);
}
// Notification handled successfully
return Power_NOTIFYDONE;
}
#endif //CC1350_LAUNCHXL || POWER_SAVING
/*******************************************************************************
*/
@@ -9,7 +9,7 @@
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2010-2018, Texas Instruments Incorporated
All rights reserved.
@@ -50,6 +50,7 @@
*/
#include <string.h>
// clang-format off
#include "bcomdef.h"
#include "osal.h"
#include "linkdb.h"
@@ -58,61 +59,21 @@
#include "gatt_uuid.h"
#include "gattservapp.h"
#include "gapbondmgr.h"
// clang-format on
#include "simple_gatt_profile.h"
/*********************************************************************
* MACROS
*/
#define _UUID(_uuid) \
{ LO_UINT16(_uuid), HI_UINT16(_uuid) }
/*********************************************************************
* CONSTANTS
*/
CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] = _UUID(SIMPLEPROFILE_SERV_UUID); // Simple GATT Profile Service UUID: 0xFFF0
CONST uint8 simpleProfilechar1UUID[ATT_BT_UUID_SIZE] = _UUID(SIMPLEPROFILE_CHAR1_UUID); // Characteristic 1 UUID: 0xFFF1
CONST uint8 simpleProfilechar2UUID[ATT_BT_UUID_SIZE] = _UUID(SIMPLEPROFILE_CHAR2_UUID); // Characteristic 2 UUID: 0xFFF2
CONST uint8 simpleProfilechar3UUID[ATT_BT_UUID_SIZE] = _UUID(SIMPLEPROFILE_CHAR3_UUID); // Characteristic 3 UUID: 0xFFF3
CONST uint8 simpleProfilechar4UUID[ATT_BT_UUID_SIZE] = _UUID(SIMPLEPROFILE_CHAR4_UUID); // Characteristic 4 UUID: 0xFFF4
CONST uint8 simpleProfilechar5UUID[ATT_BT_UUID_SIZE] = _UUID(SIMPLEPROFILE_CHAR5_UUID); // Characteristic 5 UUID: 0xFFF5
#define SERVAPP_NUM_ATTR_SUPPORTED 17
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
// Simple GATT Profile Service UUID: 0xFFF0
CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};
// Characteristic 1 UUID: 0xFFF1
CONST uint8 simpleProfilechar1UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID)
};
// Characteristic 2 UUID: 0xFFF2
CONST uint8 simpleProfilechar2UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(SIMPLEPROFILE_CHAR2_UUID), HI_UINT16(SIMPLEPROFILE_CHAR2_UUID)
};
// Characteristic 3 UUID: 0xFFF3
CONST uint8 simpleProfilechar3UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(SIMPLEPROFILE_CHAR3_UUID), HI_UINT16(SIMPLEPROFILE_CHAR3_UUID)
};
// Characteristic 4 UUID: 0xFFF4
CONST uint8 simpleProfilechar4UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(SIMPLEPROFILE_CHAR4_UUID), HI_UINT16(SIMPLEPROFILE_CHAR4_UUID)
};
// Characteristic 5 UUID: 0xFFF5
CONST uint8 simpleProfilechar5UUID[ATT_BT_UUID_SIZE] =
{
LO_UINT16(SIMPLEPROFILE_CHAR5_UUID), HI_UINT16(SIMPLEPROFILE_CHAR5_UUID)
};
#undef _UUID
/*********************************************************************
* EXTERNAL VARIABLES
@@ -133,28 +94,19 @@ static simpleProfileCBs_t *simpleProfile_AppCBs = NULL;
*/
// Simple Profile Service attribute
static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID };
static CONST gattAttrType_t simpleProfileService = {ATT_BT_UUID_SIZE, simpleProfileServUUID};
// Simple Profile Characteristic 1 Properties
static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE;
static uint8 simpleProfileChar1Props = GATT_PROP_READ;
// Characteristic 1 Value
static uint8 simpleProfileChar1 = 0;
// Simple Profile Characteristic 1 User Description
static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1";
static uint8 simpleProfileChar1[SIMPLEPROFILE_CHAR1_LEN] = {0};
// Simple Profile Characteristic 2 Properties
static uint8 simpleProfileChar2Props = GATT_PROP_READ;
// Characteristic 2 Value
static uint8 simpleProfileChar2 = 0;
// Simple Profile Characteristic 2 User Description
static uint8 simpleProfileChar2UserDesp[17] = "Characteristic 2";
static uint8 simpleProfileChar2[SIMPLEPROFILE_CHAR2_LEN] = {0};
// Simple Profile Characteristic 3 Properties
static uint8 simpleProfileChar3Props = GATT_PROP_WRITE;
@@ -162,10 +114,6 @@ static uint8 simpleProfileChar3Props = GATT_PROP_WRITE;
// Characteristic 3 Value
static uint8 simpleProfileChar3[SIMPLEPROFILE_CHAR3_LEN] = {0};
// Simple Profile Characteristic 3 User Description
static uint8 simpleProfileChar3UserDesp[17] = "Characteristic 3";
// Simple Profile Characteristic 4 Properties
static uint8 simpleProfileChar4Props = GATT_PROP_NOTIFY;
@@ -178,174 +126,89 @@ static uint8 simpleProfileChar4[SIMPLEPROFILE_CHAR4_LEN] = {0};
// that client and writes only affect the configuration of that client.
static gattCharCfg_t *simpleProfileChar4Config;
// Simple Profile Characteristic 4 User Description
static uint8 simpleProfileChar4UserDesp[17] = "Characteristic 4";
// Simple Profile Characteristic 5 Properties
static uint8 simpleProfileChar5Props = GATT_PROP_READ;
static uint8 simpleProfileChar5Props = GATT_PROP_READ | GATT_PROP_WRITE;
// Characteristic 5 Value
static uint8 simpleProfileChar5[SIMPLEPROFILE_CHAR5_LEN] = { 0, 0, 0, 0, 0 };
// Simple Profile Characteristic 5 User Description
static uint8 simpleProfileChar5UserDesp[17] = "Characteristic 5";
static uint8 simpleProfileChar5[SIMPLEPROFILE_CHAR5_LEN] = {0};
/*********************************************************************
* Profile Attributes - Table
*/
static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
{
// Simple Profile Service
{
{ ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
GATT_PERMIT_READ, /* permissions */
0, /* handle */
(uint8 *)&simpleProfileService /* pValue */
},
#define SERVAPP_NUM_ATTR_SUPPORTED 17
static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] = {
// Simple Profile Service
{{ATT_BT_UUID_SIZE, primaryServiceUUID}, GATT_PERMIT_READ, 0, (uint8 *)&simpleProfileService},
// Characteristic 1 Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar1Props
},
{{ATT_BT_UUID_SIZE, characterUUID}, GATT_PERMIT_READ, 0, &simpleProfileChar1Props},
// Characteristic Value 1
{
{ ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
&simpleProfileChar1
},
// Characteristic Value 1
{{ATT_BT_UUID_SIZE, simpleProfilechar1UUID}, GATT_PERMIT_READ, 0, simpleProfileChar1},
// Characteristic 1 User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
simpleProfileChar1UserDesp
},
// Characteristic 1 User Description
{{ATT_BT_UUID_SIZE, charUserDescUUID}, GATT_PERMIT_READ, 0, "FS"},
// Characteristic 2 Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar2Props
},
{{ATT_BT_UUID_SIZE, characterUUID}, GATT_PERMIT_READ, 0, &simpleProfileChar2Props},
// Characteristic Value 2
{
{ ATT_BT_UUID_SIZE, simpleProfilechar2UUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar2
},
// Characteristic Value 2
{{ATT_BT_UUID_SIZE, simpleProfilechar2UUID}, GATT_PERMIT_READ, 0, simpleProfileChar2},
// Characteristic 2 User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
simpleProfileChar2UserDesp
},
// Characteristic 2 User Description
{{ATT_BT_UUID_SIZE, charUserDescUUID}, GATT_PERMIT_READ, 0, "CR"},
// Characteristic 3 Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar3Props
},
{{ATT_BT_UUID_SIZE, characterUUID}, GATT_PERMIT_READ, 0, &simpleProfileChar3Props},
// Characteristic Value 3
{
{ ATT_BT_UUID_SIZE, simpleProfilechar3UUID },
GATT_PERMIT_WRITE,
0,
simpleProfileChar3
},
// Characteristic Value 3
{{ATT_BT_UUID_SIZE, simpleProfilechar3UUID}, GATT_PERMIT_WRITE, 0, simpleProfileChar3},
// Characteristic 3 User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
simpleProfileChar3UserDesp
},
// Characteristic 3 User Description
{{ATT_BT_UUID_SIZE, charUserDescUUID}, GATT_PERMIT_READ, 0, "IS"},
// Characteristic 4 Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar4Props
},
{{ATT_BT_UUID_SIZE, characterUUID}, GATT_PERMIT_READ, 0, &simpleProfileChar4Props},
// Characteristic Value 4
{
{ ATT_BT_UUID_SIZE, simpleProfilechar4UUID },
0,
0,
simpleProfileChar4
},
// Characteristic Value 4
{{ATT_BT_UUID_SIZE, simpleProfilechar4UUID}, 0, 0, simpleProfileChar4},
// Characteristic 4 configuration
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)&simpleProfileChar4Config
},
// Characteristic 4 configuration
{{ATT_BT_UUID_SIZE, clientCharCfgUUID}, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8 *)&simpleProfileChar4Config},
// Characteristic 4 User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
simpleProfileChar4UserDesp
},
// Characteristic 4 User Description
{{ATT_BT_UUID_SIZE, charUserDescUUID}, GATT_PERMIT_READ, 0, "Nt"},
// Characteristic 5 Declaration
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar5Props
},
{{ATT_BT_UUID_SIZE, characterUUID}, GATT_PERMIT_READ, 0, &simpleProfileChar5Props},
// Characteristic Value 5
{
{ ATT_BT_UUID_SIZE, simpleProfilechar5UUID },
GATT_PERMIT_AUTHEN_READ,
0,
simpleProfileChar5
},
// Characteristic Value 5
{{ATT_BT_UUID_SIZE, simpleProfilechar5UUID}, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, simpleProfileChar5},
// GATT_PERMIT_AUTHEN_READ,
// Characteristic 5 User Description
{
{ ATT_BT_UUID_SIZE, charUserDescUUID },
GATT_PERMIT_READ,
0,
simpleProfileChar5UserDesp
},
// Characteristic 5 User Description
{{ATT_BT_UUID_SIZE, charUserDescUUID}, GATT_PERMIT_READ, 0, "Dg"},
};
/*********************************************************************
* LOCAL FUNCTIONS
*/
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, //
gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen,
uint16_t offset, uint16_t maxLen,
uint8_t method);
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
uint8_t * pValue,
uint16_t * pLen,
uint16_t offset,
uint16_t maxLen,
uint8_t method);
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, //
gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t len,
uint16_t offset, uint8_t method);
uint8_t * pValue,
uint16_t len,
uint16_t offset,
uint8_t method);
/*********************************************************************
* PROFILE CALLBACKS
@@ -359,11 +222,10 @@ static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
// pfnAuthorizeAttrCB to check a client's authorization prior to calling
// pfnReadAttrCB or pfnWriteAttrCB, so no checks for authorization need to be
// made within these functions.
CONST gattServiceCBs_t simpleProfileCBs =
{
simpleProfile_ReadAttrCB, // Read callback function pointer
simpleProfile_WriteAttrCB, // Write callback function pointer
NULL // Authorization callback function pointer
CONST gattServiceCBs_t simpleProfileCBs = {
simpleProfile_ReadAttrCB, // Read callback function pointer
simpleProfile_WriteAttrCB, // Write callback function pointer
NULL // Authorization callback function pointer
};
/*********************************************************************
@@ -381,35 +243,29 @@ CONST gattServiceCBs_t simpleProfileCBs =
*
* @return Success or Failure
*/
bStatus_t SimpleProfile_AddService( uint32 services )
{
uint8 status;
bStatus_t SimpleProfile_AddService(uint32 services) {
uint8 status;
// Allocate Client Characteristic Configuration table
simpleProfileChar4Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
linkDBNumConns );
if ( simpleProfileChar4Config == NULL )
{
return ( bleMemAllocError );
}
// Allocate Client Characteristic Configuration table
simpleProfileChar4Config = (gattCharCfg_t *)ICall_malloc(sizeof(gattCharCfg_t) * linkDBNumConns);
if (simpleProfileChar4Config == NULL) {
return (bleMemAllocError);
}
// Initialize Client Characteristic Configuration attributes
GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar4Config );
// Initialize Client Characteristic Configuration attributes
GATTServApp_InitCharCfg(INVALID_CONNHANDLE, simpleProfileChar4Config);
if ( services & SIMPLEPROFILE_SERVICE )
{
// Register GATT attribute list and CBs with GATT Server App
status = GATTServApp_RegisterService( simpleProfileAttrTbl,
GATT_NUM_ATTRS( simpleProfileAttrTbl ),
GATT_MAX_ENCRYPT_KEY_SIZE,
&simpleProfileCBs );
}
else
{
status = SUCCESS;
}
if (services & SIMPLEPROFILE_SERVICE) {
// Register GATT attribute list and CBs with GATT Server App
status = GATTServApp_RegisterService(simpleProfileAttrTbl, //
GATT_NUM_ATTRS(simpleProfileAttrTbl),
GATT_MAX_ENCRYPT_KEY_SIZE,
&simpleProfileCBs);
} else {
status = SUCCESS;
}
return ( status );
return (status);
}
/*********************************************************************
@@ -422,18 +278,14 @@ bStatus_t SimpleProfile_AddService( uint32 services )
*
* @return SUCCESS or bleAlreadyInRequestedMode
*/
bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks )
{
if ( appCallbacks )
{
simpleProfile_AppCBs = appCallbacks;
bStatus_t SimpleProfile_RegisterAppCBs(simpleProfileCBs_t *appCallbacks) {
if (appCallbacks) {
simpleProfile_AppCBs = appCallbacks;
return ( SUCCESS );
}
else
{
return ( bleAlreadyInRequestedMode );
}
return (SUCCESS);
} else {
return (bleAlreadyInRequestedMode);
}
}
/*********************************************************************
@@ -450,77 +302,57 @@ bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks )
*
* @return bStatus_t
*/
bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )
{
bStatus_t ret = SUCCESS;
switch ( param )
{
bStatus_t SimpleProfile_SetParameter(uint8 param, uint8 len, void *value) {
switch (param) {
case SIMPLEPROFILE_CHAR1:
if ( len == sizeof ( uint8 ) )
{
simpleProfileChar1 = *((uint8*)value);
}
else
{
ret = bleInvalidRange;
}
break;
if (len <= SIMPLEPROFILE_CHAR1_LEN) {
memcpy(simpleProfileChar1, value, len);
} else {
return bleInvalidRange;
}
case SIMPLEPROFILE_CHAR2:
if ( len == sizeof ( uint8 ) )
{
simpleProfileChar2 = *((uint8*)value);
}
else
{
ret = bleInvalidRange;
}
break;
if (len <= SIMPLEPROFILE_CHAR2_LEN) {
memcpy(simpleProfileChar2, value, len);
} else {
return bleInvalidRange;
}
case SIMPLEPROFILE_CHAR3:
if ( len <= SIMPLEPROFILE_CHAR3_LEN )
{
memcpy(simpleProfileChar3,value,len);
}
else
{
ret = bleInvalidRange;
}
break;
if (len <= SIMPLEPROFILE_CHAR3_LEN) {
memcpy(simpleProfileChar3, value, len);
} else {
return bleInvalidRange;
}
case SIMPLEPROFILE_CHAR4:
if ( len <= SIMPLEPROFILE_CHAR4_LEN )
{
memcpy( simpleProfileChar4, value, len);
if (len <= SIMPLEPROFILE_CHAR4_LEN) {
memcpy(simpleProfileChar4, value, len);
// See if Notification has been enabled
GATTServApp_ProcessCharCfg( simpleProfileChar4Config, simpleProfileChar4, FALSE,
simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
INVALID_TASK_ID, simpleProfile_ReadAttrCB );
}
else
{
ret = bleInvalidRange;
}
break;
// See if Notification has been enabled
GATTServApp_ProcessCharCfg(simpleProfileChar4Config, //
simpleProfileChar4,
FALSE,
simpleProfileAttrTbl,
GATT_NUM_ATTRS(simpleProfileAttrTbl),
INVALID_TASK_ID,
simpleProfile_ReadAttrCB);
} else {
return bleInvalidRange;
}
case SIMPLEPROFILE_CHAR5:
if ( len == SIMPLEPROFILE_CHAR5_LEN )
{
VOID memcpy( simpleProfileChar5, value, SIMPLEPROFILE_CHAR5_LEN );
}
else
{
ret = bleInvalidRange;
}
break;
if (len <= SIMPLEPROFILE_CHAR5_LEN) {
memcpy(simpleProfileChar5, value, len);
} else {
return bleInvalidRange;
}
default:
ret = INVALIDPARAMETER;
break;
}
return INVALIDPARAMETER;
}
return ( ret );
return SUCCESS;
}
/*********************************************************************
@@ -536,37 +368,33 @@ bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )
*
* @return bStatus_t
*/
bStatus_t SimpleProfile_GetParameter( uint8 param, void *value )
{
bStatus_t ret = SUCCESS;
switch ( param )
{
bStatus_t SimpleProfile_GetParameter(uint8 param, void *value) {
switch (param) {
case SIMPLEPROFILE_CHAR1:
*((uint8*)value) = simpleProfileChar1;
break;
memcpy(value, simpleProfileChar1, SIMPLEPROFILE_CHAR1_LEN);
break;
case SIMPLEPROFILE_CHAR2:
*((uint8*)value) = simpleProfileChar2;
break;
memcpy(value, simpleProfileChar2, SIMPLEPROFILE_CHAR2_LEN);
break;
case SIMPLEPROFILE_CHAR3:
memcpy( value, simpleProfileChar3, SIMPLEPROFILE_CHAR3_LEN );
break;
memcpy(value, simpleProfileChar3, SIMPLEPROFILE_CHAR3_LEN);
break;
case SIMPLEPROFILE_CHAR4:
memcpy( value, simpleProfileChar4, SIMPLEPROFILE_CHAR4_LEN );
break;
memcpy(value, simpleProfileChar4, SIMPLEPROFILE_CHAR4_LEN);
break;
case SIMPLEPROFILE_CHAR5:
VOID memcpy( value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN );
break;
memcpy(value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN);
break;
default:
ret = INVALIDPARAMETER;
break;
}
return INVALIDPARAMETER;
}
return ( ret );
return SUCCESS;
}
/*********************************************************************
@@ -584,65 +412,57 @@ bStatus_t SimpleProfile_GetParameter( uint8 param, void *value )
*
* @return SUCCESS, blePending or Failure
*/
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, //
gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t *pLen,
uint16_t offset, uint16_t maxLen,
uint8_t method)
{
bStatus_t status = SUCCESS;
uint8_t * pValue,
uint16_t * pLen,
uint16_t offset,
uint16_t maxLen,
uint8_t method) {
bStatus_t status = SUCCESS;
// Make sure it's not a blob operation (no attributes in the profile are long)
if ( offset > 0 )
{
return ( ATT_ERR_ATTR_NOT_LONG );
}
if ( pAttr->type.len == ATT_BT_UUID_SIZE )
{
// 16-bit UUID
uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
switch ( uuid )
{
// No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
// gattserverapp handles those reads
// characteristics 1 and 2 have read permissions
// characteritisc 3 does not have read permissions; therefore it is not
// included here
// characteristic 4 does not have read permissions, but because it
// can be sent as a notification, it is included here
case SIMPLEPROFILE_CHAR1_UUID:
case SIMPLEPROFILE_CHAR2_UUID:
*pLen = 1;
pValue[0] = *pAttr->pValue;
break;
case SIMPLEPROFILE_CHAR4_UUID:
*pLen = SIMPLEPROFILE_CHAR4_LEN;
VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR4_LEN );
break;
case SIMPLEPROFILE_CHAR5_UUID:
*pLen = SIMPLEPROFILE_CHAR5_LEN;
VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR5_LEN );
break;
default:
// Should never get here! (characteristics 3 and 4 do not have read permissions)
*pLen = 0;
status = ATT_ERR_ATTR_NOT_FOUND;
break;
// Make sure it's not a blob operation (no attributes in the profile are long)
if (offset > 0) {
return (ATT_ERR_ATTR_NOT_LONG);
}
}
else
{
// 128-bit UUID
*pLen = 0;
status = ATT_ERR_INVALID_HANDLE;
}
return ( status );
if (pAttr->type.len == ATT_BT_UUID_SIZE) {
// 16-bit UUID
uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
switch (uuid) {
case SIMPLEPROFILE_CHAR1_UUID:
*pLen = SIMPLEPROFILE_CHAR1_LEN;
memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR1_LEN);
break;
case SIMPLEPROFILE_CHAR2_UUID:
*pLen = SIMPLEPROFILE_CHAR2_LEN;
memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR2_LEN);
break;
case SIMPLEPROFILE_CHAR4_UUID:
*pLen = SIMPLEPROFILE_CHAR4_LEN;
memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR4_LEN);
break;
case SIMPLEPROFILE_CHAR5_UUID:
*pLen = SIMPLEPROFILE_CHAR5_LEN;
memcpy(pValue, pAttr->pValue, SIMPLEPROFILE_CHAR5_LEN);
break;
default:
// Should never get here! (characteristics 3 and 4 do not have read permissions)
*pLen = 0;
status = ATT_ERR_ATTR_NOT_FOUND;
break;
}
} else {
// 128-bit UUID
*pLen = 0;
status = ATT_ERR_INVALID_HANDLE;
}
return (status);
}
/*********************************************************************
@@ -659,99 +479,85 @@ static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
*
* @return SUCCESS, blePending or Failure
*/
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, //
gattAttribute_t *pAttr,
uint8_t *pValue, uint16_t len,
uint16_t offset, uint8_t method)
{
bStatus_t status = SUCCESS;
uint8 notifyApp = 0xFF;
uint8_t * pValue,
uint16_t len,
uint16_t offset,
uint8_t method) {
bStatus_t status = SUCCESS;
uint8 notifyApp = 0xFF;
if ( pAttr->type.len == ATT_BT_UUID_SIZE )
{
// 16-bit UUID
uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
switch ( uuid )
{
case SIMPLEPROFILE_CHAR1_UUID:
if (pAttr->type.len == ATT_BT_UUID_SIZE) {
// 16-bit UUID
uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
//Validate the value
// Make sure it's not a blob oper
if ( offset == 0 )
{
if ( len != 1 )
{
status = ATT_ERR_INVALID_VALUE_SIZE;
}
}
else
{
status = ATT_ERR_ATTR_NOT_LONG;
}
switch (uuid) {
case SIMPLEPROFILE_CHAR3_UUID:
//Write the value
if ( status == SUCCESS )
{
uint8 *pCurValue = (uint8 *)pAttr->pValue;
*pCurValue = pValue[0];
if( pAttr->pValue == &simpleProfileChar1 )
{
notifyApp = SIMPLEPROFILE_CHAR1;
}
}
break;
case SIMPLEPROFILE_CHAR3_UUID:
if ( offset == 0 )
{
if ( len > SIMPLEPROFILE_CHAR3_LEN )
{
status = ATT_ERR_INVALID_VALUE_SIZE;
// Validate the value
// Make sure it's not a blob oper
if (offset == 0) {
if (len >= SIMPLEPROFILE_CHAR3_LEN) {
status = ATT_ERR_INVALID_VALUE_SIZE;
}
} else {
status = ATT_ERR_ATTR_NOT_LONG;
}
}
else
{
status = ATT_ERR_ATTR_NOT_LONG;
}
//Write the value
if ( status == SUCCESS )
{
// Copy pValue into the variable we point to from the attribute table.
memcpy(pAttr->pValue + offset, pValue, len);
// Write the value
if (status == SUCCESS) {
// Copy pValue into the variable we point to from the attribute table.
memcpy(pAttr->pValue + offset, pValue, len);
memset(pAttr->pValue + len, 0, SIMPLEPROFILE_CHAR3_LEN - len);
if( pAttr->pValue == simpleProfileChar3 )
{
notifyApp = SIMPLEPROFILE_CHAR3;
if (pAttr->pValue == simpleProfileChar3) {
notifyApp = SIMPLEPROFILE_CHAR3;
}
}
}
break;
case GATT_CLIENT_CHAR_CFG_UUID:
status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
offset, GATT_CLIENT_CFG_NOTIFY );
break;
break;
case SIMPLEPROFILE_CHAR5_UUID:
if (offset == 0) {
if (len >= SIMPLEPROFILE_CHAR5_LEN) {
status = ATT_ERR_INVALID_VALUE_SIZE;
}
} else {
status = ATT_ERR_ATTR_NOT_LONG;
}
default:
// Should never get here! (characteristics 2 and 4 do not have write permissions)
status = ATT_ERR_ATTR_NOT_FOUND;
break;
// Write the value
if (status == SUCCESS) {
// Copy pValue into the variable we point to from the attribute table.
memcpy(pAttr->pValue + offset, pValue, len);
memset(pAttr->pValue + len, 0, SIMPLEPROFILE_CHAR5_LEN - len);
if (pAttr->pValue == simpleProfileChar5) {
notifyApp = SIMPLEPROFILE_CHAR5;
}
}
break;
case GATT_CLIENT_CHAR_CFG_UUID:
status = GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY);
break;
default:
// Should never get here! (characteristics 2 and 4 do not have write permissions)
status = ATT_ERR_ATTR_NOT_FOUND;
break;
}
} else {
// 128-bit UUID
status = ATT_ERR_INVALID_HANDLE;
}
}
else
{
// 128-bit UUID
status = ATT_ERR_INVALID_HANDLE;
}
// If a characteristic value changed then callback function to notify application of change
if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
{
simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );
}
// If a characteristic value changed then callback function to notify application of change
if ((notifyApp != 0xFF) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange) {
simpleProfile_AppCBs->pfnSimpleProfileChange(notifyApp);
}
return ( status );
return (status);
}
/*********************************************************************
@@ -9,7 +9,7 @@
Target Device: CC2650, CC2640
******************************************************************************
Copyright (c) 2010-2018, Texas Instruments Incorporated
All rights reserved.
@@ -49,8 +49,7 @@
#define SIMPLEGATTPROFILE_H
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
/*********************************************************************
@@ -62,37 +61,36 @@ extern "C"
*/
// Profile Parameters
#define SIMPLEPROFILE_CHAR1 0 // RW uint8 - Profile Characteristic 1 value
#define SIMPLEPROFILE_CHAR2 1 // RW uint8 - Profile Characteristic 2 value
#define SIMPLEPROFILE_CHAR3 2 // RW uint8 - Profile Characteristic 3 value
#define SIMPLEPROFILE_CHAR4 3 // RW uint8 - Profile Characteristic 4 value
#define SIMPLEPROFILE_CHAR5 4 // RW uint8 - Profile Characteristic 4 value
#define SIMPLEPROFILE_CHAR1 0 // RW uint8 - Profile Characteristic 1 value
#define SIMPLEPROFILE_CHAR2 1 // RW uint8 - Profile Characteristic 2 value
#define SIMPLEPROFILE_CHAR3 2 // RW uint8 - Profile Characteristic 3 value
#define SIMPLEPROFILE_CHAR4 3 // RW uint8 - Profile Characteristic 4 value
#define SIMPLEPROFILE_CHAR5 4 // RW uint8 - Profile Characteristic 4 value
// Simple Profile Service UUID
#define SIMPLEPROFILE_SERV_UUID 0xFFF0
#define SIMPLEPROFILE_SERV_UUID 0xFFF0
// Key Pressed UUID
#define SIMPLEPROFILE_CHAR1_UUID 0xFFF1
#define SIMPLEPROFILE_CHAR2_UUID 0xFFF2
#define SIMPLEPROFILE_CHAR3_UUID 0xFFF3
#define SIMPLEPROFILE_CHAR4_UUID 0xFFF4
#define SIMPLEPROFILE_CHAR5_UUID 0xFFF5
#define SIMPLEPROFILE_CHAR1_UUID 0xFFF1
#define SIMPLEPROFILE_CHAR2_UUID 0xFFF2
#define SIMPLEPROFILE_CHAR3_UUID 0xFFF3
#define SIMPLEPROFILE_CHAR4_UUID 0xFFF4
#define SIMPLEPROFILE_CHAR5_UUID 0xFFF5
// Simple Keys Profile Services bit fields
#define SIMPLEPROFILE_SERVICE 0x00000001
#define SIMPLEPROFILE_SERVICE 0x00000001
// Length of Characteristic 5 in bytes
#define SIMPLEPROFILE_CHAR5_LEN 5
#define SIMPLEPROFILE_CHAR4_LEN 8
#define SIMPLEPROFILE_CHAR3_LEN 8
#define SIMPLEPROFILE_CHAR1_LEN 2
#define SIMPLEPROFILE_CHAR2_LEN 10
#define SIMPLEPROFILE_CHAR3_LEN 20
#define SIMPLEPROFILE_CHAR4_LEN 20
#define SIMPLEPROFILE_CHAR5_LEN 5
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* MACROS
*/
@@ -102,20 +100,16 @@ extern "C"
*/
// Callback when a characteristic value has changed
typedef void (*simpleProfileChange_t)( uint8 paramID );
typedef void (*simpleProfileChange_t)(uint8 paramID);
typedef struct
{
simpleProfileChange_t pfnSimpleProfileChange; // Called when characteristic value changes
typedef struct {
simpleProfileChange_t pfnSimpleProfileChange; // Called when characteristic value changes
} simpleProfileCBs_t;
/*********************************************************************
* API FUNCTIONS
*/
/*
* SimpleProfile_AddService- Initializes the Simple GATT Profile service by registering
* GATT attributes with the GATT server.
@@ -124,7 +118,7 @@ typedef struct
* contain more than one service.
*/
extern bStatus_t SimpleProfile_AddService( uint32 services );
extern bStatus_t SimpleProfile_AddService(uint32 services);
/*
* SimpleProfile_RegisterAppCBs - Registers the application callback function.
@@ -132,7 +126,7 @@ extern bStatus_t SimpleProfile_AddService( uint32 services );
*
* appCallbacks - pointer to application callbacks.
*/
extern bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks );
extern bStatus_t SimpleProfile_RegisterAppCBs(simpleProfileCBs_t *appCallbacks);
/*
* SimpleProfile_SetParameter - Set a Simple GATT Profile parameter.
@@ -144,7 +138,7 @@ extern bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks
* data type (example: data type of uint16 will be cast to
* uint16 pointer).
*/
extern bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value );
extern bStatus_t SimpleProfile_SetParameter(uint8 param, uint8 len, void *value);
/*
* SimpleProfile_GetParameter - Get a Simple GATT Profile parameter.
@@ -155,8 +149,7 @@ extern bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value
* data type (example: data type of uint16 will be cast to
* uint16 pointer).
*/
extern bStatus_t SimpleProfile_GetParameter( uint8 param, void *value );
extern bStatus_t SimpleProfile_GetParameter(uint8 param, void *value);
/*********************************************************************
*********************************************************************/