Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f5018b5c37 | |||
| 2a17781fde | |||
| 67d52bcd75 | |||
| b96505d79c | |||
| 7083101d79 | |||
| ee70b207ca | |||
| 314bb70489 | |||
| 459f4850ef | |||
| dbc2e3a568 | |||
| 1f4cee9279 | |||
| f18f05cd1d | |||
| 93816a8d36 | |||
| 18a8fde7de | |||
| 7742ab0c9c | |||
| 1d1e08771d | |||
| 916e27ba33 | |||
| 598c3e2629 | |||
| ca39a15e60 | |||
| 2c992d8526 | |||
| 127742b194 | |||
| dff979cbe6 | |||
| 3b13a0ff90 | |||
| 1e061f2511 | |||
| cc2648585c | |||
| b965f81fc4 | |||
| b5ddf300b9 | |||
| 22175f379f | |||
| 6ff966df58 | |||
| 65f159fad2 | |||
| 515fc57307 | |||
| b84fbb6044 | |||
| d1cdaf7041 | |||
| d824b1fbd9 | |||
| 0df352d6ff | |||
| c27b6a0ac7 | |||
| e1152f6713 | |||
| e6ab11b004 | |||
| e3e40d25e9 | |||
| 495d4deb91 | |||
| aa662f4a7b | |||
| 21f17ab7a3 | |||
| 6000816833 | |||
| 95116252c8 | |||
| 28e8a66221 | |||
| 3249e7e1e2 | |||
| d5d97db086 | |||
| c806a7e09f | |||
| 95e563e04f | |||
| 747ebf5f8b | |||
| fb942c8e40 | |||
| fdc2f05d46 | |||
| 3c2823cc13 | |||
| 9ba9131a51 | |||
| bd64c60b40 | |||
| bb7e609665 | |||
| 9c4794c868 | |||
| 019c32faf5 | |||
| 96b6e4d1b9 | |||
| 105d01e636 | |||
| 71fcc98862 | |||
| c63656ac97 | |||
| 47a24ccef3 | |||
| 2ee3abf193 | |||
| d9039070ad | |||
| f69fd4a40f | |||
| a6287ad7e3 |
+4
-1
@@ -5,4 +5,7 @@ xdctools_*/
|
||||
ccsv8/
|
||||
|
||||
# CSS build files
|
||||
FlashROM/
|
||||
FlashROM/
|
||||
|
||||
# python cache
|
||||
__pycache__/
|
||||
Generated
+3
@@ -0,0 +1,3 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<scope name="Driver" pattern="file[BioProCC2650]:simplelink/ble_sdk_2_02_02_25/src/boards/BOOSTXL_CC2650MA/*||file[BioProCC2650]:simplelink/ble_sdk_2_02_02_25/src/boards/CC2650_LAUNCHXL/*||file[BioProCC2650]:tirtos_cc13xx_cc26xx_2_21_01_08/products/tidrivers_cc13xx_cc26xx_2_21_01_01/packages/ti/drivers//*" />
|
||||
</component>
|
||||
Binary file not shown.
@@ -13,27 +13,43 @@ BioPro Device
|
||||
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/main.c`
|
||||
|
||||
|
||||
### Current project
|
||||
### Current project and state
|
||||
|
||||
1. Elite
|
||||
|
||||
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_tni.h`
|
||||
|
||||
**branch**
|
||||
|
||||
2. Neulive 1.2
|
||||
|
||||
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_uni.h`
|
||||
|
||||
**branch**
|
||||
|
||||
`neulive1.2/*`
|
||||
|
||||
3. Neulive 1.3
|
||||
|
||||
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_neulive.h`
|
||||
|
||||
**branch**
|
||||
|
||||
4. EliteZM
|
||||
|
||||
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_zm.h`
|
||||
|
||||
**branch**
|
||||
|
||||
`elite_zm/*`
|
||||
|
||||
5. NeuliveSTI
|
||||
|
||||
`simplelink/ble_sdk_2_02_02_25/src/examples/simple_peripheral/cc26xx/app/headstage/headstage_sti.h`
|
||||
|
||||
**branch**
|
||||
|
||||
`neuliveSTI/*`
|
||||
|
||||
### Notable source code
|
||||
|
||||
@@ -58,6 +74,194 @@ major source code path:
|
||||
|
||||
`simplelink/ble_sdk_2_02_02_25/src/examples/host_test/cc26xx/app/main.c`
|
||||
|
||||
**branch**
|
||||
|
||||
`host_test/master`
|
||||
|
||||
`release/host_test-*`
|
||||
|
||||
-----------------------------------------------
|
||||
|
||||
How to install this project in your PC
|
||||
--------------------------------------
|
||||
|
||||
|
||||
### install CCStudio
|
||||
|
||||
#### Prerequisite:
|
||||
|
||||
anti-virus software might cause some problems, disable it while installing is recommended.
|
||||
|
||||
#### Install CCS (Online install)
|
||||
|
||||
1. [code composer studio](http://processors.wiki.ti.com/index.php/Download_CCS) :
|
||||
choose the latest version (we use 8.2.0.00007, Online Installer, as example) of Code Composer Studio.
|
||||
|
||||
2. run installer
|
||||
|
||||
3. accept the license
|
||||
|
||||
4. install at folder `c:/ti`
|
||||
|
||||
5. select all Processor Support
|
||||
|
||||
6. select all Debug Probes.
|
||||
|
||||
7. Finish. Allow the network access if the firewall jumps a warning dialog.
|
||||
Wait for the install process......
|
||||
|
||||
|
||||
#### Offline install
|
||||
|
||||
1. [code composer studio](http://processors.wiki.ti.com/index.php/Download_CCS) :
|
||||
choose the latest version (we use 8.2.0.00007, Offline Installer) of Code Composer Studio.
|
||||
|
||||
2. Unzip it
|
||||
|
||||
3. Open the folder `CCS8.2.0.00007_win32` -> Open sub-folder `CCS8.2.0.00007_win32`
|
||||
|
||||
4. run installer *ccs_setup_8.2.0.00007*
|
||||
|
||||
5. accept the license
|
||||
|
||||
6. install at folder `c:/ti`
|
||||
|
||||
7. select all Processor Support
|
||||
|
||||
8. select all Debug Probes
|
||||
|
||||
9. Finish. Wait for the install process......
|
||||
|
||||
10. accept `Blackhawk Control` dialog popped out during the process
|
||||
(we will not use this directly)
|
||||
|
||||
11. select options to create desktop shortcut and launch CCStudio
|
||||
|
||||
#### After install, update the CCStudio
|
||||
|
||||
1. at the first launch, CCStudio will ask you to select a directory as workspace. Use the default. -> Launch
|
||||
|
||||
2. help -> check for updates -> select all available updates -> next
|
||||
|
||||
3. accept the licenses -> finish -> wait for the installation...... -> Restart Now
|
||||
|
||||
|
||||
|
||||
### install BLE STACK
|
||||
|
||||
1. [BLE STACK](http://www.ti.com/tool/BLE-STACK):
|
||||
choose `BLE-STACK-2-2-2` Free version.
|
||||
(a TI account is required)
|
||||
|
||||
1. at the *U.S. Government export approval* page,
|
||||
check all your information and submit then start to download.
|
||||
|
||||
2. run *ble_sdk_2_02_02_25_setup*
|
||||
|
||||
3. accept the license agreement
|
||||
|
||||
4. use the default installation directory `C:\ti\simplelink` -> wait for the install process......
|
||||
|
||||
5. **TI-RTOS for CC13xx and CC26xx Wireless MCUs Setup Wizard** will jump out -> next
|
||||
at the same time, *ble_sdk_2_02_02_25_setup* will still be running, don't close the window
|
||||
|
||||
6. accept the license agreement
|
||||
|
||||
7. use the default installation directory `C:/ti` -> wait for the install process......
|
||||
|
||||
|
||||
8. after **TI-RTOS for CC13xx and CC26xx Wireless MCUs Setup Wizard** has been install.
|
||||
keep waiting for *ble_sdk_2_02_02_25_setup* to process
|
||||
|
||||
9. finish
|
||||
|
||||
|
||||
### First run CCStudio and setting
|
||||
|
||||
1. start CCStudio
|
||||
|
||||
2. File -> import -> C/C++ -> CCS Projects -> next
|
||||
|
||||
3. Select search-directory `C:/ti/ble_sdk_2_02_02_25/examples/cc2650lp/simple_peripheral/ccs` -> OK
|
||||
|
||||
4. select all discovered projects -> finish
|
||||
|
||||
5. right click `simple_peripheral_cc2650lp_app` -> Properties -> Products -> **XDCtools version: 3.32.2.25_core**
|
||||
|
||||
6. remember to select **TI-RTOS for CC13xx and CC26xx: 2.21.1.08** and **Other Repositories: C:/to/ccsv8/ccs_base**
|
||||
|
||||
7. Project -> Tool-chain: **Compiler version: TI v18.1.3.LTS**
|
||||
|
||||
8. apply amd close
|
||||
|
||||
9. right click *simple_peripheral_cc2650lp_stack* -> Properties -> Products -> select all
|
||||
|
||||
10. Project -> Tool-chain: **compiler version: TI v18.1.3.LTS**
|
||||
|
||||
11. Click *build* and it's done
|
||||
|
||||
### clone this project
|
||||
|
||||
#### with Command line interface (git-bash)
|
||||
|
||||
1. `cd c:`
|
||||
|
||||
2. rename ti directory
|
||||
|
||||
`mv ti ti_backup`
|
||||
|
||||
3. clone our project.
|
||||
|
||||
`git clone URL ti`, where URL is our project url on gitlab.
|
||||
|
||||
4. move CCStudio back to ti directory
|
||||
|
||||
`mv -t ti ti_backup/ccsv8 ti_backup/xdctools-*`
|
||||
|
||||
5. open CCStudio and rebuild your project, check it work as normal.
|
||||
|
||||
### Optional
|
||||
|
||||
#### install git if you don't install it
|
||||
|
||||
* https://git-scm.com/download/win
|
||||
|
||||
* choose corresponding version for your computer from 'Git for Windows Setup'
|
||||
|
||||
|
||||
#### doxygen: tool to help documenting code
|
||||
|
||||
* download from main page http://www.doxygen.nl/download.html
|
||||
|
||||
* according to different OS, download corresponding version.
|
||||
|
||||
* press keyboard 'ctrl' + 'shift' + 'a' to search external tool, select 'external tools-setting'
|
||||
|
||||
* add external tool by pressing '+'
|
||||
|
||||
* name this external tool in the column 'name'
|
||||
|
||||
* set the path of doxygen execute file in the column 'program'
|
||||
|
||||
* set the repository we want to generate document automatically in the column 'working directory'
|
||||
|
||||
* set hotkey of doxygen to run : 'File' -> 'Setting' -> 'Keymap' -> 'external tools'
|
||||
|
||||
* press the hotkey to run doxygen
|
||||
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
* jump a dialog with **MSVC components failed to install.
|
||||
Please install executables manually from c:/ti/ccsv8/installers before using CCS**
|
||||
|
||||
ignore it.
|
||||
|
||||
* jumps a warning dialog of Windows Defender
|
||||
Allow the network access.
|
||||
|
||||
|
||||
|
||||
-----------------------------------------------
|
||||
|
||||
Copyright (c) 2019. BioPro. Scientific.
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
from devlib.util import print_instruction
|
||||
|
||||
STI_INSTRUCTION = {
|
||||
'GLOBAL': '3b001#header#;1b0;12bCURRENT',
|
||||
'LOCAL': '3b010#header;1b0;4b>CHANNEL;3b>STI_MODE;1b>PRECISION;12b>STI_FREQ;10b>STI_PW;10b>STI_PW_IPI;10b>STI_NUM'
|
||||
}
|
||||
|
||||
STI_PARAMETER = {
|
||||
'CURRENT': 10,
|
||||
'CHANNEL': 0,
|
||||
'STI_MODE': 3,
|
||||
'PRECISION': 0,
|
||||
'STI_FREQ': 10,
|
||||
'STI_PW': 10,
|
||||
'STI_PW_IPI': 10,
|
||||
'STI_NUM': 10,
|
||||
}
|
||||
|
||||
NEULIVE_INSTRUCTION = {
|
||||
'RIS': '3b101#header#;2b0;3b>LB;2b0;1bCH;1bFS;3b>WF;5b>TV;4b>PM;4b>NM;4b>SR',
|
||||
'UMC': '3b001#umc_parameter;3b>AG;4b>PW;6b>TT;2b>SB;6b>TF;1bCA;1bCB;1bCC;1bCD;4b>CHA;4b>CHB;4b>CHC;4b>CHD'
|
||||
}
|
||||
|
||||
NEULIVE_PARAMETER = {
|
||||
'LB': 0, # LOW BAND FREQEUNCY
|
||||
'CH': 0, # CHOPPER
|
||||
'FS': 0, # FAST SETTLE
|
||||
'WF': 1, # WAVEFORM : POS, NEG, P2N...etc.
|
||||
'TV': 0, # STIMULATION VOLTAGE
|
||||
'PM': 0, # P CHANNEL SELECT
|
||||
'NM': 0, # N CHANNEL SELECT
|
||||
'SR': 0, # ADC SAMPLING RATE
|
||||
'AG': 5, # AMP GAIN
|
||||
'PW': 0, # PULSE WIDTH
|
||||
'TT': 9, # STIMULATION TIMES
|
||||
'SB': 3, # STIMULATION BEHAVIOR
|
||||
'TF': 10, # STIMULATION FREQUENCY
|
||||
'CA': 1, # AMP CHANNEL A ENABLE
|
||||
'CB': 0, # AMP CHANNEL B ENABLE
|
||||
'CC': 0, # AMP CHANNEL C ENABLE
|
||||
'CD': 0, # AMP CHANNEL D ENABLE
|
||||
'CHA': 0, # AMP CHANNEL A
|
||||
'CHB': 1, # AMP CHANNEL B
|
||||
'CHC': 2, # AMP CHANNEL C
|
||||
'CHD': 3, # AMP CHANNEL D
|
||||
}
|
||||
|
||||
|
||||
print_instruction(NEULIVE_INSTRUCTION['RIS'],NEULIVE_PARAMETER)
|
||||
print_instruction(NEULIVE_INSTRUCTION['UMC'],NEULIVE_PARAMETER)
|
||||
@@ -121,6 +121,75 @@ def append_buffer(buffer: List[int], shift: int, width: int, value: int, little_
|
||||
return (shift + width) % 8
|
||||
|
||||
|
||||
class DeviceInstruction:
|
||||
"""
|
||||
**Instruction Send**
|
||||
|
||||
raw byte data format. ::
|
||||
|
||||
| 0 | 1 | 2 | 3 |
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
|
||||
-----------------------------------------------------------------
|
||||
| RIS | ID | | LEN | ............................. real instruction send
|
||||
| VIS | ID | OPER | LEN | ............................. virtual instruction send
|
||||
| CIS | ID | OPER | LEN | ............................. command instruction send
|
||||
|
||||
ID
|
||||
chip ID
|
||||
|
||||
RIS
|
||||
header for real instruction type. (header=3)
|
||||
|
||||
VIS
|
||||
header for virtual instruction type. (header=C)
|
||||
|
||||
CIS
|
||||
header for command instruction type. (header=7)
|
||||
|
||||
OPER
|
||||
operator/command
|
||||
|
||||
LEN, length
|
||||
command/data length in bytes
|
||||
"""
|
||||
|
||||
TYP_RIS = 0x30
|
||||
"""header for real instruction type.
|
||||
It is real instruction send to the chip which contain the chip configuration parameter.
|
||||
"""
|
||||
|
||||
TYP_VIS = 0xC0
|
||||
"""header for virtual instruction type.
|
||||
It is virtual instruction send to the controller chip to control the chip.
|
||||
"""
|
||||
|
||||
TYP_CIS = 0x70
|
||||
"""header for command instruction type.
|
||||
It is command send to the controller chip for the special purpose.
|
||||
"""
|
||||
|
||||
VIS_RST = 0xF0
|
||||
"""reset virtual instruction"""
|
||||
|
||||
VIS_ASK = 0x30
|
||||
"""ask in virtual instruction"""
|
||||
|
||||
VIS_STI = 0xC0
|
||||
"""stimulation on virtual instruction"""
|
||||
|
||||
VIS_FUH = 0x90
|
||||
"""flush virtual instruction"""
|
||||
|
||||
VIS_INT = 0x60
|
||||
"""interrupt virtual instruction"""
|
||||
|
||||
VIS_CAL = 0xA0
|
||||
"""device calling"""
|
||||
|
||||
CIS_VOLT = 0x10
|
||||
"""get device battery voltage level"""
|
||||
|
||||
|
||||
class InstructionContentWidth:
|
||||
"""instruction width.
|
||||
|
||||
@@ -558,25 +627,48 @@ def parse_instruction(expr: str) -> InstructionContent:
|
||||
return ins_type(width, expr, **ins_argv, comment=comment)
|
||||
|
||||
|
||||
def eval_instruction(expr: str, context: Dict[str, Any], buffer: Optional[List[int]] = None) -> List[int]:
|
||||
ins = parse_instruction(expr)
|
||||
|
||||
def eval_instruction(expr: Union[str, int], context: Dict[str, Any], buffer: Optional[List[int]] = None) -> List[int]:
|
||||
if buffer is None:
|
||||
buffer = []
|
||||
|
||||
ins.build_instruction(context, buffer, 0)
|
||||
if isinstance(expr, str):
|
||||
ins = parse_instruction(expr)
|
||||
|
||||
ins.build_instruction(context, buffer, 0)
|
||||
|
||||
elif isinstance(expr, int):
|
||||
if expr in (DeviceInstruction.VIS_RST,
|
||||
DeviceInstruction.VIS_ASK,
|
||||
DeviceInstruction.VIS_STI,
|
||||
DeviceInstruction.VIS_FUH,
|
||||
DeviceInstruction.VIS_INT,
|
||||
DeviceInstruction.VIS_CAL):
|
||||
buffer.extend([DeviceInstruction.TYP_VIS, expr])
|
||||
|
||||
else:
|
||||
raise RuntimeError('unknown expr code : ' + str(expr))
|
||||
|
||||
else:
|
||||
raise RuntimeError('illegal expr type : ' + str(expr))
|
||||
|
||||
return buffer
|
||||
|
||||
|
||||
def print_instruction(expr: str, context: Dict[str, Any], append_ris_type: bool = True):
|
||||
def print_instruction(expr: Union[str, int],
|
||||
context: Dict[str, Any],
|
||||
append_ris_type: bool = True,
|
||||
c_style_uint8_array: Optional[str] = None):
|
||||
buffer = []
|
||||
|
||||
eval_instruction(expr, context, buffer)
|
||||
|
||||
if append_ris_type:
|
||||
if append_ris_type and isinstance(expr, str):
|
||||
length = len(buffer)
|
||||
buffer.insert(0, 0x30)
|
||||
buffer.insert(1, length)
|
||||
|
||||
print(hex_line(buffer))
|
||||
if c_style_uint8_array is None:
|
||||
print(hex_line(buffer))
|
||||
else:
|
||||
for i, v in enumerate(buffer):
|
||||
print(c_style_uint8_array, '[%d]' % i, ' = ', '0x%02X' % v, ';', sep='')
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
CPU_FREQUENCY = 48e6
|
||||
|
||||
|
||||
def headstage_gptimer_get_frequency_load_value(frequency: float) -> int:
|
||||
load = int(CPU_FREQUENCY / frequency) - 1
|
||||
|
||||
if load < 0xFFFF:
|
||||
return load
|
||||
else:
|
||||
return 0xFA0000 | int(load / 250) - 1
|
||||
|
||||
|
||||
def headstage_gptimer_get_timeout_load_value(timeout_us: int) -> int:
|
||||
load = int(timeout_us * CPU_FREQUENCY / 1e6) - 1
|
||||
|
||||
if load < 0xFFFF:
|
||||
return load
|
||||
else:
|
||||
return 0xFA0000 | int(load / 250) - 1
|
||||
|
||||
|
||||
print('0x%06X' % headstage_gptimer_get_frequency_load_value(0.8))
|
||||
@@ -0,0 +1,115 @@
|
||||
from typing import Dict, Any
|
||||
|
||||
from devlib.util import print_instruction, DeviceInstruction
|
||||
|
||||
CHANNEL_STI_0 = 0
|
||||
CHANNEL_STI_1 = 1
|
||||
|
||||
STI_WAVEFORM_POS = 0x00
|
||||
STI_WAVEFORM_NEG = 0x01
|
||||
STI_WAVEFORM_P2N = 0x02
|
||||
STI_WAVEFORM_N2P = 0x03
|
||||
|
||||
STI_PRECISION_10 = 0
|
||||
STI_PRECISION_01 = 1
|
||||
|
||||
STI_INSTRUCTION = {
|
||||
'GLOBAL': '5b11111;2b0#GV;12bCURRENT',
|
||||
'LOCAL': '5b11111;2b01#LV;3b>CHANNEL;1b>PRECISION;3b>STI_MODE;12b>STI_FREQ;10b>STI_PW;10b>STI_PW_IPI;10b>STI_NUM',
|
||||
'CHANNEL': '5b11111;2b10#CE;ba0;ba1;ba2;ba3;ba4;ba5;ba6;ba7;ba8;ba9;baa;bab;bac;bad;bae;baf'
|
||||
}
|
||||
|
||||
DEFAULT_PARAMETER = {
|
||||
'CURRENT': 10, # uA
|
||||
'CHANNEL': CHANNEL_STI_0,
|
||||
'STI_MODE': STI_WAVEFORM_POS,
|
||||
'PRECISION': STI_PRECISION_10,
|
||||
'STI_FREQ': 1000, # Hz
|
||||
'STI_PW': 100, # us
|
||||
'STI_PW_IPI': 50, # us
|
||||
'STI_NUM': 900,
|
||||
}
|
||||
|
||||
|
||||
def validate_frequency_parameter(parameter: Dict[str, Any]) -> bool:
|
||||
p = int(parameter['PRECISION'])
|
||||
f = int(parameter['STI_FREQ'])
|
||||
w = int(parameter['STI_PW'])
|
||||
i = int(parameter['STI_PW_IPI'])
|
||||
return 1e6 * (1 if p == 0 else 10) / f >= 2 * w + i
|
||||
|
||||
|
||||
def get_channel_enable_parameter(*channel: int):
|
||||
return {
|
||||
'a0': 1 if 0 in channel else 0,
|
||||
'a1': 1 if 1 in channel else 0,
|
||||
'a2': 1 if 2 in channel else 0,
|
||||
'a3': 1 if 3 in channel else 0,
|
||||
'a4': 1 if 4 in channel else 0,
|
||||
'a5': 1 if 5 in channel else 0,
|
||||
'a6': 1 if 6 in channel else 0,
|
||||
'a7': 1 if 7 in channel else 0,
|
||||
'a8': 1 if 8 in channel else 0,
|
||||
'a9': 1 if 9 in channel else 0,
|
||||
'aa': 1 if 10 in channel else 0,
|
||||
'ab': 1 if 11 in channel else 0,
|
||||
'ac': 1 if 12 in channel else 0,
|
||||
'ad': 1 if 13 in channel else 0,
|
||||
'ae': 1 if 14 in channel else 0,
|
||||
'af': 1 if 15 in channel else 0,
|
||||
}
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------- #
|
||||
|
||||
STI_PARAMETER_0 = {
|
||||
'CURRENT': 10, # uA
|
||||
'CHANNEL': CHANNEL_STI_0,
|
||||
'STI_MODE': STI_WAVEFORM_POS,
|
||||
'PRECISION': STI_PRECISION_10,
|
||||
'STI_FREQ': 10, # Hz
|
||||
'STI_PW': 10, # us
|
||||
'STI_PW_IPI': 10, # us
|
||||
'STI_NUM': 900,
|
||||
}
|
||||
|
||||
STI_PARAMETER_1 = {
|
||||
'CURRENT': 10, # uA
|
||||
'CHANNEL': CHANNEL_STI_1,
|
||||
'STI_MODE': STI_WAVEFORM_NEG,
|
||||
'PRECISION': STI_PRECISION_10,
|
||||
'STI_FREQ': 10, # Hz
|
||||
'STI_PW': 10, # us
|
||||
'STI_PW_IPI': 10, # us
|
||||
'STI_NUM': 900,
|
||||
}
|
||||
|
||||
print_instruction(STI_INSTRUCTION['GLOBAL'], STI_PARAMETER_0, append_ris_type=False)
|
||||
|
||||
valid_channel_0 = validate_frequency_parameter(STI_PARAMETER_0)
|
||||
valid_channel_1 = validate_frequency_parameter(STI_PARAMETER_1)
|
||||
enable_channel = []
|
||||
|
||||
if not valid_channel_0:
|
||||
print('invalidate parameter')
|
||||
else:
|
||||
print('----')
|
||||
print_instruction(STI_INSTRUCTION['LOCAL'], STI_PARAMETER_0, append_ris_type=False)
|
||||
enable_channel.append(0)
|
||||
|
||||
if not valid_channel_1:
|
||||
print('invalidate parameter')
|
||||
else:
|
||||
print('----')
|
||||
print_instruction(STI_INSTRUCTION['LOCAL'], STI_PARAMETER_1, append_ris_type=False)
|
||||
enable_channel.append(1)
|
||||
|
||||
if valid_channel_0 or valid_channel_1:
|
||||
print('----')
|
||||
print_instruction(STI_INSTRUCTION['CHANNEL'], get_channel_enable_parameter(*enable_channel), append_ris_type=False)
|
||||
|
||||
print('--sti--')
|
||||
print_instruction(DeviceInstruction.VIS_STI, {})
|
||||
|
||||
print('--int--')
|
||||
print_instruction(DeviceInstruction.VIS_INT, {})
|
||||
@@ -0,0 +1,133 @@
|
||||
from typing import Dict, Any
|
||||
|
||||
from devlib.util import print_instruction, DeviceInstruction
|
||||
|
||||
CHANNEL_STI_0 = 0
|
||||
CHANNEL_STI_1 = 1
|
||||
|
||||
STI_WAVEFORM_POS = 0x00
|
||||
STI_WAVEFORM_NEG = 0x01
|
||||
STI_WAVEFORM_P2N = 0x02
|
||||
STI_WAVEFORM_N2P = 0x03
|
||||
|
||||
STI_PRECISION_10 = 0
|
||||
STI_PRECISION_01 = 1
|
||||
|
||||
STI_NUM_INFINITE = 1000
|
||||
|
||||
STI_INSTRUCTION = {
|
||||
'GLOBAL': '3b001#header#;1b0;12bCURRENT',
|
||||
'LOCAL': '3b010#header;1b0;4b>CHANNEL;3b>STI_MODE;1b>PRECISION;12b>STI_FREQ;10b>STI_PW;10b>STI_PW_IPI;10b>STI_NUM'
|
||||
}
|
||||
|
||||
DEFAULT_PARAMETER = {
|
||||
'CURRENT': 10, # uA
|
||||
'CHANNEL': CHANNEL_STI_0,
|
||||
'STI_MODE': STI_WAVEFORM_POS,
|
||||
'PRECISION': STI_PRECISION_10,
|
||||
'STI_FREQ': 1000, # Hz
|
||||
'STI_PW': 100, # us
|
||||
'STI_PW_IPI': 50, # us
|
||||
'STI_NUM': STI_NUM_INFINITE,
|
||||
}
|
||||
|
||||
|
||||
def validate_frequency_parameter(parameter: Dict[str, Any]) -> bool:
|
||||
p = int(parameter['PRECISION'])
|
||||
f = int(parameter['STI_FREQ'])
|
||||
w = int(parameter['STI_PW'])
|
||||
i = int(parameter['STI_PW_IPI'])
|
||||
return 1e6 * (1 if p == 0 else 10) / f >= 2 * w + i
|
||||
|
||||
|
||||
SPIN_TIMEOUT = [
|
||||
(10, 53),
|
||||
(20, 106),
|
||||
(30, 160),
|
||||
(40, 214),
|
||||
(50, 265),
|
||||
(60, 319),
|
||||
(70, 374),
|
||||
(80, 427),
|
||||
(100, 533),
|
||||
(150, 800),
|
||||
(200, 1066),
|
||||
(300, 1600),
|
||||
(400, 2133),
|
||||
(500, 2666),
|
||||
(1000, 5332),
|
||||
]
|
||||
|
||||
|
||||
def get_spin_timeout_value(timeout_us: int) -> int:
|
||||
if timeout_us == 0:
|
||||
return 0
|
||||
|
||||
elif timeout_us <= SPIN_TIMEOUT[0][0]:
|
||||
return SPIN_TIMEOUT[0][1]
|
||||
|
||||
elif timeout_us >= SPIN_TIMEOUT[-1][0]:
|
||||
return SPIN_TIMEOUT[-1][1]
|
||||
|
||||
else:
|
||||
for i in range(len(SPIN_TIMEOUT)):
|
||||
t0 = SPIN_TIMEOUT[i][0]
|
||||
v0 = SPIN_TIMEOUT[i][1]
|
||||
|
||||
if timeout_us == t0:
|
||||
return v0
|
||||
|
||||
t1 = SPIN_TIMEOUT[i + 1][0]
|
||||
v1 = SPIN_TIMEOUT[i + 1][1]
|
||||
|
||||
if t0 < timeout_us < t1:
|
||||
dt = t1 - t0
|
||||
return int((t1 - timeout_us) * v0 / dt + (timeout_us - t0) * v1 / dt)
|
||||
|
||||
raise RuntimeError()
|
||||
|
||||
|
||||
# -------------------------------------------------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
STI_PARAMETER_0 = {
|
||||
'CURRENT': 10, # uA
|
||||
'CHANNEL': CHANNEL_STI_0,
|
||||
'STI_MODE': STI_WAVEFORM_POS,
|
||||
'PRECISION': STI_PRECISION_10,
|
||||
'STI_FREQ': 10, # Hz
|
||||
'STI_PW': 10, # us
|
||||
'STI_PW_IPI': 10, # us
|
||||
'STI_NUM': STI_NUM_INFINITE,
|
||||
}
|
||||
|
||||
STI_PARAMETER_1 = {
|
||||
'CURRENT': 10, # uA
|
||||
'CHANNEL': CHANNEL_STI_1,
|
||||
'STI_MODE': STI_WAVEFORM_NEG,
|
||||
'PRECISION': STI_PRECISION_10,
|
||||
'STI_FREQ': 10, # Hz
|
||||
'STI_PW': 10, # us
|
||||
'STI_PW_IPI': 10, # us
|
||||
'STI_NUM': STI_NUM_INFINITE,
|
||||
}
|
||||
|
||||
print_instruction(STI_INSTRUCTION['GLOBAL'], STI_PARAMETER_0, append_ris_type=False)
|
||||
|
||||
if not validate_frequency_parameter(STI_PARAMETER_0):
|
||||
print('invalidate parameter')
|
||||
else:
|
||||
print('----')
|
||||
print_instruction(STI_INSTRUCTION['LOCAL'], STI_PARAMETER_0, append_ris_type=False)
|
||||
|
||||
if not validate_frequency_parameter(STI_PARAMETER_1):
|
||||
print('invalidate parameter')
|
||||
else:
|
||||
print('----')
|
||||
print_instruction(STI_INSTRUCTION['LOCAL'], STI_PARAMETER_1, append_ris_type=False)
|
||||
|
||||
print('--sti--')
|
||||
print_instruction(DeviceInstruction.VIS_STI, {})
|
||||
|
||||
print('--int--')
|
||||
print_instruction(DeviceInstruction.VIS_INT, {})
|
||||
@@ -1 +0,0 @@
|
||||
*.txt
|
||||
@@ -1,528 +1,7 @@
|
||||
"""
|
||||
purpose:
|
||||
|
||||
in order to analyze the data loss of bluetooth, a small code is needed.
|
||||
Guess that there are three type of data loss. In order to prove this idea,
|
||||
several tests are needed
|
||||
|
||||
types of data loss:
|
||||
|
||||
1. packet loss:
|
||||
bluetooth notification does not need any negotiation.
|
||||
if there is any packet loss during the connection,
|
||||
it will not be lost forever
|
||||
|
||||
2. program delay causes loss in client(headstage):
|
||||
too many effort on data packaging, it would cause
|
||||
data delay
|
||||
|
||||
3. program delay causes loss in host(controller):
|
||||
...todo and need to define
|
||||
|
||||
Assume that we have lost several bytes data. We want to analyze the type of data lost.
|
||||
method:
|
||||
compare ramp data with time stamp, there are several conditions
|
||||
if data_delta * 1 / sampling_rate == time_delta:
|
||||
this should be packet loss
|
||||
else
|
||||
this should be program delay
|
||||
|
||||
method to coped with the corresponding problem:
|
||||
1. try 'Indication' to check data loss is reduced or not.
|
||||
2. modified the procedure of data packaging
|
||||
3. after the upper two problems are excluded, this problem should be left over
|
||||
|
||||
"""
|
||||
import os.path
|
||||
import sys
|
||||
from collections import Counter
|
||||
from typing import List, Optional, Dict, Set, Any
|
||||
|
||||
|
||||
class Options:
|
||||
def __init__(self):
|
||||
self.skip = False
|
||||
self.round = 2
|
||||
self.overflow_pow: Optional[int] = None
|
||||
|
||||
# print options
|
||||
self.quiet = False
|
||||
|
||||
# graph options
|
||||
self.graph: Optional[str] = None
|
||||
self.graph_log_scale = False
|
||||
self.graph_save_path: Optional[str] = None
|
||||
|
||||
# fft graph options
|
||||
self.fft_x_log = False
|
||||
self.fft_y_norm = False
|
||||
self.fft_channel = 0
|
||||
|
||||
@staticmethod
|
||||
def print_help():
|
||||
prg = sys.argv[0]
|
||||
|
||||
print(prg, '[OPTIONS]', 'FILE', '...')
|
||||
print()
|
||||
print('OPTIONS:')
|
||||
print(' -h, --help : print help')
|
||||
print(' --skip : skip if FILE not found')
|
||||
print(' --round VALUE : floating number round')
|
||||
print(' --overflow VALUE : overflow number. 2^VALUE')
|
||||
print()
|
||||
print('OPTIONS (print):')
|
||||
print(' -q : do not print table')
|
||||
print()
|
||||
print('OPTIONS (graph):')
|
||||
print(' --graph TYPE : use matplotlib to generate graph. could be:')
|
||||
print(' ramp : ramp data, calculate value miss')
|
||||
print(' fft : sin wave data, calculate fft')
|
||||
print(' --graph-log-scale :')
|
||||
print(' --graph-save PATH : save graph file path')
|
||||
print()
|
||||
print('OPTIONS (graph=fft):')
|
||||
print(' --fft-channel CH : filter channel')
|
||||
print(' --fft-log : log x-axis')
|
||||
print(' --fft-norm : log x-axis normalize')
|
||||
print(' --fft [opt,...] : above')
|
||||
print()
|
||||
print('ARGUMENTS:')
|
||||
print(' FILE : txt data file')
|
||||
print()
|
||||
|
||||
|
||||
class Result:
|
||||
def __init__(self, data_file: str, options: Options):
|
||||
# data file information
|
||||
self.data_file = data_file
|
||||
self.date_time: Optional[str] = None
|
||||
self.device_name: Optional[str] = None
|
||||
self.device_address: Optional[str] = None
|
||||
self.parameter: Dict[str, str] = {}
|
||||
self.channel: Set[int] = set()
|
||||
self.total_duration: float = 0.0
|
||||
|
||||
# analysis data
|
||||
self.data_count = 0
|
||||
self.time_delta_counter = Counter()
|
||||
self.value_delta_counter = Counter()
|
||||
|
||||
# analysis options
|
||||
self.round = options.round
|
||||
|
||||
self.overflow: Optional[int] = None
|
||||
if options.overflow_pow is not None:
|
||||
self.overflow = 2 ** options.overflow_pow
|
||||
|
||||
# temp data
|
||||
self._prev_time: Optional[float] = None
|
||||
self._prev_value: Optional[int] = None
|
||||
self._close = False
|
||||
|
||||
@property
|
||||
def sample_rate(self) -> int:
|
||||
try:
|
||||
sample_rate = self.parameter['SAMPLE_RATE']
|
||||
except KeyError as e:
|
||||
raise RuntimeError('data file do not contain SAMPLE_RATE') from e
|
||||
|
||||
try:
|
||||
return int(sample_rate)
|
||||
except ValueError as e:
|
||||
raise RuntimeError('data file SAMPLE_RATE value not a value : ' + str(sample_rate)) from e
|
||||
|
||||
def update(self, time: float, channel: int, value: int):
|
||||
if self._close:
|
||||
raise RuntimeError('closed')
|
||||
|
||||
self.data_count += 1
|
||||
|
||||
if self._prev_time is not None:
|
||||
delta = round(time - self._prev_time, self.round)
|
||||
self.time_delta_counter[delta] += 1
|
||||
|
||||
if self._prev_value is not None:
|
||||
delta = value - self._prev_value
|
||||
self.value_delta_counter[delta] += 1
|
||||
|
||||
self._prev_time = time
|
||||
self.channel.add(channel)
|
||||
self._prev_value = value
|
||||
self.total_duration = time
|
||||
|
||||
def close(self):
|
||||
self._close = True
|
||||
|
||||
if self.overflow is not None:
|
||||
|
||||
self.value_delta_counter[1] += self.value_delta_counter[1 - self.overflow]
|
||||
del self.value_delta_counter[1 - self.overflow]
|
||||
i = 2
|
||||
|
||||
while i - self.overflow in self.value_delta_counter:
|
||||
self.value_delta_counter[i] += self.value_delta_counter[i - self.overflow]
|
||||
del self.value_delta_counter[i - self.overflow]
|
||||
i += 1
|
||||
|
||||
|
||||
def calculate(txt_file: str, options: Options) -> Result:
|
||||
if not os.path.exists(txt_file):
|
||||
raise FileNotFoundError(txt_file)
|
||||
|
||||
result = Result(txt_file, options)
|
||||
|
||||
parsing_state = 0
|
||||
|
||||
with open(txt_file) as _file:
|
||||
for line, content in enumerate(_file): # type: int, str
|
||||
content = content.strip()
|
||||
|
||||
if len(content) == 0:
|
||||
continue
|
||||
|
||||
if parsing_state == 0:
|
||||
if content.startswith('#'):
|
||||
if result.date_time is None:
|
||||
result.date_time = content[1:].strip()
|
||||
|
||||
elif content.startswith('# device_name'):
|
||||
result.device_name = content[len('# device_name'):].strip()
|
||||
|
||||
elif content.startswith('# mac_address'):
|
||||
result.device_address = content[len('# mac_address'):].strip()
|
||||
|
||||
elif content.startswith('# parameter'):
|
||||
parsing_state = 1
|
||||
|
||||
elif parsing_state == 1:
|
||||
if content.startswith('#'):
|
||||
if content.startswith('# time_stamp'):
|
||||
parsing_state = 2
|
||||
|
||||
else:
|
||||
part = content[2:].split(' ', maxsplit=2)
|
||||
|
||||
result.parameter[part[0]] = part[1]
|
||||
|
||||
elif parsing_state == 2:
|
||||
if content.startswith('#'):
|
||||
continue
|
||||
|
||||
part = content.split(' ', maxsplit=3)
|
||||
|
||||
try:
|
||||
time = part[0]
|
||||
channel = part[1]
|
||||
value = part[2]
|
||||
except IndexError:
|
||||
print('@%d' % (line + 1), 'incomplete data', ':', content)
|
||||
continue
|
||||
|
||||
check_pass = True
|
||||
|
||||
try:
|
||||
time = float(time)
|
||||
except ValueError:
|
||||
print('@%d' % (line + 1), 'incomplete time', ':', time)
|
||||
check_pass = False
|
||||
|
||||
try:
|
||||
channel = int(channel)
|
||||
except ValueError:
|
||||
print('@%d' % (line + 1), 'incomplete channel', ':', channel)
|
||||
check_pass = False
|
||||
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
print('@%d' % (line + 1), 'incomplete value', ':', value)
|
||||
check_pass = False
|
||||
|
||||
if check_pass:
|
||||
result.update(time, channel, value)
|
||||
|
||||
result.close()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def print_result(result: Result, options: Options):
|
||||
def print_table(counter: Dict[Any, Any], key_format='%10d', value_format='%d'):
|
||||
f = ' %s : %s' % (key_format, value_format)
|
||||
for k in sorted(counter.keys()):
|
||||
print(f % (k, counter[k]))
|
||||
|
||||
if not options.quiet:
|
||||
print(result.data_file)
|
||||
print('data_count', result.data_count)
|
||||
print('channel', ' '.join(list(map(str, sorted(result.channel)))))
|
||||
|
||||
try:
|
||||
sample_rate = result.sample_rate
|
||||
print('sample_rate [1/s]', sample_rate)
|
||||
print('1/sample_rate [ms]', 1000 / sample_rate)
|
||||
except RuntimeError:
|
||||
print('sample_rate', '(E)')
|
||||
|
||||
print('time_delta')
|
||||
print_table(result.time_delta_counter, '%10.2f')
|
||||
print()
|
||||
|
||||
print('value_delta')
|
||||
print_table(result.value_delta_counter)
|
||||
print()
|
||||
|
||||
# packet miss rate
|
||||
|
||||
#
|
||||
if options.graph == 'ramp':
|
||||
delta_value = list(filter(lambda it: it > 0, result.value_delta_counter))
|
||||
total = sum(map(lambda it: it * result.value_delta_counter[it], delta_value))
|
||||
miss = sum(map(lambda it: (it - 1) * result.value_delta_counter[it], delta_value))
|
||||
print('value_miss (ramp)', '%d/%d' % (miss, total), '%.2f%%' % (100 * miss / total))
|
||||
valid_time = list(filter(lambda it: it < 50, result.time_delta_counter))
|
||||
total_valid_t = sum(map(lambda it: it * result.time_delta_counter[it], valid_time))
|
||||
print('time_waste (ramp)', '%d/%d' % (total_valid_t, result.total_duration), '%.2f%%' % ( 100 * total_valid_t / result.total_duration))
|
||||
timesofwaste = list(filter(lambda it: it > 50, result.time_delta_counter))
|
||||
timesintotal = sum(map(lambda it: result.time_delta_counter[it], timesofwaste))
|
||||
print('waste time occur times (ramp)', '%d' % timesintotal)
|
||||
print()
|
||||
|
||||
paint_ramp_result(result, options)
|
||||
|
||||
elif options.graph == 'fft':
|
||||
paint_fft_result(result, options)
|
||||
|
||||
|
||||
def paint_fft_result(result: Result, options: Options):
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from scipy import signal
|
||||
from scipy.interpolate import interp1d
|
||||
from scipy.fftpack import fft
|
||||
|
||||
time_seq = []
|
||||
value_seq = []
|
||||
time_offset = None
|
||||
total_duration = 0.0
|
||||
|
||||
with open(result.data_file) as _file:
|
||||
for line in _file:
|
||||
line = line.strip()
|
||||
|
||||
if len(line) == 0 or line.startswith('#'):
|
||||
continue
|
||||
|
||||
else:
|
||||
part = line.split(' ', maxsplit=3)
|
||||
channel = int(part[1])
|
||||
|
||||
if channel == options.fft_channel:
|
||||
time = float(part[0])
|
||||
|
||||
if time_offset is None:
|
||||
time_seq.append(0.0)
|
||||
time_offset = time
|
||||
else:
|
||||
total_duration = time - time_offset
|
||||
time_seq.append(time - time_offset)
|
||||
|
||||
value_seq.append(int(part[2]))
|
||||
|
||||
if len(time_seq) == 0:
|
||||
raise RuntimeError('empty channel data : ' + str(options.fft_channel))
|
||||
|
||||
plt.figure(1)
|
||||
f1, pxx_den = signal.periodogram(value_seq, 1e3)
|
||||
plt.semilogy(f1, pxx_den)
|
||||
plt.ylim([1e-7, 1e3])
|
||||
plt.xlabel('frequency [hz]')
|
||||
plt.ylabel('PSD[v**2/Hz')
|
||||
|
||||
plt.figure(2)
|
||||
sample_rate = result.sample_rate
|
||||
time_delta = 1 / sample_rate
|
||||
total_time_step = int(total_duration / (time_delta * 1000))
|
||||
|
||||
f = interp1d(time_seq, value_seq, copy=False)
|
||||
|
||||
t = np.linspace(0, total_duration, total_time_step)
|
||||
|
||||
fft_result = fft(f(t))
|
||||
fft_result = fft_result[:len(fft_result) // 2]
|
||||
fft_x = np.linspace(0, 1.0/(2.0*time_delta), len(fft_result)//2)
|
||||
|
||||
if options.fft_x_log:
|
||||
fft_x = np.log10(fft_x)
|
||||
|
||||
if options.fft_y_norm:
|
||||
fft_result /= sum(fft_result)
|
||||
|
||||
plt.plot(fft_x, 2.0 / len(fft_result) * np.abs(fft_result[0:len(fft_result)//2]))
|
||||
|
||||
|
||||
if options.graph_save_path is not None:
|
||||
plt.savefig(options.graph_save_path, dpi=600)
|
||||
else:
|
||||
plt.show()
|
||||
|
||||
|
||||
def paint_ramp_result(result: Result, options: Options):
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
fig, (at, av) = plt.subplots(2, 1)
|
||||
|
||||
time_delta_data = list(result.time_delta_counter)
|
||||
expect_time_delta = 1000 / result.sample_rate
|
||||
time_delta_bins = int((max(time_delta_data) - min(time_delta_data)) / expect_time_delta)
|
||||
time_delta_weight = [result.time_delta_counter[k] for k in time_delta_data]
|
||||
at.hist(time_delta_data,
|
||||
bins=time_delta_bins,
|
||||
weights=time_delta_weight,
|
||||
log=options.graph_log_scale,
|
||||
align='left')
|
||||
|
||||
value_delta_data = list(result.value_delta_counter)
|
||||
value_delta_bins = max(value_delta_data) - min(value_delta_data)
|
||||
value_delta_weight = [result.value_delta_counter[k] for k in value_delta_data]
|
||||
av.hist(value_delta_data,
|
||||
bins=value_delta_bins,
|
||||
weights=value_delta_weight,
|
||||
log=options.graph_log_scale,
|
||||
align='left')
|
||||
|
||||
fig.tight_layout()
|
||||
|
||||
if options.graph_save_path is not None:
|
||||
plt.savefig(options.graph_save_path, dpi=600)
|
||||
else:
|
||||
plt.show()
|
||||
|
||||
|
||||
|
||||
|
||||
def main(argv: List[str]):
|
||||
"""
|
||||
|
||||
:param argv:
|
||||
:return:
|
||||
"""
|
||||
|
||||
# df = pd.read_csv("C:/Users/yichin/Downloads/last-2019-07-18-16-30-15-7.csv", sep=",", skiprows=12, header=None)
|
||||
# sel_df = pd.DataFrame(df)
|
||||
# column, row = sel_df.shape
|
||||
# sel_df = sel_df.fillna(value=0)
|
||||
# delta_df = sel_df.diff(periods=1)
|
||||
# delta_df = delta_df.fillna(value=0)
|
||||
# delta_df = delta_df.drop(column - 1)
|
||||
# delta_df.set_axis(['time_delta', 'data_delta'], axis='columns', inplace=True)
|
||||
|
||||
o = Options()
|
||||
|
||||
i = 0
|
||||
while i < len(argv):
|
||||
arg = argv[i]
|
||||
|
||||
if arg in ('-h', '--help'):
|
||||
o.print_help()
|
||||
return
|
||||
|
||||
elif arg == '--skip':
|
||||
o.skip = True
|
||||
i += 1
|
||||
|
||||
elif arg == '--round':
|
||||
o.round = int(argv[i + 1])
|
||||
i += 2
|
||||
|
||||
elif arg.startswith('--round='):
|
||||
o.round = int(arg[len('--round='):])
|
||||
i += 1
|
||||
|
||||
elif arg == '--overflow':
|
||||
o.overflow_pow = int(argv[i + 1])
|
||||
i += 2
|
||||
|
||||
elif arg.startswith('--overflow='):
|
||||
o.overflow_pow = int(arg[len('--overflow='):])
|
||||
i += 1
|
||||
|
||||
elif arg == '-q':
|
||||
o.quiet = True
|
||||
i += 1
|
||||
|
||||
elif arg == '--graph':
|
||||
o.graph = argv[i + 1]
|
||||
i += 2
|
||||
|
||||
elif arg.startswith('--graph='):
|
||||
o.graph = arg[len('--graph='):]
|
||||
i += 1
|
||||
|
||||
elif arg == '--graph-log-scale':
|
||||
o.graph_log_scale = True
|
||||
i += 1
|
||||
|
||||
elif arg == '--graph-save':
|
||||
o.graph_save_path = argv[i + 1]
|
||||
i += 2
|
||||
|
||||
elif arg.startswith('--graph-save='):
|
||||
o.graph = arg[len('--graph-save='):]
|
||||
i += 1
|
||||
|
||||
elif arg == '--fft-channel':
|
||||
o.fft_channel = int(argv[i + 1])
|
||||
i += 2
|
||||
|
||||
elif arg.startswith('--fft-channel='):
|
||||
o.fft_channel = int(arg[len('--fft-channel='):])
|
||||
i += 1
|
||||
|
||||
elif arg == '--fft-log':
|
||||
o.fft_x_log = True
|
||||
i += 1
|
||||
|
||||
elif arg == '--fft-norm':
|
||||
o.fft_y_norm = True
|
||||
i += 1
|
||||
|
||||
elif arg.startswith('--fft'):
|
||||
if arg == '--fft':
|
||||
c = argv[i + 1]
|
||||
i += 2
|
||||
elif arg.startswith('--fft='):
|
||||
c = arg[len('--fft='):]
|
||||
i += 1
|
||||
else:
|
||||
raise ValueError('unknown options : ' + arg)
|
||||
|
||||
for a in c.split(','):
|
||||
if a == 'log':
|
||||
o.fft_x_log = True
|
||||
elif a == 'norm':
|
||||
o.fft_y_norm = True
|
||||
elif a.startswith('channel='):
|
||||
o.fft_channel = int(a[len('channel='):])
|
||||
else:
|
||||
raise ValueError('unknown options : --fft-' + a)
|
||||
|
||||
elif arg.startswith('-'):
|
||||
raise ValueError('unknown options : ' + arg)
|
||||
|
||||
else:
|
||||
i += 1
|
||||
try:
|
||||
result = calculate(arg, o)
|
||||
except FileNotFoundError:
|
||||
if o.skip:
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
|
||||
else:
|
||||
print_result(result, o)
|
||||
def main():
|
||||
with open('C:/ti/python_test_code/uni/att_notify.psd', 'r') as file:
|
||||
print(file.read())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
from devlib.util import print_instruction
|
||||
|
||||
NEULIVE_INSTRUCTION = {
|
||||
'RIS': '3b101#header#;2b0;3b>LB;4b0;1bCH;1bFS;3b>WF;5b>TV;4b>PM;4b>NM;4b>SR',
|
||||
'UMC': '3b001#umc_parameter;3b>AG;4b>PW;6b>TT;2b>SB;6b>TF;1bCA;1bCB;1bCC;1bCD;4b>CHA;4b>CHB;4b>CHC;4b>CHD'
|
||||
}
|
||||
|
||||
NEULIVE_PARAMETER = {
|
||||
'LB': 0,
|
||||
'CH': 0,
|
||||
'FS': 0,
|
||||
'WF': 0,
|
||||
'TV': 0,
|
||||
'PM': 15,
|
||||
'NM': 0,
|
||||
'SR': 0,
|
||||
'AG': 5,
|
||||
'PW': 0,
|
||||
'TT': 0,
|
||||
'SB': 1,
|
||||
'TF': 3,
|
||||
'CA': 1,
|
||||
'CB': 0,
|
||||
'CC': 0,
|
||||
'CD': 0,
|
||||
'CHA': 0,
|
||||
'CHB': 1,
|
||||
'CHC': 2,
|
||||
'CHD': 3,
|
||||
}
|
||||
|
||||
print_instruction(NEULIVE_INSTRUCTION['RIS'], NEULIVE_PARAMETER)
|
||||
print_instruction(NEULIVE_INSTRUCTION['UMC'], NEULIVE_PARAMETER)
|
||||
@@ -1,15 +1,47 @@
|
||||
import unittest
|
||||
from random import randint
|
||||
from typing import List, Optional
|
||||
from typing import List, Optional, Tuple, Iterable
|
||||
|
||||
REC_CHANNEL_COUNT = 16
|
||||
REC_CHANNEL_COUNT = 12
|
||||
|
||||
CHANNEL_INS2MUX = (10, 0, 1, 2, 3, 8, 7, 6, 5, 4, 9, 8)
|
||||
'''index:ins -> value:mux'''
|
||||
|
||||
CHANNEL_MUX2INS = (1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 0, 11)
|
||||
'''index:mux -> value:ins'''
|
||||
|
||||
|
||||
def to_channel_table(*channel: int) -> List[bool]:
|
||||
return [i in channel for i in range(REC_CHANNEL_COUNT)]
|
||||
|
||||
|
||||
def rearrange_channel_mux_table(channel_table: List[bool]) -> Optional[List[int]]:
|
||||
def to_mux_channel(channel: Iterable[int], sort=False) -> List[int]:
|
||||
ret = [CHANNEL_INS2MUX[ch] for ch in channel]
|
||||
|
||||
if sort:
|
||||
ret.sort()
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def to_ins_channel(channel: Iterable[int], sort=False) -> List[int]:
|
||||
ret = [CHANNEL_MUX2INS[ch] for ch in channel]
|
||||
|
||||
if sort:
|
||||
ret.sort()
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def to_mux_channel_table(*channel: int) -> List[bool]:
|
||||
return [CHANNEL_MUX2INS[i] in channel for i in range(REC_CHANNEL_COUNT)]
|
||||
|
||||
|
||||
def to_ins_channel_table(*channel: int) -> List[bool]:
|
||||
return [CHANNEL_INS2MUX[i] in channel for i in range(REC_CHANNEL_COUNT)]
|
||||
|
||||
|
||||
def rearrange_channel_mux_table(channel_table: List[bool]) -> Tuple[int, Optional[List[int]]]:
|
||||
enable_channel_number = 0
|
||||
last_enable_channel = 0
|
||||
|
||||
@@ -19,14 +51,14 @@ def rearrange_channel_mux_table(channel_table: List[bool]) -> Optional[List[int]
|
||||
enable_channel_number += 1
|
||||
|
||||
if enable_channel_number == 0:
|
||||
return None
|
||||
return 0, None
|
||||
|
||||
channel_mux = [0 for _ in range(REC_CHANNEL_COUNT)]
|
||||
|
||||
if enable_channel_number == 1:
|
||||
channel_mux[0] = last_enable_channel
|
||||
|
||||
return channel_mux
|
||||
return 1, channel_mux
|
||||
|
||||
next_enable_channel = last_enable_channel
|
||||
channel_mux_index = last_enable_channel
|
||||
@@ -57,131 +89,102 @@ def rearrange_channel_mux_table(channel_table: List[bool]) -> Optional[List[int]
|
||||
channel_mux[channel_mux_index] = channel_mux[channel_mux_index + offset]
|
||||
channel_mux_index -= 1
|
||||
|
||||
return channel_mux
|
||||
return last_enable_channel + 1, channel_mux
|
||||
|
||||
|
||||
def channel_used_count(channel_mux: List[int]):
|
||||
def count_used_channel(channel_mux: List[int]):
|
||||
ret = [0] * REC_CHANNEL_COUNT
|
||||
|
||||
channel_uc = [0] * 16
|
||||
channel_sel = [0] * 16
|
||||
for i in range(15):
|
||||
for j in range(16):
|
||||
if channel_mux[i] == j:
|
||||
if channel_mux[i] != channel_mux[i+1]:
|
||||
channel_uc[j] += 1
|
||||
channel_sel[j] = j
|
||||
for ch in channel_mux:
|
||||
ret[ch] += 1
|
||||
|
||||
return channel_uc, channel_sel
|
||||
return ret
|
||||
|
||||
|
||||
def channel_table_transfer(channel_mux: List[bool]) -> Optional[List[bool]]:
|
||||
channel_look_up_table = [1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 0, 11]
|
||||
true_channel = [False] * 16
|
||||
for i in range(16):
|
||||
if channel_mux[i]:
|
||||
true_channel[channel_look_up_table[i]] = True
|
||||
|
||||
return true_channel
|
||||
def expect_channel_count(*channel: int) -> List[int]:
|
||||
channel_mux = to_mux_channel_table(*channel)
|
||||
used, mux_arrange = rearrange_channel_mux_table(channel_mux)
|
||||
if used == 0:
|
||||
ins_arrange = to_ins_channel([])
|
||||
else:
|
||||
ins_arrange = to_ins_channel(mux_arrange[:used], sort=False)
|
||||
return count_used_channel(ins_arrange)
|
||||
|
||||
|
||||
def channel_table_tran(channel_mux: List[bool]):
|
||||
channel_look_up_table = [2, 3, 4, 5, 10, 9, 8, 7, 6, 11, 1, 12]
|
||||
channel_sel = [0] * 16
|
||||
channel_index = 0
|
||||
for i in range(16):
|
||||
if channel_mux[i]:
|
||||
channel_sel[channel_index] = channel_look_up_table[i]
|
||||
channel_index += 1
|
||||
channel_sel.sort(reverse=True)
|
||||
return channel_sel, channel_index
|
||||
def loop_repeat(col: List[int]) -> Iterable[int]:
|
||||
while True:
|
||||
yield from iter(col)
|
||||
|
||||
|
||||
def channel_use_count(channel_sel: List[int], channel_index: int) -> Optional[List[int]]:
|
||||
repeat_times = int(channel_sel[0] / channel_index)
|
||||
remain_value = int(channel_sel[0] % channel_index)
|
||||
ch_use_cnt = [0] * 16
|
||||
for i in range(channel_index):
|
||||
if i < remain_value:
|
||||
ch_use_cnt[i] = remain_value + repeat_times
|
||||
else:
|
||||
ch_use_cnt[i] = repeat_times
|
||||
return ch_use_cnt
|
||||
def channel_count(*channel: int) -> List[int]:
|
||||
if len(channel) == 0:
|
||||
return [0] * REC_CHANNEL_COUNT
|
||||
|
||||
elif len(channel) == 1:
|
||||
channel = channel[0]
|
||||
return [1 if ch == channel else 0 for ch in range(REC_CHANNEL_COUNT)]
|
||||
|
||||
def count_channel_without_re(channel_mux: List[bool]) -> Optional[List[int]]:
|
||||
channel_sel, channel_index = channel_table_tran(channel_mux)
|
||||
ch_use_cnt = channel_use_count(channel_sel, channel_index)
|
||||
for i in range(channel_index):
|
||||
channel_sel[i] -= 1
|
||||
print(channel_sel)
|
||||
print(ch_use_cnt)
|
||||
return ch_use_cnt
|
||||
else:
|
||||
channel_mux = to_mux_channel(channel, sort=True)
|
||||
ret = [0] * REC_CHANNEL_COUNT
|
||||
i = max(channel_mux) + 1
|
||||
|
||||
for ch in loop_repeat(channel_mux[::-1]):
|
||||
ret[CHANNEL_MUX2INS[ch]] += 1
|
||||
i -= 1
|
||||
if i == 0:
|
||||
break
|
||||
|
||||
def reverse_channel_table(original_ch: List[int]) -> Optional[List[int]]:
|
||||
reverse_look_up_table = [10, 0, 1, 2, 3, 8, 7, 6, 5, 4, 9, 8]
|
||||
reverse_ch = [0] * 16
|
||||
for i in range(16):
|
||||
if original_ch[i] != 0:
|
||||
reverse_ch[reverse_look_up_table[i]] = original_ch[i]
|
||||
return reverse_ch
|
||||
|
||||
|
||||
def count_channel(channel_mux: List[bool]) -> Optional[List[int]]:
|
||||
real_ch = channel_table_transfer(channel_mux)
|
||||
ch_mux = rearrange_channel_mux_table(real_ch)
|
||||
ch_count, ch_sel = channel_used_count(ch_mux)
|
||||
reverse_ch = reverse_channel_table(ch_count)
|
||||
reverse_ch.sort(reverse=True)
|
||||
ch_sel.sort(reverse=True)
|
||||
print(ch_sel)
|
||||
print(reverse_ch)
|
||||
return reverse_ch
|
||||
return ret
|
||||
|
||||
|
||||
class UniRearrangeMuxChannelTest(unittest.TestCase):
|
||||
def test_empty_channel(self):
|
||||
self.assertIsNone(rearrange_channel_mux_table(to_channel_table()))
|
||||
i, a = rearrange_channel_mux_table(to_channel_table())
|
||||
self.assertEqual(0, i)
|
||||
self.assertIsNone(a)
|
||||
|
||||
def test_single_channel(self):
|
||||
for _ in range(3):
|
||||
c = randint(0, REC_CHANNEL_COUNT - 1)
|
||||
|
||||
expect = [c if i == 0 else 0 for i in range(REC_CHANNEL_COUNT)]
|
||||
print(expect)
|
||||
self.assertEqual(expect, rearrange_channel_mux_table(to_channel_table(c)))
|
||||
self.assertTupleEqual((1, expect), rearrange_channel_mux_table(to_channel_table(c)))
|
||||
|
||||
def test_two_channel(self):
|
||||
self.assertEqual([1, 7, 1, 7, 1, 7, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
rearrange_channel_mux_table(to_channel_table(7, 1)))
|
||||
self.assertEqual([2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
rearrange_channel_mux_table(to_channel_table(2, 1)))
|
||||
self.assertEqual([3, 7, 2, 3, 7, 2, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
rearrange_channel_mux_table(to_channel_table(7, 3, 2)))
|
||||
self.assertTupleEqual((8, [1, 7, 1, 7, 1, 7, 1, 7, 0, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(7, 1)))
|
||||
self.assertTupleEqual((3, [2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(2, 1)))
|
||||
self.assertTupleEqual((8, [3, 7, 2, 3, 7, 2, 3, 7, 0, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(7, 3, 2)))
|
||||
|
||||
def test_many_channel(self):
|
||||
self.assertEqual([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ],
|
||||
rearrange_channel_mux_table(to_channel_table(1, 0)))
|
||||
self.assertTupleEqual((2, [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(1, 0)))
|
||||
|
||||
self.assertEqual([2, 5, 2, 5, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ],
|
||||
rearrange_channel_mux_table(to_channel_table(2, 5)))
|
||||
self.assertTupleEqual((6, [2, 5, 2, 5, 2, 5, 0, 0, 0, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(2, 5)))
|
||||
|
||||
self.assertEqual([1, 3, 5, 1, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ],
|
||||
rearrange_channel_mux_table(to_channel_table(1, 3, 5)))
|
||||
self.assertTupleEqual((6, [1, 3, 5, 1, 3, 5, 0, 0, 0, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(1, 3, 5)))
|
||||
|
||||
self.assertEqual([4, 5, 1, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ],
|
||||
rearrange_channel_mux_table(to_channel_table(4, 1, 3, 5)))
|
||||
self.assertTupleEqual((6, [4, 5, 1, 3, 4, 5, 0, 0, 0, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(4, 1, 3, 5)))
|
||||
|
||||
self.assertEqual([5, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ],
|
||||
rearrange_channel_mux_table(to_channel_table(4, 1, 2, 3, 5)))
|
||||
|
||||
self.assertEqual([6, 7, 8, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, ],
|
||||
rearrange_channel_mux_table(to_channel_table(3, 4, 5, 6, 7, 8)))
|
||||
self.assertTupleEqual((6, [5, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(4, 1, 2, 3, 5)))
|
||||
|
||||
self.assertTupleEqual((9, [6, 7, 8, 3, 4, 5, 6, 7, 8, 0, 0, 0]),
|
||||
rearrange_channel_mux_table(to_channel_table(3, 4, 5, 6, 7, 8)))
|
||||
|
||||
def test_count_channel(self):
|
||||
self.assertEqual(count_channel(to_channel_table(7, 3, 2)), count_channel_without_re(to_channel_table(7, 3, 2)))
|
||||
self.assertEqual(count_channel(to_channel_table(0, 10, 2)), count_channel_without_re(to_channel_table(0, 10, 2)))
|
||||
self.assertEqual(expect_channel_count(), channel_count())
|
||||
self.assertEqual(expect_channel_count(0), channel_count(0))
|
||||
self.assertEqual(expect_channel_count(4), channel_count(4))
|
||||
self.assertEqual(expect_channel_count(2, 4), channel_count(4, 2))
|
||||
self.assertEqual(expect_channel_count(7, 3, 2), channel_count(7, 3, 2))
|
||||
self.assertEqual(expect_channel_count(0, 1, 2), channel_count(0, 1, 2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
inEditor=false
|
||||
onBuild=false
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.cdt.debug.core.toggleBreakpointModel=com.ti.ccstudio.debug.CCSBreakpointMarker
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<configurations XML_version="1.2" id="configurations_0">
|
||||
<configuration XML_version="1.2" id="configuration_0">
|
||||
<instance XML_version="1.2" desc="Texas Instruments XDS100v3 USB Debug Probe" href="connections/TIXDS100v3_Dot7_Connection.xml" id="Texas Instruments XDS100v3 USB Debug Probe" xml="TIXDS100v3_Dot7_Connection.xml" xmlpath="connections"/>
|
||||
<connection XML_version="1.2" id="Texas Instruments XDS100v3 USB Debug Probe">
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2icepick_c.xml" id="drivers" xml="tixds100v2icepick_c.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2cs_dap.xml" id="drivers" xml="tixds100v2cs_dap.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2cortexM.xml" id="drivers" xml="tixds100v2cortexM.xml" xmlpath="drivers"/>
|
||||
<property Type="choicelist" Value="2" id="The Converter Usage">
|
||||
<choice Name="Generate 1149.7 2-pin advanced modes" value="enable">
|
||||
<property Type="choicelist" Value="1" id="The Converter 1149.7 Frequency">
|
||||
<choice Name="Overclock with user specified value" value="unused">
|
||||
<property Type="choicelist" Value="5" id="-- Choose a value from 1.0MHz to 50.0MHz"/>
|
||||
</choice>
|
||||
</property>
|
||||
<property Type="choicelist" Value="5" id="The Target Scan Format"/>
|
||||
</choice>
|
||||
</property>
|
||||
<platform XML_version="1.2" id="platform_0">
|
||||
<instance XML_version="1.2" desc="CC2640F128" href="devices/cc2640f128.xml" id="CC2640F128" xml="cc2640f128.xml" xmlpath="devices"/>
|
||||
</platform>
|
||||
</connection>
|
||||
</configuration>
|
||||
</configurations>
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
The 'targetConfigs' folder contains target-configuration (.ccxml) files, automatically generated based
|
||||
on the device and connection settings specified in your project on the Properties > General page.
|
||||
|
||||
Please note that in automatic target-configuration management, changes to the project's device and/or
|
||||
connection settings will either modify an existing or generate a new target-configuration file. Thus,
|
||||
if you manually edit these auto-generated files, you may need to re-apply your changes. Alternatively,
|
||||
you may create your own target-configuration file for this project and manage it manually. You can
|
||||
always switch back to automatic target-configuration management by checking the "Manage the project's
|
||||
target-configuration automatically" checkbox on the project's Properties > General page.
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
inEditor=false
|
||||
onBuild=false
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.cdt.debug.core.toggleBreakpointModel=com.ti.ccstudio.debug.CCSBreakpointMarker
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<configurations XML_version="1.2" id="configurations_0">
|
||||
<configuration XML_version="1.2" id="configuration_0">
|
||||
<instance XML_version="1.2" desc="Texas Instruments XDS100v3 USB Debug Probe" href="connections/TIXDS100v3_Dot7_Connection.xml" id="Texas Instruments XDS100v3 USB Debug Probe" xml="TIXDS100v3_Dot7_Connection.xml" xmlpath="connections"/>
|
||||
<connection XML_version="1.2" id="Texas Instruments XDS100v3 USB Debug Probe">
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2icepick_c.xml" id="drivers" xml="tixds100v2icepick_c.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2cs_dap.xml" id="drivers" xml="tixds100v2cs_dap.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2cortexM.xml" id="drivers" xml="tixds100v2cortexM.xml" xmlpath="drivers"/>
|
||||
<property Type="choicelist" Value="2" id="The Converter Usage">
|
||||
<choice Name="Generate 1149.7 2-pin advanced modes" value="enable">
|
||||
<property Type="choicelist" Value="1" id="The Converter 1149.7 Frequency">
|
||||
<choice Name="Overclock with user specified value" value="unused">
|
||||
<property Type="choicelist" Value="5" id="-- Choose a value from 1.0MHz to 50.0MHz"/>
|
||||
</choice>
|
||||
</property>
|
||||
<property Type="choicelist" Value="5" id="The Target Scan Format"/>
|
||||
</choice>
|
||||
</property>
|
||||
<platform XML_version="1.2" id="platform_0">
|
||||
<instance XML_version="1.2" desc="CC2640F128" href="devices/cc2640f128.xml" id="CC2640F128" xml="cc2640f128.xml" xmlpath="devices"/>
|
||||
</platform>
|
||||
</connection>
|
||||
</configuration>
|
||||
</configurations>
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
The 'targetConfigs' folder contains target-configuration (.ccxml) files, automatically generated based
|
||||
on the device and connection settings specified in your project on the Properties > General page.
|
||||
|
||||
Please note that in automatic target-configuration management, changes to the project's device and/or
|
||||
connection settings will either modify an existing or generate a new target-configuration file. Thus,
|
||||
if you manually edit these auto-generated files, you may need to re-apply your changes. Alternatively,
|
||||
you may create your own target-configuration file for this project and manage it manually. You can
|
||||
always switch back to automatic target-configuration management by checking the "Manage the project's
|
||||
target-configuration automatically" checkbox on the project's Properties > General page.
|
||||
@@ -9,6 +9,6 @@
|
||||
<linkerCommandFile value="cc26x0f128.cmd"/>
|
||||
<rts value="libc.a"/>
|
||||
<createSlaveProjects value=""/>
|
||||
<connection value="common/targetdb/connections/TIXDS110_Connection.xml"/>
|
||||
<isTargetManual value="true"/>
|
||||
<connection value="common/targetdb/connections/TIXDS100v3_Dot7_Connection.xml"/>
|
||||
<isTargetManual value="false"/>
|
||||
</projectOptions>
|
||||
|
||||
+2
-2
@@ -9,6 +9,6 @@
|
||||
<linkerCommandFile value="cc26x0f128.cmd"/>
|
||||
<rts value="libc.a"/>
|
||||
<createSlaveProjects value=""/>
|
||||
<connection value="common/targetdb/connections/TIXDS110_Connection.xml"/>
|
||||
<isTargetManual value="true"/>
|
||||
<connection value="common/targetdb/connections/TIXDS100v3_Dot7_Connection.xml"/>
|
||||
<isTargetManual value="false"/>
|
||||
</projectOptions>
|
||||
|
||||
+1
-1
@@ -9,6 +9,6 @@
|
||||
<linkerCommandFile value="cc26x0f128.cmd"/>
|
||||
<rts value="libc.a"/>
|
||||
<createSlaveProjects value=""/>
|
||||
<connection value="common/targetdb/connections/TIXDS100v3_Dot7_Connection.xml"/>
|
||||
<connection value="common/targetdb/connections/TIXDS110_Connection.xml"/>
|
||||
<isTargetManual value="false"/>
|
||||
</projectOptions>
|
||||
|
||||
@@ -72,7 +72,6 @@
|
||||
</option>
|
||||
<option id="com.ti.ccstudio.buildDefinitions.TMS470_18.1.compilerID.DEFINE.45713043" name="Pre-define NAME (--define, -D)" superClass="com.ti.ccstudio.buildDefinitions.TMS470_18.1.compilerID.DEFINE" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="BOARD_DISPLAY_EXCLUDE_UART"/>
|
||||
<listOptionValue builtIn="false" value="HEADSTAGE_NOTIFY_USE_ATT"/>
|
||||
<listOptionValue builtIn="false" value="POWER_SAVING"/>
|
||||
<listOptionValue builtIn="false" value="BOOSTXL_CC2650MA"/>
|
||||
<listOptionValue builtIn="false" value="HEADSTAGE_MA_USE_SPI2"/>
|
||||
|
||||
+15
-14
@@ -1,19 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<configurations XML_version="1.2" id="configurations_0">
|
||||
<configuration XML_version="1.2" id="Texas Instruments XDS100v3 USB Debug Probe_0">
|
||||
<instance XML_version="1.2" desc="Texas Instruments XDS100v3 USB Debug Probe_0" href="connections/TIXDS100v3_Dot7_Connection.xml" id="Texas Instruments XDS100v3 USB Debug Probe_0" xml="TIXDS100v3_Dot7_Connection.xml" xmlpath="connections"/>
|
||||
<connection XML_version="1.2" id="Texas Instruments XDS100v3 USB Debug Probe_0">
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2icepick_c.xml" id="drivers" xml="tixds100v2icepick_c.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2cs_dap.xml" id="drivers" xml="tixds100v2cs_dap.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2cortexM.xml" id="drivers" xml="tixds100v2cortexM.xml" xmlpath="drivers"/>
|
||||
<property Type="choicelist" Value="2" id="The Converter Usage">
|
||||
<choice Name="Generate 1149.7 2-pin advanced modes" value="enable">
|
||||
<property Type="choicelist" Value="1" id="The Converter 1149.7 Frequency">
|
||||
<choice Name="Overclock with user specified value" value="unused">
|
||||
<property Type="choicelist" Value="5" id="-- Choose a value from 1.0MHz to 50.0MHz"/>
|
||||
</choice>
|
||||
</property>
|
||||
<property Type="choicelist" Value="5" id="The Target Scan Format"/>
|
||||
<configuration XML_version="1.2" id="Texas Instruments XDS110 USB Debug Probe_0">
|
||||
<instance XML_version="1.2" desc="Texas Instruments XDS110 USB Debug Probe_0" href="connections/TIXDS110_Connection.xml" id="Texas Instruments XDS110 USB Debug Probe_0" xml="TIXDS110_Connection.xml" xmlpath="connections"/>
|
||||
<connection XML_version="1.2" id="Texas Instruments XDS110 USB Debug Probe_0">
|
||||
<instance XML_version="1.2" href="drivers/tixds510icepick_c.xml" id="drivers" xml="tixds510icepick_c.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds510cs_dap.xml" id="drivers" xml="tixds510cs_dap.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds510cortexM.xml" id="drivers" xml="tixds510cortexM.xml" xmlpath="drivers"/>
|
||||
<property Type="choicelist" Value="1" id="Power Selection">
|
||||
<choice Name="Probe supplied power" value="1">
|
||||
<property Type="stringfield" Value="3.3" id="Voltage Level"/>
|
||||
</choice>
|
||||
</property>
|
||||
<property Type="choicelist" Value="0" id="JTAG Signal Isolation"/>
|
||||
<property Type="choicelist" Value="4" id="SWD Mode Settings">
|
||||
<choice Name="cJTAG (1149.7) 2-pin advanced modes" value="enable">
|
||||
<property Type="choicelist" Value="1" id="XDS110 Aux Port"/>
|
||||
</choice>
|
||||
</property>
|
||||
<platform XML_version="1.2" id="platform_0">
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -9,6 +9,6 @@
|
||||
<linkerCommandFile value="cc26x0f128.cmd"/>
|
||||
<rts value="libc.a"/>
|
||||
<createSlaveProjects value=""/>
|
||||
<connection value="common/targetdb/connections/TIXDS100v3_Dot7_Connection.xml"/>
|
||||
<connection value="common/targetdb/connections/TIXDS110_Connection.xml"/>
|
||||
<isTargetManual value="false"/>
|
||||
</projectOptions>
|
||||
|
||||
+1
@@ -12,6 +12,7 @@
|
||||
<stringAttribute key="com.ti.ccstudio.debug.debugModel.ATTR_TARGET_CONFIG" value="${target_config_active_default:simple_peripheral_cc2650em_stack}"/>
|
||||
<stringAttribute key="com.ti.ccstudio.debug.debugModel.MRU_PROGRAM.C:\ti\simplelink\ble_sdk_2_02_02_25\examples\cc2650em\simple_peripheral\ccs\stack\targetConfigs\CC2650F128.ccxml.Texas Instruments XDS100v3 USB Debug Probe_0/Cortex_M3_0" value="C:/ti\simplelink\ble_sdk_2_02_02_25\examples\cc2650em\simple_peripheral\ccs\stack\FlashROM\simple_peripheral_cc2650em_stack.out"/>
|
||||
<stringAttribute key="com.ti.ccstudio.debug.debugModel.MRU_PROGRAM.C:\ti\simplelink\ble_sdk_2_02_02_25\examples\cc2650em\simple_peripheral\ccs\stack\targetConfigs\CC2650F128.ccxml.Texas Instruments XDS110 USB Debug Probe/Cortex_M3_0" value="C:/ti\simplelink\ble_sdk_2_02_02_25\examples\cc2650em\simple_peripheral\ccs\stack\FlashROM\simple_peripheral_cc2650em_stack.out"/>
|
||||
<stringAttribute key="com.ti.ccstudio.debug.debugModel.MRU_PROGRAM.C:\ti\simplelink\ble_sdk_2_02_02_25\examples\cc2650em\simple_peripheral\ccs\stack\targetConfigs\CC2650F128.ccxml.Texas Instruments XDS110 USB Debug Probe_0/Cortex_M3_0" value="C:/ti\simplelink\ble_sdk_2_02_02_25\examples\cc2650em\simple_peripheral\ccs\stack\FlashROM\simple_peripheral_cc2650em_stack.out"/>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/simple_peripheral_cc2650em_stack"/>
|
||||
</listAttribute>
|
||||
|
||||
+15
-14
@@ -1,19 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<configurations XML_version="1.2" id="configurations_0">
|
||||
<configuration XML_version="1.2" id="Texas Instruments XDS100v3 USB Debug Probe_0">
|
||||
<instance XML_version="1.2" desc="Texas Instruments XDS100v3 USB Debug Probe_0" href="connections/TIXDS100v3_Dot7_Connection.xml" id="Texas Instruments XDS100v3 USB Debug Probe_0" xml="TIXDS100v3_Dot7_Connection.xml" xmlpath="connections"/>
|
||||
<connection XML_version="1.2" id="Texas Instruments XDS100v3 USB Debug Probe_0">
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2icepick_c.xml" id="drivers" xml="tixds100v2icepick_c.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2cs_dap.xml" id="drivers" xml="tixds100v2cs_dap.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds100v2cortexM.xml" id="drivers" xml="tixds100v2cortexM.xml" xmlpath="drivers"/>
|
||||
<property Type="choicelist" Value="2" id="The Converter Usage">
|
||||
<choice Name="Generate 1149.7 2-pin advanced modes" value="enable">
|
||||
<property Type="choicelist" Value="1" id="The Converter 1149.7 Frequency">
|
||||
<choice Name="Overclock with user specified value" value="unused">
|
||||
<property Type="choicelist" Value="5" id="-- Choose a value from 1.0MHz to 50.0MHz"/>
|
||||
</choice>
|
||||
</property>
|
||||
<property Type="choicelist" Value="5" id="The Target Scan Format"/>
|
||||
<configuration XML_version="1.2" id="Texas Instruments XDS110 USB Debug Probe_0">
|
||||
<instance XML_version="1.2" desc="Texas Instruments XDS110 USB Debug Probe_0" href="connections/TIXDS110_Connection.xml" id="Texas Instruments XDS110 USB Debug Probe_0" xml="TIXDS110_Connection.xml" xmlpath="connections"/>
|
||||
<connection XML_version="1.2" id="Texas Instruments XDS110 USB Debug Probe_0">
|
||||
<instance XML_version="1.2" href="drivers/tixds510icepick_c.xml" id="drivers" xml="tixds510icepick_c.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds510cs_dap.xml" id="drivers" xml="tixds510cs_dap.xml" xmlpath="drivers"/>
|
||||
<instance XML_version="1.2" href="drivers/tixds510cortexM.xml" id="drivers" xml="tixds510cortexM.xml" xmlpath="drivers"/>
|
||||
<property Type="choicelist" Value="1" id="Power Selection">
|
||||
<choice Name="Probe supplied power" value="1">
|
||||
<property Type="stringfield" Value="3.3" id="Voltage Level"/>
|
||||
</choice>
|
||||
</property>
|
||||
<property Type="choicelist" Value="0" id="JTAG Signal Isolation"/>
|
||||
<property Type="choicelist" Value="4" id="SWD Mode Settings">
|
||||
<choice Name="cJTAG (1149.7) 2-pin advanced modes" value="enable">
|
||||
<property Type="choicelist" Value="1" id="XDS110 Aux Port"/>
|
||||
</choice>
|
||||
</property>
|
||||
<platform XML_version="1.2" id="platform_0">
|
||||
|
||||
@@ -219,53 +219,64 @@ SPICC26XXDMA_Object spiCC26XXDMAObjects[BOOSTXL_CC2650MA_SPICOUNT];
|
||||
|
||||
/* SPI configuration structure, describing which pins are to be used */
|
||||
const SPICC26XXDMA_HWAttrsV1 spiCC26XXDMAHWAttrs[BOOSTXL_CC2650MA_SPICOUNT] = {
|
||||
//
|
||||
{
|
||||
.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_MA_USE_SPI2
|
||||
{
|
||||
.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
|
||||
//
|
||||
.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]
|
||||
//
|
||||
},
|
||||
#ifdef HEADSTAGE_MA_USE_SPI2
|
||||
{
|
||||
.fxnTablePtr = &SPICC26XXDMA_fxnTable,
|
||||
.object = &spiCC26XXDMAObjects[1],
|
||||
.hwAttrs = &spiCC26XXDMAHWAttrs[1]
|
||||
//
|
||||
.fxnTablePtr = &SPICC26XXDMA_fxnTable,
|
||||
.object = &spiCC26XXDMAObjects[1],
|
||||
.hwAttrs = &spiCC26XXDMAHWAttrs[1]
|
||||
//
|
||||
},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
#endif
|
||||
{NULL, NULL, NULL}};
|
||||
/*
|
||||
* ========================== SPI DMA end =====================================
|
||||
*/
|
||||
*/
|
||||
|
||||
/*
|
||||
* ========================== Crypto begin ====================================
|
||||
@@ -503,22 +514,165 @@ const PWM_Config PWM_config[BOOSTXL_CC2650MA_PWMCOUNT + 1] = {
|
||||
*/
|
||||
|
||||
/*
|
||||
* ============================= I2C Begin=====================================
|
||||
*/
|
||||
|
||||
#ifdef ELITE_I2C
|
||||
|
||||
/* Generic I2C instance identifiers */
|
||||
#define Board_I2C CC2650_MA_I2C0
|
||||
/*!
|
||||
* @def CC2650_LAUNCHXL_I2CName
|
||||
* @brief Enum of I2C names on the CC2650 dev board
|
||||
* ============================= ADC begin ======================================
|
||||
*/
|
||||
typedef enum CC2650_MA_I2CName {
|
||||
CC2650_MA_I2C0 = 0,
|
||||
|
||||
CC2650_MA_I2CCOUNT
|
||||
} CC2650_MA_I2CName;
|
||||
#ifdef HEADSTAGE_MA_USE_ADC
|
||||
|
||||
#include <ti/drivers/ADC.h>
|
||||
#include <ti/drivers/adc/ADCCC26XX.h>
|
||||
|
||||
#if defined(__TI_COMPILER_VERSION__)
|
||||
#pragma DATA_SECTION(ADC_config, ".const:ADC_config")
|
||||
#pragma DATA_SECTION(adcCC26xxHWAttrs, ".const:adcCC26xxHWAttrs")
|
||||
#endif
|
||||
|
||||
ADCCC26XX_Object adcCC26xxObjects[BOOSTXL_CC2650MA_ADCCOUNT];
|
||||
|
||||
const ADCCC26XX_HWAttrs adcCC26xxHWAttrs[BOOSTXL_CC2650MA_ADCCOUNT] = {
|
||||
//
|
||||
{
|
||||
//
|
||||
.adcDIO = DIO7,
|
||||
.adcCompBInput = ADC_COMPB_IN_AUXIO7,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = DIO8,
|
||||
.adcCompBInput = ADC_COMPB_IN_AUXIO6,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = DIO9,
|
||||
.adcCompBInput = ADC_COMPB_IN_AUXIO5,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = PIN_UNASSIGNED,
|
||||
.adcCompBInput = ADC_COMPB_IN_AUXIO4,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = PIN_UNASSIGNED,
|
||||
.adcCompBInput = ADC_COMPB_IN_AUXIO3,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = PIN_UNASSIGNED,
|
||||
.adcCompBInput = ADC_COMPB_IN_AUXIO2,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = PIN_UNASSIGNED,
|
||||
.adcCompBInput = ADC_COMPB_IN_AUXIO1,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = PIN_UNASSIGNED,
|
||||
.adcCompBInput = ADC_COMPB_IN_AUXIO0,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_10P9_MS,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = PIN_UNASSIGNED,
|
||||
.adcCompBInput = ADC_COMPB_IN_DCOUPL,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = PIN_UNASSIGNED,
|
||||
.adcCompBInput = ADC_COMPB_IN_VSS,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
},
|
||||
{
|
||||
//
|
||||
.adcDIO = PIN_UNASSIGNED,
|
||||
.adcCompBInput = ADC_COMPB_IN_VDDS,
|
||||
.refSource = ADCCC26XX_FIXED_REFERENCE,
|
||||
.samplingDuration = ADCCC26XX_SAMPLING_DURATION_2P7_US,
|
||||
.inputScalingEnabled = true,
|
||||
.triggerSource = ADCCC26XX_TRIGGER_MANUAL
|
||||
//
|
||||
}
|
||||
//
|
||||
};
|
||||
|
||||
const ADC_Config ADC_config[] = {
|
||||
//
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[0], &adcCC26xxHWAttrs[0]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[1], &adcCC26xxHWAttrs[1]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[2], &adcCC26xxHWAttrs[2]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[3], &adcCC26xxHWAttrs[3]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[4], &adcCC26xxHWAttrs[4]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[5], &adcCC26xxHWAttrs[5]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[6], &adcCC26xxHWAttrs[6]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[7], &adcCC26xxHWAttrs[7]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[8], &adcCC26xxHWAttrs[8]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[9], &adcCC26xxHWAttrs[9]},
|
||||
{&ADCCC26XX_fxnTable, &adcCC26xxObjects[10], &adcCC26xxHWAttrs[10]},
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
#endif // HEADSTAGE_MA_USE_ADC
|
||||
|
||||
/*
|
||||
* ============================= ADC end ======================================
|
||||
*/
|
||||
/*
|
||||
* ============================= I2C Begin=====================================
|
||||
*/
|
||||
|
||||
#ifdef HEADSTAGE_LED_USE_I2C
|
||||
|
||||
#define Board_I2C0_SCL0 IOID_10
|
||||
#define Board_I2C0_SDA0 IOID_11
|
||||
|
||||
/* Place into subsections to allow the TI linker to remove items properly */
|
||||
#if defined(__TI_COMPILER_VERSION__)
|
||||
@@ -530,10 +684,10 @@ typedef enum CC2650_MA_I2CName {
|
||||
#include <ti/drivers/i2c/I2CCC26XX.h>
|
||||
|
||||
/* I2C objects */
|
||||
I2CCC26XX_Object i2cCC26xxObjects[CC2650_MA_I2CCOUNT];
|
||||
I2CCC26XX_Object i2cCC26xxObjects[BOOSTXL_CC2650MA_I2CCOUNT];
|
||||
|
||||
/* I2C configuration structure, describing which pins are to be used */
|
||||
const I2CCC26XX_HWAttrsV1 i2cCC26xxHWAttrs[CC2650_MA_I2CCOUNT] = {
|
||||
const I2CCC26XX_HWAttrsV1 i2cCC26xxHWAttrs[BOOSTXL_CC2650MA_I2CCOUNT] = {
|
||||
{
|
||||
.baseAddr = I2C0_BASE,
|
||||
.powerMngrId = PowerCC26XX_PERIPH_I2C0,
|
||||
@@ -554,9 +708,11 @@ const I2C_Config I2C_config[] = {
|
||||
},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
#endif
|
||||
/*
|
||||
* ========================== I2C end =========================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* ============================= Watchdog begin =====================================
|
||||
*/
|
||||
|
||||
@@ -137,7 +137,7 @@ extern const PIN_Config BoardGpioInitTable[];
|
||||
#define Board_PWMPIN4 PIN_UNASSIGNED
|
||||
#define Board_PWMPIN5 PIN_UNASSIGNED
|
||||
#define Board_PWMPIN6 PIN_UNASSIGNED
|
||||
#define Board_PWMPIN7 PIN_UNASSIGNED
|
||||
#define Board_PWMPIN7 IOID_11
|
||||
|
||||
/** ============================================================================
|
||||
* Instance identifiers
|
||||
|
||||
@@ -100,7 +100,6 @@ if (typeof NO_ROM == 'undefined' || (typeof NO_ROM != 'undefined' && NO_ROM == 0
|
||||
|
||||
/* ================ Clock configuration ================ */
|
||||
var Clock = xdc.useModule('ti.sysbios.knl.Clock');
|
||||
var Timestamp = xdc.useModule('xdc.runtime.Timestamp');
|
||||
/*
|
||||
* When using Power and calibrateRCOSC is set to true, this should be set to 10.
|
||||
* The timer used by the Clock module supports TickMode_DYNAMIC. This enables us
|
||||
@@ -113,7 +112,6 @@ var Timestamp = xdc.useModule('xdc.runtime.Timestamp');
|
||||
Clock.tickPeriod = 10;
|
||||
Clock.swiPriority = 5;
|
||||
|
||||
Timestamp.SupportProxy = xdc.useModule('ti.sysbios.family.arm.cc26xx.TimestampProvider');
|
||||
|
||||
/* ================ Types configuration ================ */
|
||||
var Types = xdc.useModule('xdc.runtime.Types');
|
||||
|
||||
@@ -368,9 +368,6 @@ static void HostTestApp_processAttEvent(gattMsgEvent_t *message) {
|
||||
} else if (method == ATT_HANDLE_VALUE_NOTI) {
|
||||
attHandleValueNoti_t *att_notify = (attHandleValueNoti_t *)(&message->msg);
|
||||
master_handle_notify(att_notify->len, att_notify->pValue);
|
||||
} else if (method == ATT_HANDLE_VALUE_IND) {
|
||||
attHandleValueInd_t *att_indicate = (attHandleValueInd_t *)(&message->msg);
|
||||
master_handle_notify(att_indicate->len, att_indicate->pValue);
|
||||
}
|
||||
|
||||
// Free message. Needed only for ATT Protocol messages
|
||||
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
@startuml
|
||||
|
||||
|
||||
start
|
||||
|
||||
while (negedge chip select)
|
||||
if (rxbuf is wrong) then (yes)
|
||||
:modify data until it is correct;
|
||||
else
|
||||
:pass;
|
||||
endif
|
||||
partition headstage_notify_append_data {
|
||||
if (buf offset == INIT) then (yes)
|
||||
:reset timestamp;
|
||||
endif
|
||||
if (buf offset == BUFF_SIZE)
|
||||
:set time delta;
|
||||
endif
|
||||
:append data & return index;
|
||||
}
|
||||
if (buf offset == BUFF_SIZE)
|
||||
:headstage_notify_send(0.676ms);
|
||||
endif
|
||||
:headstage_spi_lsk_transaction (0.528ms);
|
||||
endwhile
|
||||
stop
|
||||
|
||||
@enduml
|
||||
+7
-4
@@ -242,12 +242,13 @@ extern ICall_Semaphore semaphore;
|
||||
* make task sleep in certain [ms].
|
||||
* count with cpu tick.
|
||||
*/
|
||||
#define headstage_cpu_delay_ms(ms) CPUdelay(ms * 16000)
|
||||
#define headstage_cpu_delay_ms(ms) CPUdelay((ms) * 16000)
|
||||
|
||||
/**
|
||||
* make task sleep in certain [us].
|
||||
* count with cpu tick.
|
||||
*/
|
||||
#define headstage_cpu_delay_us(us) CPUdelay(us * 16)
|
||||
#define headstage_cpu_delay_us(us) CPUdelay((us) * 16)
|
||||
|
||||
/*======================================
|
||||
==== abstract function declaration ====
|
||||
@@ -282,10 +283,12 @@ static void headstage_update_vis_instruction(uint8_t vis_oper);
|
||||
*/
|
||||
static uint8_t CHIP_ID = 0;
|
||||
|
||||
#define CONNECT_HANDLE_UNCONNECTED 0xFFFF
|
||||
|
||||
/**
|
||||
* connection handle. updated by system.
|
||||
*/
|
||||
static uint16_t CONNECT_HANDLE = 0;
|
||||
static uint16_t CONNECT_HANDLE = CONNECT_HANDLE_UNCONNECTED;
|
||||
|
||||
/*====================
|
||||
==== event table ====
|
||||
@@ -311,7 +314,7 @@ typedef struct {
|
||||
==== device implement implement header ====
|
||||
=========================================*/
|
||||
|
||||
#include "headstage_zm.h"
|
||||
#include "headstage_uni.h"
|
||||
|
||||
/*======================
|
||||
==== main function ====
|
||||
|
||||
+2
-3
@@ -1,12 +1,11 @@
|
||||
/* 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
|
||||
|
||||
#include "headstage_led.h"
|
||||
|
||||
// clang-format off
|
||||
#define CIS_LED_DISABLE 0x00
|
||||
#define CIS_LED_ENABLE 0x01
|
||||
|
||||
+9
-7
@@ -30,13 +30,15 @@ static void headstage_clock_callback(UArg arg) {
|
||||
|
||||
// XXX function not tested
|
||||
// period in mini second
|
||||
#define headstage_clock_open(_period) \
|
||||
do { \
|
||||
Clock_Params param; \
|
||||
Clock_Params_init(¶m); \
|
||||
param.period = 48000*(_period); \
|
||||
param.startFlag = false; \
|
||||
clock_handle = Clock_create(headstage_clock_callback, 1, ¶m, NULL); \
|
||||
#define headstage_clock_open(p) \
|
||||
do { \
|
||||
Clock_Params param; \
|
||||
Clock_Params_init(¶m); \
|
||||
param.period = 0; \
|
||||
param.startFlag = false; \
|
||||
clock_handle = Clock_create(headstage_clock_callback, 0, ¶m, NULL); \
|
||||
uint32_t _period = (p)*1000 / Clock_tickPeriod; \
|
||||
Clock_setPeriod(clock_handle, _period); \
|
||||
} while (0)
|
||||
|
||||
#define headstage_clock_set_frequency(frequency) \
|
||||
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
/* Copyright (c) 2019. BioPro. Scientific.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Headstage indicate utility
|
||||
==========================
|
||||
|
||||
reference code :
|
||||
root:
|
||||
glucose.c
|
||||
glucserive.c
|
||||
|
||||
code need modifying:
|
||||
headstage_indicate.h
|
||||
simple_gatt_profile.c : WriteAtterCB -> add case "indication" to support indicate
|
||||
|
||||
sipmle_peripheral.c : find another service callback
|
||||
|
||||
use this website to construct software structure : http://plantuml.com/zh/
|
||||
|
||||
reference document:
|
||||
bluetooth Core5.1 Vol 3, Part F, Section 3.4.6
|
||||
The Prepare Write Request is used to request the server to prepare to write the
|
||||
value of an attribute. The server will respond to this request with a Prepare Write
|
||||
Response, so that the client can verify that the value was received correctly.
|
||||
|
||||
host-test can ask simple-peripheral to prepare the queue to write attribute
|
||||
|
||||
5.3.4.3 Queued Writes
|
||||
Prepare Write commands allows a GATT server to send more payload data by queuing up multiple write
|
||||
requests. The default queue size is 5. With a default MTU of 23 and payload of 18 bytes, up to 90 bytes of
|
||||
payload can be sent. Refer to Core_v4.2 specification (Vol 3, Part F, Section 3.4.6) for more information
|
||||
on queued writes.
|
||||
Adjust the Prepare Write queue with GATTServApp_SetParameter with parameter
|
||||
GATT_PARAM_NUM_PREPARE_WRITES. There is no specified limit, but it is bounded by the available
|
||||
HEAPMGR space. Refer to the API definition in gattservapp.h.
|
||||
|
||||
GATT_PARAM_NUM_PREPARE_WRITES
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HEADSTAGE_INDICATE_H
|
||||
#define HEADSTAGE_INDICATE_H
|
||||
|
||||
#include <xdc/runtime/Timestamp.h>
|
||||
|
||||
#define headstage_time_stamp() Timestamp_get32()
|
||||
|
||||
/*==========================
|
||||
==== indicate function ====
|
||||
=========================*/
|
||||
|
||||
/*
|
||||
* send indicate
|
||||
* connHandle -> where to assign this parameter
|
||||
*/
|
||||
|
||||
static bStatus_t headstage_indicate() {
|
||||
uint16_t buffer_size = BLE_NOT_BUFF_SIZE;
|
||||
uint8_t *value = (uint8_t *)GATT_bm_alloc(CONNECT_HANDLE, ATT_HANDLE_VALUE_IND, GATT_MAX_MTU,&buffer_size);
|
||||
|
||||
if (value != NULL) {
|
||||
memcpy(value, headstage_notify_buffer, buffer_size);
|
||||
}
|
||||
|
||||
attHandleValueInd_t indicate = {
|
||||
// clang-format off
|
||||
.handle = 0x1E,
|
||||
.len = buffer_size,
|
||||
.pValue = value
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
if (GATT_Indication(CONNECT_HANDLE, &indicate, 0, ICall_getEntityId()) != SUCCESS) {
|
||||
GATT_bm_free((gattMsg_t *)&indicate, ATT_HANDLE_VALUE_IND);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
+28
-14
@@ -125,7 +125,6 @@ static uint8_t headstage_led_set_color(uint16_t *ins_buf, uint8_t repeat, uint8_
|
||||
/*============================
|
||||
==== LED implement (SPI) ====
|
||||
===========================*/
|
||||
#define HEADSTAGE_LED_USE_SPI
|
||||
|
||||
#ifdef HEADSTAGE_LED_USE_SPI
|
||||
|
||||
@@ -192,33 +191,48 @@ static void headstage_led_color(uint8_t color) {
|
||||
==== LED implement (GPIO) ====
|
||||
============================*/
|
||||
|
||||
#ifdef BOOSTXL_CC2650MA
|
||||
#define HEADSTAGE_LED_USE_GPIO
|
||||
#endif
|
||||
|
||||
#ifdef HEADSTAGE_LED_USE_GPIO
|
||||
#include "headstage_pin.h"
|
||||
/*
|
||||
every 400us to transmit spi data
|
||||
*/
|
||||
|
||||
#define SPI_LED_BUFF_SIZE 20
|
||||
#define SPI_LED_REPEAT 2
|
||||
|
||||
static uint16_t headstage_spi_led_txbuf[SPI_LED_BUFF_SIZE];
|
||||
|
||||
#define LED_GPIO_DELAY 16 * 400 // 2500hz
|
||||
|
||||
/**
|
||||
* every 400us to transmit spi data
|
||||
*/
|
||||
static void headstage_led_spi_transmit() {
|
||||
for (int8_t i = 0; i < 8; i++) {
|
||||
uint16_t d = headstage_spi_led_txbuf[i];
|
||||
for (int8_t j = 15; j >= 0; j--) {
|
||||
int16_t v = (d & (1 << j)); // why check > 0 or not
|
||||
bool SET_LED = (v > 0) ? 1 : 0;
|
||||
bool high = ((d & (1 << j)) > 0) ? 1 : 0;
|
||||
|
||||
headstage_pin_output(PIN_LED_CLK, 1);
|
||||
CPUdelay(16 * 400); // 2500hz
|
||||
headstage_pin_output(PIN_LED_OUT, SET_LED);
|
||||
CPUdelay(LED_GPIO_DELAY); // 2500hz
|
||||
|
||||
headstage_pin_output(PIN_LED_OUT, high);
|
||||
headstage_pin_output(PIN_LED_CLK, 0);
|
||||
CPUdelay(16 * 400); // 2500hz
|
||||
CPUdelay(LED_GPIO_DELAY); // 2500hz
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void headstage_led_spi_color(uint8_t color) {
|
||||
static void headstage_led_open() {}
|
||||
|
||||
static void headstage_led_close() {}
|
||||
|
||||
static void headstage_led_send(LEDParameter *led) {
|
||||
headstage_led_set_buffer(headstage_spi_led_txbuf, SPI_LED_REPEAT, led);
|
||||
|
||||
headstage_led_spi_transmit();
|
||||
}
|
||||
|
||||
static void headstage_led_color(uint8_t color) {
|
||||
headstage_led_set_color(headstage_spi_led_txbuf, SPI_LED_REPEAT, color);
|
||||
|
||||
headstage_led_spi_transmit();
|
||||
}
|
||||
|
||||
|
||||
+19
-3
@@ -31,7 +31,8 @@ optional implement
|
||||
|
||||
#include <xdc/runtime/Timestamp.h>
|
||||
|
||||
#define headstage_time_stamp_us() (Timestamp_get32() / 2)
|
||||
#define headstage_time_stamp() Timestamp_get32()
|
||||
#define headstage_time_stamp_ms() (Timestamp_get32() / 32)
|
||||
|
||||
/*========================
|
||||
==== notify function ====
|
||||
@@ -51,7 +52,7 @@ static void headstage_notify_send() {
|
||||
if (value != NULL) {
|
||||
memcpy(value, headstage_notify_buffer, buffer_size);
|
||||
|
||||
attHandleValueNoti_t notify = {
|
||||
attHandleValueNoti_t notify =
|
||||
// clang-format off
|
||||
.handle = 0x1E,
|
||||
.len = buffer_size,
|
||||
@@ -66,9 +67,24 @@ static void headstage_notify_send() {
|
||||
}
|
||||
|
||||
#else
|
||||
SimpleProfile_SetParameter(BLE_NOT_BUFF_CHAR, BLE_NOT_BUFF_SIZE, headstage_notify_buffer) ;
|
||||
|
||||
SimpleProfile_SetParameter(BLE_NOT_BUFF_CHAR, BLE_NOT_BUFF_SIZE, headstage_notify_buffer);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(HEADSTAGE_TNI_H)
|
||||
#include "tni/headstage_notify.h"
|
||||
#elif defined(HEADSTAGE_UNI_H)
|
||||
#include "tni/headstage_notify.h"
|
||||
#elif defined(HEADSTAGE_ZM_H)
|
||||
#include "zm/headstage_notify.h"
|
||||
#elif defined(HEADSTAGE_STI_H)
|
||||
#include "sti/headstage_notify.h"
|
||||
#else
|
||||
|
||||
#error "headstage_notify"
|
||||
|
||||
#endif
|
||||
|
||||
#endif // HEADSTAGE_NOTIFY_H
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/* Copyright (c) 2019. BioPro. Scientific.
|
||||
*/
|
||||
|
||||
#ifndef HEADSTAGE_NOTIFY_GENERAL_H
|
||||
#define HEADSTAGE_NOTIFY_GENERAL_H
|
||||
|
||||
#ifndef HEADSTAGE_NOTIFY_H
|
||||
#error "headstage/headstage_notify.h not included"
|
||||
#endif
|
||||
|
||||
static uint32_t not_buf_offset = 0;
|
||||
static uint32_t not_time_stamp = 0;
|
||||
|
||||
static void headstage_notify_set_timestamp() {
|
||||
not_time_stamp = headstage_time_stamp();
|
||||
|
||||
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_length) {
|
||||
headstage_notify_buffer[0] = CHIP_ID;
|
||||
headstage_notify_buffer[1] = data_length;
|
||||
|
||||
not_buf_offset = 0;
|
||||
}
|
||||
|
||||
#endif // HEADSTAGE_NOTIFY_GENERAL_H
|
||||
+931
-151
File diff suppressed because it is too large
Load Diff
-1
@@ -36,7 +36,6 @@ Real instruction format
|
||||
#include "headstage_gptimer.h"
|
||||
#include "headstage_notify.h"
|
||||
#include "headstage_pin.h"
|
||||
#include "tni/headstage_notify.h"
|
||||
#include "tni/headstage_spi.h"
|
||||
|
||||
/*=================================
|
||||
|
||||
+211
-99
@@ -7,6 +7,16 @@
|
||||
#ifndef HEADSTAGE_UNI_H
|
||||
#define HEADSTAGE_UNI_H
|
||||
|
||||
/*============================
|
||||
==== product information ====
|
||||
===========================*/
|
||||
|
||||
#define DEVICE_NAME "Neulive-v0.3"
|
||||
#define MAJOR_PRODUCT_NUMBER 1
|
||||
#define MINOR_PRODUCT_NUMBER 1
|
||||
#define MAJOR_VERSION_NUMBER 0
|
||||
#define MINOR_VERSION_NUMBER 2
|
||||
|
||||
// TODO low frequency mode
|
||||
// TODO battery record
|
||||
// TODO watchdog function need implementing
|
||||
@@ -15,6 +25,15 @@
|
||||
/*=================
|
||||
==== constant ====
|
||||
=================*/
|
||||
|
||||
// data rate
|
||||
// clang-format off
|
||||
#define UMC_LSK_FREQ 5000 // 500 khz
|
||||
#define UMC_ASK_FREQ 1000 // 100 khz
|
||||
#define UMC_SYS_CLK 100000 // target is 8Mhz
|
||||
#define UMC_POLY_R_CLK 1000 // poly-R switching clock
|
||||
// clang-format on
|
||||
|
||||
// data transmit format 9'b PREAMBLE + 4'b HEADER + 10'bit DATA
|
||||
// clang-format off
|
||||
#define UMC_PREAMBLE 0b011000001
|
||||
@@ -25,20 +44,18 @@
|
||||
/*================
|
||||
==== include ====
|
||||
================*/
|
||||
#include "time.h"
|
||||
|
||||
#include "population.h"
|
||||
#include "headstage_arm.h"
|
||||
#include "headstage_notify.h"
|
||||
#include "headstage_debug.h"
|
||||
#include "headstage_pin.h"
|
||||
#include "headstage_led.h"
|
||||
#include "headstage_arm.h"
|
||||
#include "headstage_watchdog.h"
|
||||
#include "headstage_notify.h"
|
||||
#include "tni/headstage_notify.h"
|
||||
#include "uni/headstage_spi.h"
|
||||
#include "uni/headstage_pwm.h"
|
||||
#include "uni/headstage_adc.h"
|
||||
#include "uni/uni1.2_parameter.h"
|
||||
#include "headstage_indicate.h"
|
||||
|
||||
/*===================================
|
||||
==== instruction building macro ====
|
||||
@@ -107,22 +124,16 @@
|
||||
==== constant ====
|
||||
=================*/
|
||||
|
||||
// data rate
|
||||
// clang-format off
|
||||
#define UMC_LSK_FREQ 100000 // 500 khz
|
||||
#define UMC_ASK_FREQ 20000 // 100 khz
|
||||
#define UMC_SYS_CLK 2000000 // target is 8Mhz
|
||||
#define UMC_POLY_R_CLK 1000 // poly-R switching clock
|
||||
|
||||
|
||||
// Neulive instruction macro
|
||||
// UNI 1.2 instruction macro
|
||||
#define UMC_HAND_SHAKE_SEND 0b0011000011
|
||||
#define UMC_HAND_SHAKE_RECV 0b01010011000110000000110001100000
|
||||
#define UMC_MODE_LSK_OUT 0b101001
|
||||
#define UMC_CALIB_DONE 0b1010 // UMC_CALIB_DONE + UMC_MODE_LSK_OUT -> leave initial state and set "CHIP ID"
|
||||
#define UMC_CONFIG_DONE 0b0100 // UMC_CONFIG_DONE + 6'bxxxxxx -> EXIT config state
|
||||
#define UMC_CONFIG_DONE 0b0100 // UMC_CONFIG_DONE + 6'bxxxxxx -> EXIT config state
|
||||
#define UMC_IRQ 0b1110
|
||||
#define UMC_IRQ_CODE 0b001001 // UMC_IRQ + UMC_IRQ_CODE + CHIP ID -> when we want to go back to configure data.
|
||||
#define UMC_IRQ_CODE 0b001001 // UMC_IRQ + UMC_IRQ_CODE + CHIP ID -> when we want to go back to configure data.
|
||||
#define UMC_GOLDEN_KEY 0b01011010010110000010100101100000 //this is important to leave wait trigger state.
|
||||
|
||||
// we need to check transfer data meets or not
|
||||
@@ -134,9 +145,10 @@
|
||||
|
||||
#define RIS_DEFAULT 0x00
|
||||
#define RIS_SET_PARA 0x20
|
||||
#define RIS_RECONFIG 0x40
|
||||
#define RIS_RESET_AMP 0x60
|
||||
#define RIS_DIR 0xA0
|
||||
#define RIS_UMC_TRIG 0xC0
|
||||
#define RIS_STI 0xF0
|
||||
|
||||
#define STI_MODE_DISABLE 0
|
||||
#define STI_MODE_POS 1
|
||||
@@ -179,7 +191,8 @@
|
||||
|
||||
#define REC_CHANNEL_COUNT 16
|
||||
|
||||
static uint16_t sti_waveform_table[5] = {
|
||||
static uint16_t sti_waveform_table[6] = {
|
||||
{0b000000},
|
||||
{0b000011}, // positive
|
||||
{0b001100}, // negative
|
||||
{0b110000}, // p 2 s
|
||||
@@ -191,9 +204,9 @@ static uint16_t sti_waveform_table[5] = {
|
||||
// TODO when we choose trigger mode , but we can't transmit any trigger instruction.
|
||||
static uint16_t sti_mode_table[4] = {
|
||||
{0b001100}, // disable stimulation, it would there will be no trigger to be set
|
||||
{0b110000}, // continuous mode
|
||||
{0b001100}, // trigger mode
|
||||
{0b000011}, // limited mode
|
||||
{0b110000} // continuous mode
|
||||
{0b000011} // limited mode
|
||||
};
|
||||
|
||||
static uint16_t amp_band_table[8] = { //
|
||||
@@ -210,6 +223,97 @@ static uint16_t fast_settle_table[2] = { //
|
||||
{0b000000},
|
||||
{0b000001}};
|
||||
|
||||
// XXX not used
|
||||
static uint16_t sti_channel_table[4] = {
|
||||
{0b000010}, // 3
|
||||
{0b001000}, // 4
|
||||
{0b001100}, // 5
|
||||
{0b010000} // 6
|
||||
};
|
||||
|
||||
/*
|
||||
* we need to use this parameter
|
||||
*/
|
||||
#ifdef UNI_1P2
|
||||
static uint16_t reverse_channel[16] = {{0x0A}, // 1
|
||||
{0x0B},
|
||||
{0x00},
|
||||
{0x01},
|
||||
{0x02},
|
||||
{0x07},
|
||||
{0x06},
|
||||
{0x03},
|
||||
{0x05},
|
||||
{0x04},
|
||||
{0x08},
|
||||
{0xff},
|
||||
{0x0c},
|
||||
{0x09},
|
||||
{0xff},
|
||||
{0xff}};
|
||||
#else
|
||||
static uint16_t reverse_channel[16] = {{0x0A}, // 1
|
||||
{0x00},
|
||||
{0x01},
|
||||
{0x02},
|
||||
{0x03},
|
||||
{0x08},
|
||||
{0x07},
|
||||
{0x06},
|
||||
{0x05},
|
||||
{0x04},
|
||||
{0x09},
|
||||
{0x0B},
|
||||
{0xFF},
|
||||
{0xFF},
|
||||
{0xff},
|
||||
{0xff}};
|
||||
#endif
|
||||
|
||||
/* we can change amp channel from one to eight
|
||||
* the user will choose these channel from this table
|
||||
*/
|
||||
|
||||
#ifdef UNI_1p2
|
||||
static uint16_t amp_channel_table[13] = { //
|
||||
{0x03},
|
||||
{0x04},
|
||||
{0x05},
|
||||
{0x08},
|
||||
{0x0A},
|
||||
{0x09},
|
||||
{0x07},
|
||||
{0x06},
|
||||
{0x0B},
|
||||
{0x0E},
|
||||
{0x01},
|
||||
{0x02},
|
||||
{0x0D}};
|
||||
#else
|
||||
static uint16_t amp_channel_table[12] = { //
|
||||
{0x02},
|
||||
{0x03},
|
||||
{0x04},
|
||||
{0x05},
|
||||
{0x0A},
|
||||
{0x09},
|
||||
{0x08},
|
||||
{0x07},
|
||||
{0x06},
|
||||
{0x0b},
|
||||
{0x01},
|
||||
{0x0C}};
|
||||
#endif
|
||||
|
||||
static uint16_t amp_gain_table[] = {
|
||||
0b100011, // 2
|
||||
0b101100, // 5
|
||||
0b101001, // 10
|
||||
0b000011, // 200
|
||||
0b001100, // 500
|
||||
0b001001, // 1000
|
||||
};
|
||||
|
||||
/**
|
||||
* pulse width, with unit us
|
||||
*/
|
||||
@@ -451,7 +555,6 @@ static void headstage_umc_state_transfer_lsk();
|
||||
// clang-format off
|
||||
#define EVT_UMC_ASK 0x0001
|
||||
#define EVT_UMC_LSK 0x0002
|
||||
#define EVT_UMC_STI 0x0004
|
||||
// clang-format on
|
||||
|
||||
static void headstage_uni_event() {
|
||||
@@ -465,12 +568,6 @@ static void headstage_uni_event() {
|
||||
headstage_umc_state_transfer_lsk();
|
||||
}
|
||||
|
||||
if (flag_mask(EVT_UMC_STI)) {
|
||||
flag_disable(EVT_UMC_STI);
|
||||
headstage_state = UMC_STATE_WAIT_TRIGGER;
|
||||
headstage_umc_state_transfer_lsk();
|
||||
}
|
||||
|
||||
if (EVENT_MASK == 0) {
|
||||
// fast return
|
||||
}
|
||||
@@ -514,15 +611,17 @@ static void headstage_init() {
|
||||
headstage_pin_open();
|
||||
headstage_spi_open();
|
||||
headstage_pwm_open();
|
||||
headstage_led_spi_color(COLOR_GREEN);
|
||||
|
||||
// headstage_i2c_open();
|
||||
|
||||
// headstage_watchdog_open();
|
||||
// if(headstage_watchdog_handle == NULL)
|
||||
// {
|
||||
// headstage_led_spi_color(COLOR_RED);
|
||||
// headstage_led_color(COLOR_RED);
|
||||
// }
|
||||
|
||||
headstage_pin_output(PIN_RESET, 1); // initialize DBS chip
|
||||
headstage_pin_output(PIN_STI_SEL, 1); // chip select is ok
|
||||
headstage_pin_output(PIN_STI_SEL, 0); // chip select is ok
|
||||
headstage_pin_output(PIN_VGRP, 1); //
|
||||
headstage_pin_output(PIN_FASTSET, 0); //
|
||||
}
|
||||
@@ -533,7 +632,7 @@ static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t* instructi
|
||||
uint8_t amp_lbf = (instruction[0] & 0b00000111);
|
||||
uint8_t chopper = (instruction[1] & 0b00100000) >> 5;
|
||||
uint8_t fast_settle = (instruction[1] & 0b00010000) >> 4;
|
||||
uint8_t sti_waveform = (instruction[1] & 0b00001110) >> 1; // define pos to neg or neg to pos
|
||||
uint8_t sti_waveform = (instruction[1] & 0b00001110) >> 1;
|
||||
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;
|
||||
@@ -547,8 +646,8 @@ static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t* instructi
|
||||
INSTRUCTION.chopper = chopper;
|
||||
INSTRUCTION.fast_settle = fast_settle;
|
||||
INSTRUCTION.sti_volt = sti_volt;
|
||||
INSTRUCTION.sti_channel_pmos = sti_channel_table[sti_chp];
|
||||
INSTRUCTION.sti_channel_nmos = sti_channel_table[sti_chn];
|
||||
INSTRUCTION.sti_channel_pmos = sti_chp;
|
||||
INSTRUCTION.sti_channel_nmos = sti_chn;
|
||||
break;
|
||||
}
|
||||
case RIS_SET_PARA: {
|
||||
@@ -578,18 +677,18 @@ static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t* instructi
|
||||
// todo: check multichannel selection is correct or not
|
||||
case RIS_DEFAULT: {
|
||||
INSTRUCTION.channel_table[amp_channel_table[0] - 1] = TRUE;
|
||||
INSTRUCTION.amp_gain = 5; // x1000
|
||||
INSTRUCTION.pulse_width = 0; // 40us
|
||||
INSTRUCTION.sti_times = 0; // repeat stimulation x1
|
||||
INSTRUCTION.mode = 1; // trigger mode
|
||||
INSTRUCTION.sti_freq = 3; // 30hz
|
||||
INSTRUCTION.sti_waveform = 1; // positive
|
||||
INSTRUCTION.chopper = 0; // turn off chopper
|
||||
INSTRUCTION.fast_settle = 0; // turn on fast settling
|
||||
INSTRUCTION.sti_volt = 0; // 2Volt
|
||||
INSTRUCTION.sti_channel_nmos = 0; // sti nch = ch2 means sti turn off
|
||||
INSTRUCTION.sti_channel_pmos = 1; // sti pch = ch1 means sti turn off
|
||||
INSTRUCTION.amp_low_band_freq = 0; // the maximum
|
||||
INSTRUCTION.amp_gain = 5; // x1000
|
||||
INSTRUCTION.pulse_width = 0; // 40us
|
||||
INSTRUCTION.sti_times = 0; // repeat stimulation x1
|
||||
INSTRUCTION.mode = 1; // trigger mode
|
||||
INSTRUCTION.sti_freq = 3; // 30hz
|
||||
INSTRUCTION.sti_waveform = 1; // positive
|
||||
INSTRUCTION.chopper = 0; // turn off chopper
|
||||
INSTRUCTION.fast_settle = 0; // turn on fast settling
|
||||
INSTRUCTION.sti_volt = 0; // 2Volt
|
||||
INSTRUCTION.sti_channel_nmos = 15; // sti nch = ch2 means sti turn off
|
||||
INSTRUCTION.sti_channel_pmos = 0; // sti pch = ch1 means sti turn off
|
||||
INSTRUCTION.amp_low_band_freq = 0; // the maximum
|
||||
|
||||
// this for-loop is used for setting the amplifier channel
|
||||
// for (unsigned int i = 0; i < REC_CHANNEL_COUNT; i++) {
|
||||
@@ -597,13 +696,13 @@ static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t* instructi
|
||||
// }
|
||||
break;
|
||||
}
|
||||
case RIS_RECONFIG:
|
||||
// state_oper = EVT_STATE_CHANGE_REV;
|
||||
break;
|
||||
|
||||
case RIS_UMC_TRIG:
|
||||
tx_put_u32(0, build_configure_instruction(UMC_TRIG, UMC_STIMULUS));
|
||||
flag_notify(EVT_UMC_STI);
|
||||
/*
|
||||
load
|
||||
*/
|
||||
case RIS_STI:
|
||||
// tx_put_u32(0, build_configure_instruction(0b1011, 0b000011));
|
||||
// headstage_spi_ask_transaction(4);
|
||||
break;
|
||||
|
||||
case RIS_RESET_AMP:
|
||||
@@ -637,7 +736,7 @@ static void headstage_update_vis_instruction(uint8_t vis_oper) {
|
||||
headstage_pwm_start(headstage_poly_r_pwm_handle);
|
||||
UMC_STATE.config_type = CONFIG_AMP_MUX;
|
||||
UMC_STATE.reset_flag = 0;
|
||||
headstage_led_spi_color(COLOR_BLUE);
|
||||
headstage_led_color(COLOR_BLUE);
|
||||
flag_notify(EVT_UMC_LSK);
|
||||
}
|
||||
|
||||
@@ -667,9 +766,6 @@ static void headstage_update_vis_instruction(uint8_t vis_oper) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* todo: need to define some procedure to detect this device status
|
||||
*/
|
||||
static uint8_t headstage_debug_instruction(uint8_t* ins_buf) {
|
||||
return 0;
|
||||
}
|
||||
@@ -679,56 +775,56 @@ static uint8_t headstage_debug_instruction(uint8_t* ins_buf) {
|
||||
=====================*/
|
||||
|
||||
static void headstage_uni_test_data_append_notify_buffer(uint8_t* dat_buf) {
|
||||
uint8_t channel = 0;
|
||||
dat_buf[0] = dat_buf[0];
|
||||
dat_buf[1] = (dat_buf[1] + 1) & 0xfc;
|
||||
headstage_notify_append_data(channel, dat_buf);
|
||||
uint8_t channel = 0;
|
||||
uint16_t data_value = (((uint16_t)dat_buf[0] & 0x0F) << 6) | ((dat_buf[1] & 0xFC) >> 2);
|
||||
|
||||
headstage_notify_append_data(channel, &data_value);
|
||||
|
||||
// always send notify no matter buffer full or not
|
||||
headstage_notify_flip_buffer();
|
||||
headstage_notify_send();
|
||||
}
|
||||
|
||||
// implement this function to detect
|
||||
static void headstage_uni_delay() {
|
||||
for (uint16_t i = 0; i < 1023; i++)
|
||||
;
|
||||
}
|
||||
|
||||
// todo: check data length extension with this function -> this function should be
|
||||
static void headstage_uni_umc_data_append_notify_buffer(uint8_t* dat_buf) {
|
||||
// check LSK data preamble ( 0b01100_0001 ) 58(01011000) 2c(00101100)
|
||||
// sometimes we lose the first bit , it means we only receive
|
||||
// 0110_0000_1010_1xxx_xxxx_xxxX_XXXX_XXXX and
|
||||
// 1100_0001_0101_xxxx_xxxx_xxXX_XXXX_XXXX
|
||||
if (((spi_rxbuf[0] & 0xC1) != 0xC1) && (spi_rxbuf[0] != 0x00)) {
|
||||
headstage_uni_delay();
|
||||
headstage_led_spi_color(COLOR_CYAN);
|
||||
} else {
|
||||
if ((dat_buf[1] & 0x28) == 0x28) {
|
||||
dat_buf[0] = (dat_buf[0] << 1) | ((dat_buf[1] >> 7) & 0x01);
|
||||
dat_buf[1] = (dat_buf[1] << 1) | ((dat_buf[2] >> 7) & 0x01);
|
||||
dat_buf[2] = (dat_buf[2] << 1) | ((dat_buf[3] >> 7) & 0x01);
|
||||
}
|
||||
|
||||
uint8_t channel;
|
||||
|
||||
if ((INSTRUCTION.enable_channel_number == 1) || (dat_buf[0] == 0xc1)) {
|
||||
channel = reverse_channel[INSTRUCTION.last_enable_channel];
|
||||
} else {
|
||||
uint8_t channel_pointer = (INSTRUCTION.channel_pointer + 1) % INSTRUCTION.last_enable_channel;
|
||||
INSTRUCTION.channel_pointer = channel_pointer;
|
||||
channel = reverse_channel[INSTRUCTION.channel_mux[channel_pointer]];
|
||||
}
|
||||
// uint16_t data_value = (uint16_t)(((dat_buf[1] & 0x0F) << 6) | ((dat_buf[2] & 0xFC) >> 2));
|
||||
uint8_t data_size = headstage_notify_append_data(channel, dat_buf);
|
||||
|
||||
if (data_size >= BLE_NOT_BUFF_SIZE) {
|
||||
headstage_notify_send();
|
||||
headstage_notify_flip_buffer();
|
||||
}
|
||||
if ((dat_buf[1] & 0x28) == 0x28) {
|
||||
dat_buf[0] = (dat_buf[0] << 1) | ((dat_buf[1] >> 7) & 0x01);
|
||||
dat_buf[1] = (dat_buf[1] << 1) | ((dat_buf[2] >> 7) & 0x01);
|
||||
dat_buf[2] = (dat_buf[2] << 1) | ((dat_buf[3] >> 7) & 0x01);
|
||||
}
|
||||
|
||||
uint8_t channel;
|
||||
|
||||
if (INSTRUCTION.enable_channel_number == 1) {
|
||||
channel = reverse_channel[INSTRUCTION.last_enable_channel];
|
||||
} else if (dat_buf[0] == 0xc1) {
|
||||
channel = reverse_channel[INSTRUCTION.last_enable_channel];
|
||||
} else {
|
||||
uint8_t channel_pointer = (INSTRUCTION.channel_pointer + 1) % INSTRUCTION.last_enable_channel;
|
||||
INSTRUCTION.channel_pointer = channel_pointer;
|
||||
channel = reverse_channel[INSTRUCTION.channel_mux[channel_pointer]];
|
||||
}
|
||||
|
||||
// uint16_t data_value = (uint16_t)(((dat_buf[1] & 0x0F) << 6) | ((dat_buf[2] & 0xFC) >> 2));
|
||||
uint8_t data_size = headstage_notify_append_data(channel, dat_buf);
|
||||
|
||||
if (data_size >= BLE_NOT_BUFF_SIZE) {
|
||||
headstage_notify_send();
|
||||
/*
|
||||
events |= SPI_PERIODIC_EVT;
|
||||
Semaphore_post(semaphore);
|
||||
*/
|
||||
}
|
||||
|
||||
headstage_spi_lsk_transaction(3);
|
||||
/*
|
||||
spi_lsk_transaction(3, NULL, spi_rxbuf);
|
||||
*/
|
||||
}
|
||||
|
||||
/*=====================
|
||||
@@ -842,12 +938,15 @@ static void headstage_umc_state_transfer_ask() {
|
||||
headstage_spi_lsk_transaction(8);
|
||||
break;
|
||||
case UMC_STATE_TRIGGER:
|
||||
case UMC_STATE_CONTINUOUS:
|
||||
case UMC_STATE_LIMITED:
|
||||
headstage_spi_lsk_transaction(8);
|
||||
break;
|
||||
case UMC_STATE_WAIT_TRIGGER:
|
||||
headstage_state = UMC_STATE_TRIGGER;
|
||||
headstage_spi_lsk_transaction(3);
|
||||
case UMC_STATE_CONTINUOUS:
|
||||
headstage_spi_lsk_transaction(8);
|
||||
break;
|
||||
case UMC_STATE_LIMITED:
|
||||
headstage_spi_lsk_transaction(8);
|
||||
break;
|
||||
case UMC_STATE_INTERRUPT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -938,14 +1037,11 @@ static void headstage_umc_state_transfer_lsk() {
|
||||
*/
|
||||
case UMC_STATE_WAIT_START:
|
||||
if (headstage_debug_buffer[1] > 18) {
|
||||
// this transaction make cause amplifier data right shift
|
||||
headstage_spi_lsk_transaction(3);
|
||||
headstage_spi_lsk_transaction(7);
|
||||
switch (INSTRUCTION.mode) {
|
||||
default:
|
||||
headstage_state = UMC_STATE_CONTINUOUS;
|
||||
UMC_STATE.trigger_times = 0;
|
||||
break;
|
||||
case 3:
|
||||
case 0:
|
||||
// continuous mode
|
||||
headstage_state = UMC_STATE_CONTINUOUS;
|
||||
UMC_STATE.trigger_times = 0;
|
||||
@@ -975,23 +1071,39 @@ static void headstage_umc_state_transfer_lsk() {
|
||||
break;
|
||||
case UMC_STATE_TRIGGER:
|
||||
headstage_uni_umc_data_append_notify_buffer(spi_rxbuf);
|
||||
// headstage_state = UMC_STATE_WAIT_TRIGGER;
|
||||
|
||||
// headstage_cpu_delay_ms(1);
|
||||
|
||||
// headstage_spi_lsk_transaction(3);
|
||||
|
||||
break;
|
||||
|
||||
case UMC_STATE_WAIT_TRIGGER:
|
||||
// XXX how to back to UMC_STATE_TRIGGER state
|
||||
headstage_spi_ask_transaction(4);
|
||||
break;
|
||||
|
||||
case UMC_STATE_CONTINUOUS:
|
||||
headstage_uni_umc_data_append_notify_buffer(spi_rxbuf);
|
||||
|
||||
// headstage_cpu_delay_ms(1);
|
||||
|
||||
// headstage_spi_lsk_transaction(3);
|
||||
break;
|
||||
|
||||
case UMC_STATE_LIMITED:
|
||||
headstage_uni_umc_data_append_notify_buffer(spi_rxbuf);
|
||||
UMC_STATE.trigger_times--;
|
||||
|
||||
if (UMC_STATE.trigger_times == 0) {
|
||||
headstage_state = UMC_STATE_WAIT_START;
|
||||
}
|
||||
|
||||
// headstage_cpu_delay_ms(1);
|
||||
|
||||
// headstage_spi_lsk_transaction(3);
|
||||
break;
|
||||
case UMC_STATE_INTERRUPT:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
#define HEADSTAGE_ZM_H
|
||||
|
||||
// product information
|
||||
#define DEVICE_NAME "Elite-ZM-v1.4-re"
|
||||
#define DEVICE_NAME "Elite-ZM-v1.2-30"
|
||||
#define MAJOR_PRODUCT_NUMBER 0
|
||||
#define MINOR_PRODUCT_NUMBER 2
|
||||
#define MAJOR_VERSION_NUMBER 1
|
||||
|
||||
+9
-5
@@ -11,13 +11,17 @@
|
||||
#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
|
||||
|
||||
#define CC2650_ADC0 BOOSTXL_CC2650MA_ADC0 // DIO7
|
||||
#define CC2650_ADC1 BOOSTXL_CC2650MA_ADC1 // DIO8
|
||||
#define CC2650_ADC2 BOOSTXL_CC2650MA_ADC2 // DIO9
|
||||
|
||||
#endif
|
||||
|
||||
static ADC_Handle headstage_adc_handle_0;
|
||||
@@ -31,10 +35,10 @@ static ADC_Handle headstage_adc_handle_2;
|
||||
do { \
|
||||
ADC_init(); \
|
||||
ADC_Params param; \
|
||||
ADC_Params_init(¶ms); \
|
||||
ADC_Params_init(¶m); \
|
||||
headstage_adc_handle_0 = ADC_open(CC2650_ADC0, ¶m); \
|
||||
headstage_adc_handle_1 = ADC_open(CC2650_ADC1, ¶m); \
|
||||
headstage_adc_handle_2 = ADC_open(CC2650_ADC2, ¶m); \
|
||||
} while (0)
|
||||
|
||||
#endif // HEADSTAGE_ADC_H
|
||||
#endif // HEADSTAGE_ADC_H
|
||||
|
||||
+17
-16
@@ -13,17 +13,14 @@ static GPTimerCC26XX_Handle gptimer_handle_p1;
|
||||
static GPTimerCC26XX_Handle gptimer_handle_s0;
|
||||
static GPTimerCC26XX_Handle gptimer_handle_s1;
|
||||
|
||||
static void headstage_gptimer_perd_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
|
||||
static void headstage_gptimer_step_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
|
||||
static void headstage_sti_gptimer_main_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
|
||||
static void headstage_sti_gptimer_step_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)
|
||||
|
||||
static void headstage_gptimer_open() {
|
||||
// improve timer accuracy
|
||||
// Power_setDependency(XOSC_HF);
|
||||
|
||||
GPTimerCC26XX_Params params;
|
||||
GPTimerCC26XX_Params_init(¶ms);
|
||||
|
||||
@@ -32,19 +29,21 @@ static void headstage_gptimer_open() {
|
||||
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
|
||||
|
||||
gptimer_handle_p0 = GPTimerCC26XX_open(Board_GPTIMER0A, ¶ms);
|
||||
gptimer_handle_s0 = GPTimerCC26XX_open(Board_GPTIMER0B, ¶ms);
|
||||
gptimer_handle_p1 = GPTimerCC26XX_open(Board_GPTIMER1A, ¶ms);
|
||||
gptimer_handle_p1 = GPTimerCC26XX_open(Board_GPTIMER0B, ¶ms);
|
||||
|
||||
GPTimerCC26XX_Params_init(¶ms);
|
||||
|
||||
params.width = GPT_CONFIG_16BIT;
|
||||
params.mode = GPT_MODE_ONESHOT_DOWN;
|
||||
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
|
||||
|
||||
gptimer_handle_s0 = GPTimerCC26XX_open(Board_GPTIMER1A, ¶ms);
|
||||
gptimer_handle_s1 = GPTimerCC26XX_open(Board_GPTIMER1B, ¶ms);
|
||||
|
||||
GPTimerCC26XX_setLoadValue(gptimer_handle_p0, 0xFFFFFF);
|
||||
GPTimerCC26XX_setLoadValue(gptimer_handle_p1, 0xFFFFFF);
|
||||
GPTimerCC26XX_setLoadValue(gptimer_handle_s0, 0xFFFFFF);
|
||||
GPTimerCC26XX_setLoadValue(gptimer_handle_s1, 0xFFFFFF);
|
||||
|
||||
GPTimerCC26XX_registerInterrupt(gptimer_handle_p0, headstage_gptimer_perd_callback, GPT_INT_TIMEOUT);
|
||||
GPTimerCC26XX_registerInterrupt(gptimer_handle_p1, headstage_gptimer_perd_callback, GPT_INT_TIMEOUT);
|
||||
GPTimerCC26XX_registerInterrupt(gptimer_handle_s0, headstage_gptimer_step_callback, GPT_INT_TIMEOUT);
|
||||
GPTimerCC26XX_registerInterrupt(gptimer_handle_s1, headstage_gptimer_step_callback, GPT_INT_TIMEOUT);
|
||||
GPTimerCC26XX_registerInterrupt(gptimer_handle_p0, headstage_sti_gptimer_main_callback, GPT_INT_TIMEOUT);
|
||||
GPTimerCC26XX_registerInterrupt(gptimer_handle_p1, headstage_sti_gptimer_main_callback, GPT_INT_TIMEOUT);
|
||||
GPTimerCC26XX_registerInterrupt(gptimer_handle_s0, headstage_sti_gptimer_step_callback, GPT_INT_TIMEOUT);
|
||||
GPTimerCC26XX_registerInterrupt(gptimer_handle_s1, headstage_sti_gptimer_step_callback, GPT_INT_TIMEOUT);
|
||||
}
|
||||
|
||||
#define headstage_gptimer_set_load_value(gptimer_handle, load_value) GPTimerCC26XX_setLoadValue(gptimer_handle, load_value)
|
||||
@@ -68,4 +67,6 @@ static void headstage_gptimer_open() {
|
||||
GPTimerCC26XX_setLoadValue(gptimer_handle, _load); \
|
||||
} while (0)
|
||||
|
||||
#define headstage_gptimer_set_callback(handle, callback) GPTimerCC26XX_registerInterrupt(handle, callback, GPT_INT_TIMEOUT);
|
||||
|
||||
#endif // HEADSTAGE_GPTIMER_H
|
||||
|
||||
+47
-28
@@ -1,37 +1,49 @@
|
||||
/* Copyright (c) 2019. BioPro. Scientific.
|
||||
*/
|
||||
|
||||
#ifndef HEADSTAGE_NOTIFY_TDC4VC3_H
|
||||
#define HEADSTAGE_NOTIFY_TDC4VC3_H
|
||||
/*
|
||||
|
||||
notify data format
|
||||
==================
|
||||
|
||||
struct {
|
||||
u8 device_id;
|
||||
u8 data_length;
|
||||
|
||||
u32 cpu_timestamp;
|
||||
|
||||
u4 _;
|
||||
u12 battery_voltage;
|
||||
|
||||
u4 sti_channel;
|
||||
u12 sti_channel_voltage;
|
||||
|
||||
u16 sti_remind_times;
|
||||
|
||||
u4 sti_channel;
|
||||
u12 sti_channel_voltage;
|
||||
|
||||
u16 sti_remind_times;
|
||||
|
||||
// total 16 bytes
|
||||
}
|
||||
|
||||
*/
|
||||
#ifndef HEADSTAGE_NOTIFY_STI_H
|
||||
#define HEADSTAGE_NOTIFY_STI_H
|
||||
|
||||
#ifndef HEADSTAGE_NOTIFY_H
|
||||
#error "headstage/headstage_notify.h not included"
|
||||
#endif
|
||||
|
||||
#define NOT_BUF_OFFSET_INIT 6
|
||||
#include "../headstage_notify_general.h"
|
||||
|
||||
static uint32_t not_buf_offset = NOT_BUF_OFFSET_INIT;
|
||||
static uint32_t not_time_stamp = 0;
|
||||
#define NOT_BUF_OFFSET_INIT 8
|
||||
#define NOT_BUF_ALMOST_FULL 15
|
||||
|
||||
static void headstage_notify_set_timestamp() {
|
||||
not_time_stamp = headstage_time_stamp_us();
|
||||
#define headstage_notify_flip_buffer() _headstage_notify_flip_buffer(not_buf_offset);
|
||||
|
||||
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) {
|
||||
static uint8_t headstage_notify_append_data(uint8_t channel, uint16_t data_value, uint16_t times_remind) {
|
||||
if (not_buf_offset <= NOT_BUF_OFFSET_INIT) {
|
||||
headstage_notify_set_timestamp();
|
||||
|
||||
@@ -42,17 +54,24 @@ static uint8_t headstage_notify_append_data(uint8_t channel, uint16_t data_value
|
||||
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);
|
||||
if (channel == CHANNEL_BATTERY) {
|
||||
headstage_notify_buffer[6] = ((data_value >> 8) & 0x0F);
|
||||
headstage_notify_buffer[7] = (data_value & 0xFF);
|
||||
|
||||
} else {
|
||||
headstage_notify_buffer[not_buf_offset++] = ((channel & 0x0F) << 4) | ((data_value >> 8) & 0x0F);
|
||||
headstage_notify_buffer[not_buf_offset++] = (data_value & 0xFF);
|
||||
headstage_notify_buffer[not_buf_offset++] = ((times_remind >> 8) & 0xFF);
|
||||
headstage_notify_buffer[not_buf_offset++] = (times_remind & 0xFF);
|
||||
}
|
||||
|
||||
uint8_t ret = not_buf_offset;
|
||||
|
||||
if (not_buf_offset >= BLE_NOT_BUFF_SIZE) {
|
||||
if (not_buf_offset >= NOT_BUF_ALMOST_FULL) {
|
||||
headstage_notify_flip_buffer();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif // HEADSTAGE_NOTIFY_TDC4VC3_H
|
||||
#endif // HEADSTAGE_NOTIFY_STI_H
|
||||
|
||||
+22
-15
@@ -7,20 +7,8 @@
|
||||
#if defined(CC2650_LAUNCHXL)
|
||||
|
||||
// clang-format off
|
||||
#define PIN_PON1 IOID_5
|
||||
#define PIN_POL1 IOID_6
|
||||
#define PIN_POL0 IOID_10
|
||||
#define PIN_PON0 IOID_11
|
||||
#define PIN_TPS IOID_3
|
||||
#define PIN_CUR IOID_4
|
||||
#define PIN_VBAT IOID_7
|
||||
#define PIN_SEN0 IOID_8
|
||||
#define PIN_SEN1 IOID_9
|
||||
// clang-format on
|
||||
|
||||
#elif defined(BOOSTXL_CC2650MA)
|
||||
|
||||
// clang-format off
|
||||
#define PIN_LED_R IOID_6
|
||||
#define PIN_LED_G IOID_7
|
||||
#define PIN_PON1 IOID_9
|
||||
#define PIN_POL1 IOID_14
|
||||
#define PIN_POL0 IOID_13
|
||||
@@ -32,6 +20,22 @@
|
||||
#define PIN_SEN1 IOID_30
|
||||
// clang-format on
|
||||
|
||||
#elif defined(BOOSTXL_CC2650MA)
|
||||
|
||||
// clang-format off
|
||||
#define PIN_LED_R PIN_UNASSIGNED
|
||||
#define PIN_LED_G PIN_UNASSIGNED
|
||||
#define PIN_PON1 IOID_5
|
||||
#define PIN_POL1 IOID_6
|
||||
#define PIN_POL0 IOID_10
|
||||
#define PIN_PON0 IOID_11
|
||||
#define PIN_TPS IOID_3
|
||||
#define PIN_CUR IOID_4
|
||||
#define PIN_VBAT IOID_71
|
||||
#define PIN_SEN0 IOID_8
|
||||
#define PIN_SEN1 IOID_9
|
||||
// clang-format on
|
||||
|
||||
#endif
|
||||
|
||||
static PIN_Config headstage_pin_configuration[] = { //
|
||||
@@ -41,7 +45,10 @@ static PIN_Config headstage_pin_configuration[] = { //
|
||||
PIN_PON0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
|
||||
PIN_TPS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
|
||||
|
||||
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,
|
||||
|
||||
//
|
||||
PIN_TERMINATE};
|
||||
|
||||
#endif // HEADSTAGE_PIN_STI_H
|
||||
#endif // HEADSTAGE_PIN_STI_H
|
||||
|
||||
+21
-31
@@ -8,53 +8,43 @@
|
||||
#error "headstage/headstage_notify.h not included"
|
||||
#endif
|
||||
|
||||
#include "../headstage_notify_general.h"
|
||||
|
||||
#define NOT_BUF_OFFSET_INIT 8
|
||||
|
||||
static uint32_t not_buf_offset = NOT_BUF_OFFSET_INIT;
|
||||
static uint32_t not_time_stamp = 0;
|
||||
#define headstage_notify_flip_buffer() _headstage_notify_flip_buffer((not_buf_offset - NOT_BUF_OFFSET_INIT) / 2);
|
||||
|
||||
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, uint8_t *data_value) {
|
||||
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[1] & 0x0f);
|
||||
headstage_notify_buffer[not_buf_offset++] = data_value[2] & 0xFC;
|
||||
}
|
||||
|
||||
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_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();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
*/
|
||||
#ifndef HEADSTAGE_ADC_H
|
||||
#define HEADSTAGE_ADC_H
|
||||
#endif // HEADSTAGE_ADC_H
|
||||
#endif // HEADSTAGE_ADC_H
|
||||
|
||||
-417
@@ -1,417 +0,0 @@
|
||||
|
||||
|
||||
/*
|
||||
* this header file need to be modified, to control
|
||||
*/
|
||||
|
||||
#include "Python.h"
|
||||
#include "structmember.h"
|
||||
|
||||
#ifdef _RASPBERRY_PI3_
|
||||
#include <wiringPi.h>
|
||||
#else
|
||||
#include "wiringPi.h"
|
||||
#endif
|
||||
|
||||
#define SPI_SPEED_US 100
|
||||
|
||||
// class Bpsspi
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD;
|
||||
|
||||
unsigned int cpol;
|
||||
unsigned int cpha;
|
||||
|
||||
unsigned int clk;
|
||||
unsigned int mosi;
|
||||
int miso;
|
||||
unsigned int cs_sz;
|
||||
unsigned int *cs;
|
||||
|
||||
} Bpsspi;
|
||||
|
||||
// Bpsspi __init__
|
||||
static PyObject *Bpsspi_new(PyTypeObject *type, PyObject *args, PyObject *keywords);
|
||||
static int Bpsspi_init(Bpsspi *self, PyObject *args, PyObject *kwargs);
|
||||
static void Bpsspi_dealloc(Bpsspi *self);
|
||||
|
||||
// member
|
||||
static PyMemberDef BpsspiMembers[] = { //
|
||||
{"cpol", T_UINT, offsetof(Bpsspi, cpol), READONLY, "polarity"},
|
||||
{"cpha", T_UINT, offsetof(Bpsspi, cpha), READONLY, "phase"},
|
||||
{"clk", T_UINT, offsetof(Bpsspi, clk), READONLY, "clock pin"},
|
||||
{"mosi", T_UINT, offsetof(Bpsspi, mosi), READONLY, "mosi pin"},
|
||||
{"miso", T_INT, offsetof(Bpsspi, miso), READONLY, "miso pin"},
|
||||
{"cs_sz", T_UINT, offsetof(Bpsspi, cs_sz), READONLY, "chip selection pins number"},
|
||||
{NULL}};
|
||||
|
||||
// methods
|
||||
|
||||
static PyObject *Bpsspi_reset(Bpsspi *self);
|
||||
static PyObject *Bpsspi_set_cs(Bpsspi *self, PyObject *args, PyObject *kwargs);
|
||||
static PyObject *Bpsspi_send_byte_transmit(Bpsspi *self, PyObject *args, PyObject *kwargs);
|
||||
static PyObject *Bpsspi_send_byte_exchange(Bpsspi *self, PyObject *args, PyObject *kwargs);
|
||||
|
||||
static PyMethodDef BpsspiMethods[] = { //
|
||||
{"reset", (PyCFunction)Bpsspi_reset, METH_NOARGS, "Bpsspi.reset"},
|
||||
|
||||
// set_cs(self, cs:int, output:bool)
|
||||
{"set_cs", (PyCFunction)Bpsspi_set_cs, METH_VARARGS | METH_KEYWORDS, "Bpsspi.set_cs"},
|
||||
|
||||
// send_byte_transmit(self, data:bytes)
|
||||
{"send_byte_transmit", (PyCFunction)Bpsspi_send_byte_transmit, METH_VARARGS | METH_KEYWORDS, "Bpsspi.send_byte_transmit"},
|
||||
|
||||
// send_byte_exchange(self, data:bytes) -> List[int]
|
||||
{"send_byte_exchange", (PyCFunction)Bpsspi_send_byte_exchange, METH_VARARGS | METH_KEYWORDS, "Bpsspi.send_byte_exchange"},
|
||||
{NULL}};
|
||||
|
||||
static PyTypeObject BpsspiType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0) //,
|
||||
.tp_name = "Bpsspi",
|
||||
.tp_doc = "BPS spi",
|
||||
.tp_basicsize = sizeof(Bpsspi),
|
||||
.tp_itemsize = 0,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
||||
.tp_new = Bpsspi_new,
|
||||
.tp_init = (initproc)Bpsspi_init,
|
||||
.tp_dealloc = (destructor)Bpsspi_dealloc,
|
||||
.tp_members = BpsspiMembers,
|
||||
.tp_methods = BpsspiMethods,
|
||||
};
|
||||
|
||||
// function implement
|
||||
static PyObject *Bpsspi_new(PyTypeObject *type, PyObject *args, PyObject *keywords) {
|
||||
Bpsspi *self = (Bpsspi *)type->tp_alloc(type, 0);
|
||||
|
||||
if (self != NULL) {
|
||||
self->cpol = 0;
|
||||
self->cpha = 0;
|
||||
self->clk = 0;
|
||||
self->mosi = 0;
|
||||
self->miso = -1;
|
||||
self->cs_sz = 0;
|
||||
self->cs = NULL;
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
static int Bpsspi_init_cs(Bpsspi *self) {
|
||||
if (self->cs != NULL) {
|
||||
PyMem_Free(self->cs);
|
||||
self->cs = NULL;
|
||||
}
|
||||
|
||||
self->cs = (unsigned int *)PyMem_Malloc(self->cs_sz * sizeof(unsigned int));
|
||||
if (self->cs == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "PyMem_Malloc cs fail");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Bpsspi_init(Bpsspi *self, PyObject *args, PyObject *kwargs) {
|
||||
static char *keywords[] = {"clk", "mosi", "miso", "cs", "cpol", "cpha", NULL};
|
||||
|
||||
unsigned int clk;
|
||||
unsigned int mosi;
|
||||
PyObject * miso = NULL;
|
||||
PyObject * cs = NULL;
|
||||
int cpol = 0;
|
||||
int cpha = 0;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "II|OOpp", keywords, &clk, &mosi, &miso, &cs, &cpol, &cpha)) return -1;
|
||||
|
||||
self->clk = clk;
|
||||
self->mosi = mosi;
|
||||
self->cpol = cpol > 0;
|
||||
self->cpha = cpha > 0;
|
||||
|
||||
// miso
|
||||
if (miso == NULL || miso == Py_None) {
|
||||
self->miso = -1;
|
||||
|
||||
} else if (PyLong_Check(miso)) {
|
||||
int miso_val = (int)PyLong_AsLong(miso);
|
||||
|
||||
if (miso_val < 0) {
|
||||
PyErr_Format(PyExc_ValueError, "negative miso pin %d", miso_val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->miso = miso_val;
|
||||
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError, "illegal miso type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// cs
|
||||
if (cs == NULL || cs == Py_None) {
|
||||
self->cs_sz = 0;
|
||||
self->cs = NULL;
|
||||
|
||||
} else if (PyLong_Check(cs)) {
|
||||
self->cs_sz = 1;
|
||||
Bpsspi_init_cs(self);
|
||||
|
||||
int cs_val = (int)PyLong_AsLong(cs);
|
||||
|
||||
if (cs_val < 0) {
|
||||
PyErr_Format(PyExc_ValueError, "negative cs pin %d", cs_val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*self->cs = cs_val;
|
||||
|
||||
} else if (PyTuple_Check(cs)) {
|
||||
self->cs_sz = PyTuple_GET_SIZE(cs);
|
||||
Bpsspi_init_cs(self);
|
||||
|
||||
for (unsigned int i = 0; i < self->cs_sz; i++) {
|
||||
PyObject *cs_ref = PyTuple_GetItem(cs, i);
|
||||
|
||||
if (cs_ref == NULL) return -1;
|
||||
|
||||
int cs_val = (int)PyLong_AsLong(cs_ref);
|
||||
|
||||
if (cs_val == -1 && PyErr_Occurred()) return -1;
|
||||
|
||||
if (cs_val < 0) {
|
||||
PyErr_Format(PyExc_ValueError, "negative cs pin %d", cs_val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(self->cs + i) = cs_val;
|
||||
}
|
||||
|
||||
} else {
|
||||
PyErr_SetString(PyExc_ValueError, "illegal cs type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// reset
|
||||
Bpsspi_reset(self);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Bpsspi_dealloc(Bpsspi *self) {
|
||||
if (self->cs != NULL) {
|
||||
PyMem_Free(self->cs);
|
||||
self->cs = NULL;
|
||||
}
|
||||
|
||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
||||
}
|
||||
|
||||
static PyObject *Bpsspi_reset(Bpsspi *self) {
|
||||
pinMode(self->clk, OUTPUT);
|
||||
digitalWrite(self->clk, (self->cpol) ? HIGH : LOW);
|
||||
|
||||
pinMode(self->mosi, OUTPUT);
|
||||
digitalWrite(self->mosi, LOW);
|
||||
|
||||
if (self->miso >= 0) {
|
||||
pinMode(self->miso, INPUT);
|
||||
pullUpDnControl(self->miso, LOW);
|
||||
}
|
||||
if (self->cs_sz > 0) {
|
||||
for (unsigned int i = 0; i < self->cs_sz; i++) {
|
||||
pinMode(*(self->cs + i), OUTPUT);
|
||||
digitalWrite(*(self->cs + i), HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static int Bpsspi_set_cs0(Bpsspi *self, unsigned int cs, int output) {
|
||||
if (self->cs_sz == 0) return 0;
|
||||
|
||||
for (unsigned int i = 0; i < self->cs_sz; i++) {
|
||||
if (cs == *(self->cs + i)) {
|
||||
digitalWrite(*(self->cs + i), output);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *Bpsspi_set_cs(Bpsspi *self, PyObject *args, PyObject *kwargs) {
|
||||
static char *keywords[] = {"cs", "output", NULL};
|
||||
|
||||
unsigned int cs;
|
||||
int hl = 0;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ip", keywords, &cs, &hl)) return NULL;
|
||||
|
||||
if (self->cs_sz == 0) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
Bpsspi_set_cs0(self, cs, hl ? HIGH : LOW);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *Bpsspi_send_byte_transmit(Bpsspi *self, PyObject *args, PyObject *kwargs) {
|
||||
static char *keywords[] = {"data", NULL};
|
||||
|
||||
PyObject *data_ref;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", keywords, &data_ref)) return NULL;
|
||||
|
||||
if (!PyBytes_Check(data_ref)) {
|
||||
PyErr_SetString(PyExc_ValueError, "data not bytes");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_ssize_t data_sz = PyBytes_GET_SIZE(data_ref);
|
||||
char * data = PyBytes_AS_STRING(data_ref);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
int clk_0 = (self->cpol) ? HIGH : LOW;
|
||||
int clk_1 = (self->cpol) ? LOW : HIGH;
|
||||
|
||||
digitalWrite(self->clk, clk_0);
|
||||
|
||||
for (unsigned int i = 0; i < data_sz; i++) {
|
||||
char d = data[i];
|
||||
|
||||
for (int j = 7; j >= 0; j--) {
|
||||
int v = (d & (1 << j)) > 0;
|
||||
|
||||
if (self->cpha) {
|
||||
digitalWrite(self->clk, clk_1);
|
||||
delayMicroseconds(SPI_SPEED_US);
|
||||
|
||||
digitalWrite(self->mosi, (v) ? HIGH : LOW);
|
||||
digitalWrite(self->clk, clk_0);
|
||||
} else {
|
||||
digitalWrite(self->mosi, (v) ? HIGH : LOW);
|
||||
digitalWrite(self->clk, clk_1);
|
||||
delayMicroseconds(SPI_SPEED_US);
|
||||
|
||||
digitalWrite(self->clk, clk_0);
|
||||
}
|
||||
|
||||
delayMicroseconds(SPI_SPEED_US);
|
||||
}
|
||||
}
|
||||
|
||||
digitalWrite(self->clk, clk_0);
|
||||
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
// XXX not tested
|
||||
static PyObject *Bpsspi_send_byte_exchange(Bpsspi *self, PyObject *args, PyObject *kwargs) {
|
||||
if (self->miso < 0) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "miso pin not set");
|
||||
}
|
||||
|
||||
static char *keywords[] = {"data", NULL};
|
||||
|
||||
PyObject *data_ref;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", keywords, &data_ref)) return NULL;
|
||||
|
||||
if (!PyBytes_Check(data_ref)) {
|
||||
PyErr_SetString(PyExc_ValueError, "data not bytes");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_ssize_t data_sz = PyBytes_GET_SIZE(data_ref);
|
||||
char * data = PyBytes_AS_STRING(data_ref);
|
||||
|
||||
PyObject *ret = PyList_New(data_sz);
|
||||
if (ret == NULL) return NULL;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
int clk_0 = (self->cpol) ? HIGH : LOW;
|
||||
int clk_1 = (self->cpol) ? LOW : HIGH;
|
||||
|
||||
digitalWrite(self->clk, clk_0);
|
||||
|
||||
for (unsigned int i = 0; i < data_sz; i++) {
|
||||
char d = data[i];
|
||||
int r = 0;
|
||||
|
||||
for (int j = 7; j >= 0; j--) {
|
||||
int v = (d & (1 << j)) > 0;
|
||||
|
||||
if (self->cpha) {
|
||||
digitalWrite(self->clk, clk_1);
|
||||
delayMicroseconds(SPI_SPEED_US);
|
||||
|
||||
digitalWrite(self->mosi, (v) ? HIGH : LOW);
|
||||
digitalWrite(self->clk, clk_0);
|
||||
delayMicroseconds(SPI_SPEED_US);
|
||||
|
||||
if (digitalRead(self->miso)) {
|
||||
r |= (1 << j);
|
||||
}
|
||||
|
||||
} else {
|
||||
digitalWrite(self->mosi, (v) ? HIGH : LOW);
|
||||
digitalWrite(self->clk, clk_1);
|
||||
delayMicroseconds(SPI_SPEED_US);
|
||||
|
||||
if (digitalRead(self->miso)) {
|
||||
r |= (1 << j);
|
||||
}
|
||||
|
||||
digitalWrite(self->clk, clk_0);
|
||||
delayMicroseconds(SPI_SPEED_US);
|
||||
}
|
||||
}
|
||||
|
||||
PyList_SET_ITEM(ret, i, PyLong_FromLong(r));
|
||||
}
|
||||
|
||||
digitalWrite(self->clk, clk_0);
|
||||
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// module init
|
||||
|
||||
static PyMethodDef moduleMethods[] = { //
|
||||
{NULL, NULL, 0, NULL}};
|
||||
|
||||
static struct PyModuleDef BpsspiModule = { //
|
||||
PyModuleDef_HEAD_INIT,
|
||||
// module name
|
||||
"bpsspi",
|
||||
// module doc
|
||||
NULL,
|
||||
-1,
|
||||
moduleMethods};
|
||||
|
||||
// module export
|
||||
|
||||
PyMODINIT_FUNC PyInit_bpsspi(void) {
|
||||
wiringPiSetupPhys();
|
||||
|
||||
PyObject *module;
|
||||
|
||||
module = PyModule_Create(&BpsspiModule);
|
||||
if (module == NULL) return NULL;
|
||||
|
||||
if (PyType_Ready(&BpsspiType) < 0) return NULL;
|
||||
|
||||
Py_INCREF(&BpsspiType);
|
||||
PyModule_AddObject(module, "Bpsspi", (PyObject *)&BpsspiType);
|
||||
|
||||
return module;
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/* 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
|
||||
|
||||
#include "../headstage_notify_general.h"
|
||||
|
||||
#define NOT_BUF_OFFSET_INIT 8
|
||||
|
||||
#define headstage_notify_flip_buffer() _headstage_notify_flip_buffer((not_buf_offset - NOT_BUF_OFFSET_INIT) / 2);
|
||||
|
||||
static uint8_t headstage_notify_append_data(uint8_t channel, uint8_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 == NOT_BUF_OFFSET_INIT + 2) {
|
||||
uint32_t current = headstage_time_stamp();
|
||||
uint32_t time_delta = ((current - not_time_stamp) >> 1) & 0xFFFF;
|
||||
|
||||
headstage_notify_buffer[6] = time_delta & 0xFF;
|
||||
headstage_notify_buffer[7] = (time_delta >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
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[1] & 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) {
|
||||
headstage_notify_flip_buffer();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // HEADSTAGE_NOTIFY_TDC4VAF2_H
|
||||
+80
-110
@@ -1,64 +1,64 @@
|
||||
{
|
||||
"name": "Neulive",
|
||||
"version": "1.3",
|
||||
"version": "0.2",
|
||||
"match_rule": {
|
||||
"local_name_pattern": "Neulive.*",
|
||||
"major_product_number": 1,
|
||||
"minor_product_number": 1,
|
||||
"major_version_number": 1,
|
||||
"minor_version_number": 3
|
||||
"major_version_number": 0,
|
||||
"minor_version_number": 2
|
||||
},
|
||||
"constant": {
|
||||
"REC_CHANNEL_COUNT": 12,
|
||||
"REC_CHANNEL_COUNT": 13,
|
||||
"STI_CHANNEL_COUNT": 4,
|
||||
"ADC_SAMPLE_RATE_LIST": [
|
||||
2000,
|
||||
3800,
|
||||
7600,
|
||||
15200,
|
||||
30400
|
||||
10000,
|
||||
19000,
|
||||
38000,
|
||||
76000,
|
||||
152000
|
||||
],
|
||||
"STI_FREQ_LIST": [
|
||||
6,
|
||||
8,
|
||||
10,
|
||||
12,
|
||||
14,
|
||||
16,
|
||||
18,
|
||||
20,
|
||||
22,
|
||||
24,
|
||||
26,
|
||||
28,
|
||||
30,
|
||||
32,
|
||||
34,
|
||||
36,
|
||||
38,
|
||||
40,
|
||||
50,
|
||||
60,
|
||||
70,
|
||||
80,
|
||||
90,
|
||||
100,
|
||||
110,
|
||||
120,
|
||||
130,
|
||||
140,
|
||||
150,
|
||||
160,
|
||||
170,
|
||||
180,
|
||||
190,
|
||||
200,
|
||||
400,
|
||||
600,
|
||||
800,
|
||||
1000,
|
||||
1200,
|
||||
1400,
|
||||
1600,
|
||||
1800,
|
||||
2000
|
||||
2000,
|
||||
3000,
|
||||
4000,
|
||||
5000,
|
||||
6000,
|
||||
7000,
|
||||
8000,
|
||||
9000,
|
||||
10000
|
||||
],
|
||||
"STI_PULSE_WIDTH": [
|
||||
80,
|
||||
180,
|
||||
280,
|
||||
380,
|
||||
480,
|
||||
580,
|
||||
680,
|
||||
780,
|
||||
880,
|
||||
980
|
||||
40,
|
||||
90,
|
||||
140,
|
||||
190,
|
||||
240,
|
||||
290,
|
||||
340,
|
||||
390,
|
||||
440,
|
||||
490
|
||||
]
|
||||
},
|
||||
"parameters": {
|
||||
@@ -84,22 +84,22 @@
|
||||
"description": "amp gain",
|
||||
"record_meta": true,
|
||||
"value": [
|
||||
3,
|
||||
14,
|
||||
27,
|
||||
60,
|
||||
280,
|
||||
540
|
||||
2,
|
||||
5,
|
||||
10,
|
||||
200,
|
||||
500,
|
||||
1000
|
||||
]
|
||||
},
|
||||
"LOW_FREQ_BAND": {
|
||||
"description": "low pass filter",
|
||||
"description": "",
|
||||
"record_meta": true,
|
||||
"domain": [
|
||||
8
|
||||
]
|
||||
},
|
||||
"STI_MODE": {
|
||||
"STI_BEHAVIOR": {
|
||||
"description": "how to execute stimulus",
|
||||
"value": [
|
||||
"DISABLE",
|
||||
@@ -108,8 +108,8 @@
|
||||
"CONTINUOUS"
|
||||
]
|
||||
},
|
||||
"STI_WAVEFORM": {
|
||||
"description": "describe the waveform of stimulation",
|
||||
"STI_MODE": {
|
||||
"description": "stimulation mode",
|
||||
"value": [
|
||||
"Positive Pulse",
|
||||
"Negative Pulse",
|
||||
@@ -118,13 +118,13 @@
|
||||
"Arbitrary Waveform"
|
||||
]
|
||||
},
|
||||
"STI_AMPERE": {
|
||||
"description": "stimulation ampere, unit: uA ",
|
||||
"STI_VOLT": {
|
||||
"description": "stimulation voltage",
|
||||
"type": "float",
|
||||
"domain": [
|
||||
32
|
||||
],
|
||||
"value": " 31 * VALUE "
|
||||
"value": "2 + 3 * VALUE / 31"
|
||||
},
|
||||
"STI_TIMES": {
|
||||
"description": "how many times will be executed",
|
||||
@@ -162,27 +162,17 @@
|
||||
"value": "STI_PULSE_WIDTH[VALUE]"
|
||||
},
|
||||
"CHOPPER": {
|
||||
"description": "default_disable",
|
||||
"description": "",
|
||||
"domain": "bool"
|
||||
},
|
||||
"FAST_SETTLE": {
|
||||
"description": "protect amplifier input when stimulation is executed",
|
||||
"description": "",
|
||||
"domain": "bool"
|
||||
},
|
||||
"UMC_TEST": {
|
||||
"description": "start umc test mode",
|
||||
"domain": "action",
|
||||
"on_change": "umc_default"
|
||||
},
|
||||
"UMC_RESET": {
|
||||
"description": "reset headstage to perform another setting",
|
||||
"domain": "action",
|
||||
"on_change": "reset"
|
||||
},
|
||||
"UMC_TRIGGER": {
|
||||
"description": "trigger stimulation when device is in trigger mode",
|
||||
"domain": "action",
|
||||
"on_change": "STIMULUS"
|
||||
}
|
||||
},
|
||||
"instruction": {
|
||||
@@ -191,19 +181,12 @@
|
||||
"expression": "len(CHANNEL) > 0",
|
||||
"raise": "no recording channel"
|
||||
},
|
||||
"data_format",
|
||||
"_notify(True)",
|
||||
"start_recording",
|
||||
"umc_parameter",
|
||||
"_sync(True)",
|
||||
"VIS_STI"
|
||||
],
|
||||
"trigger stimulation": [
|
||||
"umc_sti_trigger0"
|
||||
],
|
||||
"umc_reset": [
|
||||
"VIS_RST"
|
||||
],
|
||||
"data_format": [
|
||||
"_data_format('TDC4VAF2')"
|
||||
],
|
||||
@@ -211,45 +194,40 @@
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"3b101#direct header;2b0#don't care;3b>LOW_FREQ_BAND",
|
||||
"2b0#don't care;1bCHOPPER;1bFAST_SETTLE;3b>STI_WAVEFORM",
|
||||
"5b>STI_AMPERE;4b>STI_PMOS",
|
||||
"4b0#don't care;1bCHOPPER;1bFAST_SETTLE",
|
||||
"5b>STI_VOLT;4b>STI_PMOS",
|
||||
"4b>STI_NMOS;4b>SAMPLE_RATE"
|
||||
]
|
||||
},
|
||||
"umc_parameter": {
|
||||
"type": "RIS",
|
||||
"foreach-parameter": {
|
||||
"parameter": "CHANNEL",
|
||||
"variable": [
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d"
|
||||
]
|
||||
},
|
||||
"data": [
|
||||
"3b001#umc parameter header;3b>AMP_GAIN",
|
||||
"4b>PULSE_WIDTH;6b>STI_TIMES",
|
||||
"2b>STI_MODE;6b>STI_FREQ",
|
||||
"1ba?;1bb?;1bc?;1bd?",
|
||||
"4b>a?:0;4b>b?:0",
|
||||
"4b>c?:0;4b>d?:0"
|
||||
"3b001#umc parameter header",
|
||||
"3b>AMP_GAIN;4b>PULSE_WIDTH",
|
||||
"6b>STI_TIMES;2b>STI_BEHAVIOR",
|
||||
"6b>STI_FREQ"
|
||||
]
|
||||
},
|
||||
"umc_default": [
|
||||
"_set('CHANNEL', 0)",
|
||||
"_set('SAMPLE_RATE', 0)",
|
||||
"_set('AMP_GAIN', 5)",
|
||||
"_set('STI_WAVEFORM', 1)",
|
||||
"_set('STI_MODE', 1)",
|
||||
"_set('STI_NMOS', 0)",
|
||||
"_set('STI_PMOS', 1)",
|
||||
"_set('STI_AMPERE', 0)",
|
||||
"_set('CHANNEL', 3)",
|
||||
"_set('CHANNEL', 4)",
|
||||
"_set('CHANNEL', 5)",
|
||||
"_set('CHANNEL', 6)",
|
||||
"_set('CHANNEL', 7)",
|
||||
"_set('CHANNEL', 8)",
|
||||
"_set('SAMPLE_RATE', 9)",
|
||||
"_set('AMP_GAIN', 3)",
|
||||
"_set('STI_BEHAVIOR', 1)",
|
||||
"_set('STI_MODE', 0)",
|
||||
"_set('STI_NMOS', STI_PMOS + 1)",
|
||||
"_set('STI_PMOS', 0)",
|
||||
"_set('STI_NMOS', 1)",
|
||||
"_set('STI_VOLT', 0)",
|
||||
"_set('STI_FREQ', 0)",
|
||||
"_set('STI_TIMES', 0)",
|
||||
"_set('PULSE_WIDTH', 0)",
|
||||
"_set('FAST_SETTLE', 1)",
|
||||
"_set('CHOPPER', 0)",
|
||||
"_set('FAST_SETTLE', 0)",
|
||||
"_set('CHOPPER', 1)",
|
||||
"data_format",
|
||||
"_notify(True)",
|
||||
"umc_default0",
|
||||
@@ -261,14 +239,6 @@
|
||||
"data": [
|
||||
"1B0#load umc default parameter into uni"
|
||||
]
|
||||
},
|
||||
"umc_sti_trigger0": {
|
||||
"type": "RIS",
|
||||
"description": "this function is perform only in trigger mode",
|
||||
"data": [
|
||||
"1BC0# trigger stimulation when recording is performed"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+66
-83
@@ -5,60 +5,60 @@
|
||||
"local_name_pattern": "Neulive.*",
|
||||
"major_product_number": 1,
|
||||
"minor_product_number": 1,
|
||||
"major_version_number": 1,
|
||||
"major_version_number": 0,
|
||||
"minor_version_number": 2
|
||||
},
|
||||
"constant": {
|
||||
"REC_CHANNEL_COUNT": 13,
|
||||
"STI_CHANNEL_COUNT": 4,
|
||||
"ADC_SAMPLE_RATE_LIST": [
|
||||
2000,
|
||||
3800,
|
||||
7600,
|
||||
15200,
|
||||
30400
|
||||
10000,
|
||||
19000,
|
||||
38000,
|
||||
76000,
|
||||
152000
|
||||
],
|
||||
"STI_FREQ_LIST": [
|
||||
6,
|
||||
8,
|
||||
10,
|
||||
12,
|
||||
14,
|
||||
16,
|
||||
18,
|
||||
20,
|
||||
22,
|
||||
24,
|
||||
26,
|
||||
28,
|
||||
30,
|
||||
32,
|
||||
34,
|
||||
36,
|
||||
38,
|
||||
40,
|
||||
50,
|
||||
60,
|
||||
70,
|
||||
80,
|
||||
90,
|
||||
100,
|
||||
110,
|
||||
120,
|
||||
130,
|
||||
140,
|
||||
150,
|
||||
160,
|
||||
170,
|
||||
180,
|
||||
190,
|
||||
200,
|
||||
400,
|
||||
600,
|
||||
800,
|
||||
1000,
|
||||
1200,
|
||||
1400,
|
||||
1600,
|
||||
1800,
|
||||
2000
|
||||
2000,
|
||||
3000,
|
||||
4000,
|
||||
5000,
|
||||
6000,
|
||||
7000,
|
||||
8000,
|
||||
9000,
|
||||
10000
|
||||
],
|
||||
"STI_PULSE_WIDTH": [
|
||||
80,
|
||||
180,
|
||||
280,
|
||||
380,
|
||||
480,
|
||||
580,
|
||||
680,
|
||||
780,
|
||||
880,
|
||||
980
|
||||
40,
|
||||
90,
|
||||
140,
|
||||
190,
|
||||
240,
|
||||
290,
|
||||
340,
|
||||
390,
|
||||
440,
|
||||
490
|
||||
]
|
||||
},
|
||||
"parameters": {
|
||||
@@ -84,12 +84,12 @@
|
||||
"description": "amp gain",
|
||||
"record_meta": true,
|
||||
"value": [
|
||||
3,
|
||||
40,
|
||||
70,
|
||||
30,
|
||||
400,
|
||||
700
|
||||
2,
|
||||
5,
|
||||
10,
|
||||
200,
|
||||
500,
|
||||
1000
|
||||
]
|
||||
},
|
||||
"LOW_FREQ_BAND": {
|
||||
@@ -99,7 +99,7 @@
|
||||
8
|
||||
]
|
||||
},
|
||||
"STI_MODE": {
|
||||
"STI_BEHAVIOR": {
|
||||
"description": "how to execute stimulus",
|
||||
"value": [
|
||||
"DISABLE",
|
||||
@@ -108,8 +108,8 @@
|
||||
"CONTINUOUS"
|
||||
]
|
||||
},
|
||||
"STI_WAVEFORM": {
|
||||
"description": "describe the waveform of stimulation",
|
||||
"STI_MODE": {
|
||||
"description": "stimulation mode",
|
||||
"value": [
|
||||
"Positive Pulse",
|
||||
"Negative Pulse",
|
||||
@@ -119,12 +119,12 @@
|
||||
]
|
||||
},
|
||||
"STI_VOLT": {
|
||||
"description": "stimulation volt, unit: V ",
|
||||
"description": "stimulation voltage",
|
||||
"type": "float",
|
||||
"domain": [
|
||||
32
|
||||
],
|
||||
"value": " 2 + 3 * VALUE / 31"
|
||||
"value": "2 + 3 * VALUE / 31"
|
||||
},
|
||||
"STI_TIMES": {
|
||||
"description": "how many times will be executed",
|
||||
@@ -162,27 +162,17 @@
|
||||
"value": "STI_PULSE_WIDTH[VALUE]"
|
||||
},
|
||||
"CHOPPER": {
|
||||
"description": "default_disable",
|
||||
"description": "",
|
||||
"domain": "bool"
|
||||
},
|
||||
"FAST_SETTLE": {
|
||||
"description": "protect amplifier input when stimulation is executed",
|
||||
"description": "",
|
||||
"domain": "bool"
|
||||
},
|
||||
"UMC_TEST": {
|
||||
"description": "start umc test mode",
|
||||
"domain": "action",
|
||||
"on_change": "umc_default"
|
||||
},
|
||||
"UMC_RESET": {
|
||||
"description": "reset headstage to perform another setting",
|
||||
"domain": "action",
|
||||
"on_change": "reset"
|
||||
},
|
||||
"UMC_TRIGGER": {
|
||||
"description": "trigger stimulation when device is in trigger mode",
|
||||
"domain": "action",
|
||||
"on_change": "STIMULUS"
|
||||
}
|
||||
},
|
||||
"instruction": {
|
||||
@@ -198,10 +188,10 @@
|
||||
"_sync(True)",
|
||||
"VIS_STI"
|
||||
],
|
||||
"trigger stimulation": [
|
||||
"umc_sti_trigger0"
|
||||
"stop": [
|
||||
"VIS_INT"
|
||||
],
|
||||
"umc_reset": [
|
||||
"restart": [
|
||||
"VIS_RST"
|
||||
],
|
||||
"data_format": [
|
||||
@@ -211,7 +201,7 @@
|
||||
"type": "RIS",
|
||||
"data": [
|
||||
"3b101#direct header;2b0#don't care;3b>LOW_FREQ_BAND",
|
||||
"2b0#don't care;1bCHOPPER;1bFAST_SETTLE;3b>STI_WAVEFORM",
|
||||
"2b0#don't care;1bCHOPPER;1bFAST_SETTLE;3b>STI_MODE",
|
||||
"5b>STI_VOLT;4b>STI_PMOS",
|
||||
"4b>STI_NMOS;4b>SAMPLE_RATE"
|
||||
]
|
||||
@@ -230,26 +220,27 @@
|
||||
"data": [
|
||||
"3b001#umc parameter header;3b>AMP_GAIN",
|
||||
"4b>PULSE_WIDTH;6b>STI_TIMES",
|
||||
"2b>STI_MODE;6b>STI_FREQ",
|
||||
"2b>STI_BEHAVIOR;6b>STI_FREQ",
|
||||
"1ba?;1bb?;1bc?;1bd?",
|
||||
"4b>a?:0;4b>b?:0",
|
||||
"4b>c?:0;4b>d?:0"
|
||||
]
|
||||
},
|
||||
"umc_default": [
|
||||
"_set('CHANNEL', 0)",
|
||||
"_set('CHANNEL', 1)",
|
||||
"_set('SAMPLE_RATE', 0)",
|
||||
"_set('AMP_GAIN', 5)",
|
||||
"_set('STI_WAVEFORM', 1)",
|
||||
"_set('STI_MODE', 1)",
|
||||
"_set('STI_NMOS', 0)",
|
||||
"_set('STI_PMOS', 1)",
|
||||
"_set('STI_BEHAVIOR', 1)",
|
||||
"_set('STI_MODE', 0)",
|
||||
"_set('STI_NMOS', STI_PMOS + 1)",
|
||||
"_set('STI_PMOS', 0)",
|
||||
"_set('STI_NMOS', 1)",
|
||||
"_set('STI_VOLT', 0)",
|
||||
"_set('STI_FREQ', 0)",
|
||||
"_set('STI_TIMES', 0)",
|
||||
"_set('PULSE_WIDTH', 0)",
|
||||
"_set('FAST_SETTLE', 1)",
|
||||
"_set('CHOPPER', 0)",
|
||||
"_set('FAST_SETTLE', 0)",
|
||||
"_set('CHOPPER', 1)",
|
||||
"data_format",
|
||||
"_notify(True)",
|
||||
"umc_default0",
|
||||
@@ -261,14 +252,6 @@
|
||||
"data": [
|
||||
"1B0#load umc default parameter into uni"
|
||||
]
|
||||
},
|
||||
"umc_sti_trigger0": {
|
||||
"type": "RIS",
|
||||
"description": "this function is perform only in trigger mode",
|
||||
"data": [
|
||||
"1BC0# trigger stimulation when recording is performed"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
/* Copyright (c) 2019. BioPro. Scientific.
|
||||
*/
|
||||
#ifndef NEULIVE_1P2
|
||||
#define NEULIVE_1P2
|
||||
|
||||
/*============================
|
||||
==== product information ====
|
||||
===========================*/
|
||||
|
||||
#define DEVICE_NAME "Neulive-v1.2"
|
||||
#define MAJOR_PRODUCT_NUMBER 1
|
||||
#define MINOR_PRODUCT_NUMBER 1
|
||||
#define MAJOR_VERSION_NUMBER 1 // need to modify
|
||||
#define MINOR_VERSION_NUMBER 2
|
||||
|
||||
static uint16_t sti_channel_table[4] = {
|
||||
{0b000001}, // 2
|
||||
{0b000111}, // 8
|
||||
{0b001011}, // 12
|
||||
{0b001111} // 16
|
||||
};
|
||||
|
||||
static uint16_t reverse_channel[16] = {{0x0A}, // 1
|
||||
{0x0B},
|
||||
{0x00},
|
||||
{0x01},
|
||||
{0x02},
|
||||
{0x07},
|
||||
{0x06},
|
||||
{0x03},
|
||||
{0x05},
|
||||
{0x04},
|
||||
{0x08},
|
||||
{0xff},
|
||||
{0x0c},
|
||||
{0x09},
|
||||
{0xff},
|
||||
{0xff}};
|
||||
|
||||
static uint16_t amp_channel_table[13] = { //
|
||||
{0x03},
|
||||
{0x04},
|
||||
{0x05},
|
||||
{0x08},
|
||||
{0x0A},
|
||||
{0x09},
|
||||
{0x07},
|
||||
{0x06},
|
||||
{0x0B},
|
||||
{0x0E},
|
||||
{0x01},
|
||||
{0x02},
|
||||
{0x0D}};
|
||||
|
||||
static uint16_t amp_gain_table[] = {
|
||||
0b100011, // 3
|
||||
0b000011, // 30
|
||||
0b101100, // 40
|
||||
0b101001, // 70
|
||||
0b001100, // 400
|
||||
0b001001, // 700
|
||||
};
|
||||
|
||||
#endif
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
/* Copyright (c) 2019. BioPro. Scientific.
|
||||
*/
|
||||
#ifndef NEULIVE_1P3
|
||||
#define NEULIVE_1P3
|
||||
|
||||
/*============================
|
||||
==== product information ====
|
||||
===========================*/
|
||||
|
||||
#define DEVICE_NAME "Neulive-v1.3"
|
||||
#define MAJOR_PRODUCT_NUMBER 1
|
||||
#define MINOR_PRODUCT_NUMBER 1
|
||||
#define MAJOR_VERSION_NUMBER 1
|
||||
#define MINOR_VERSION_NUMBER 3
|
||||
|
||||
static uint16_t sti_channel_table[4] = {
|
||||
{0b000010}, // 3
|
||||
{0b000011}, // 4
|
||||
{0b000100}, // 5
|
||||
{0b000101} // 6
|
||||
};
|
||||
|
||||
static uint16_t reverse_channel[16] = {{0x0A}, // 1
|
||||
{0x00},
|
||||
{0x01},
|
||||
{0x02},
|
||||
{0x03},
|
||||
{0x08},
|
||||
{0x07},
|
||||
{0x06},
|
||||
{0x05},
|
||||
{0x04},
|
||||
{0x09},
|
||||
{0x0B},
|
||||
{0xFF},
|
||||
{0xFF},
|
||||
{0xff},
|
||||
{0xff}};
|
||||
|
||||
static uint16_t amp_channel_table[12] = { //
|
||||
{0x02},
|
||||
{0x03},
|
||||
{0x04},
|
||||
{0x05},
|
||||
{0x0A},
|
||||
{0x09},
|
||||
{0x08},
|
||||
{0x07},
|
||||
{0x06},
|
||||
{0x0b},
|
||||
{0x01},
|
||||
{0x0C}};
|
||||
|
||||
static uint16_t amp_gain_table[] = {
|
||||
0b100011, // 3
|
||||
0b101100, // 14
|
||||
0b101001, // 27
|
||||
0b000011, // 60
|
||||
0b001100, // 280
|
||||
0b001001, // 540
|
||||
};
|
||||
|
||||
#endif
|
||||
+5
-31
@@ -4,37 +4,14 @@
|
||||
#define HEADSTAGE_PIN_ZM_H
|
||||
|
||||
// clang-format off
|
||||
#define PIN_ADC_CS IOID_8
|
||||
#define PIN_DAC_CS IOID_9
|
||||
#define PIN_SWITCH_ON IOID_11
|
||||
#define PIN_SHUTDOWN_6994 IOID_10
|
||||
#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_13
|
||||
|
||||
#define PIN_TURNON_200R IOID_5
|
||||
#define PIN_TURNON_10K IOID_6
|
||||
|
||||
/* I2C */
|
||||
#ifdef ELITE_I2C
|
||||
#define Board_I2C0_SCL0 IOID_7
|
||||
#define Board_I2C0_SDA0 IOID_1
|
||||
#endif
|
||||
#define PIN_ENABLE_V05 IOID_14
|
||||
// clang-format on
|
||||
|
||||
// from Elite IV-test branch
|
||||
/* SPI Board */
|
||||
#define Board_SPI0_MISO PIN_UNASSIGNED
|
||||
#define Board_SPI0_MOSI IOID_1
|
||||
#define Board_SPI0_CLK IOID_0
|
||||
#define Board_SPI0_CS PIN_UNASSIGNED
|
||||
|
||||
#define Board_SPI1_MISO IOID_3
|
||||
#define Board_SPI1_MOSI IOID_2
|
||||
#define Board_SPI1_CLK IOID_4
|
||||
#define Board_SPI1_CS PIN_UNASSIGNED
|
||||
// End of Elite IV-test branch
|
||||
|
||||
|
||||
#if defined(CC2650_LAUNCHXL)
|
||||
#define PIN_LED_R IOID_6
|
||||
#define PIN_LED_G IOID_7
|
||||
@@ -45,9 +22,6 @@ 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_TURNON_200R | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
|
||||
PIN_TURNON_10K | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
|
||||
|
||||
PIN_ENABLE_V10 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
|
||||
PIN_ENABLE_V05 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,
|
||||
|
||||
|
||||
+5
-14
@@ -36,23 +36,14 @@ static SPI_Transaction headstage_spi_adc_transaction;
|
||||
#define headstage_spi_open() \
|
||||
do { \
|
||||
SPI_init(); \
|
||||
SPI_Params spi_parameter0; \
|
||||
SPI_Params_init(&spi_parameter0); \
|
||||
SPI_Params spi_parameter; \
|
||||
SPI_Params_init(&spi_parameter); \
|
||||
spi_parameter.transferMode = SPI_MODE_BLOCKING; \
|
||||
spi_parameter.mode = SPI_MASTER; \
|
||||
spi_parameter.bitRate = 2000; \
|
||||
spi_parameter.dataSize = 16; \
|
||||
spi_parameter.frameFormat = SPI_POL0_PHA1; \
|
||||
headstage_spi_dac_handle = SPI_open(Board_SPI0, &spi_parameter0);\
|
||||
|
||||
SPI_Params spi_parameter1; \
|
||||
SPI_Params_init(&spi_parameter1); \
|
||||
spi_parameter.transferMode = SPI_MODE_BLOCKING; \
|
||||
spi_parameter.mode = SPI_MASTER; \
|
||||
spi_parameter.bitRate = 1000000; \
|
||||
spi_parameter.bitRate = 12000000; \
|
||||
spi_parameter.dataSize = 8; \
|
||||
spi_parameter.frameFormat = SPI_POL0_PHA1; \
|
||||
headstage_spi_dac_handle = SPI_open(Board_SPI1, &spi_parameter1);\
|
||||
spi_parameter.frameFormat = SPI_POL0_PHA0; \
|
||||
headstage_spi_dac_handle = SPI_open(Board_SPI0, &spi_parameter); \
|
||||
} while (0)
|
||||
|
||||
#define headstage_dac_transaction() \
|
||||
|
||||
+93
-99
@@ -184,7 +184,7 @@ typedef struct {
|
||||
static ICall_EntityID self;
|
||||
|
||||
// Semaphore globally used to post events to the application thread
|
||||
ICall_Semaphore semaphore;
|
||||
static ICall_Semaphore semaphore;
|
||||
|
||||
// Queue object used for app messages
|
||||
static Queue_Struct application_message;
|
||||
@@ -221,7 +221,6 @@ static void SimpleBLEPeripheral_sendAttRsp(void);
|
||||
static void SimpleBLEPeripheral_freeAttRsp(uint8_t status);
|
||||
static void SimpleBLEPeripheral_stateChangeCB(gaprole_States_t newState);
|
||||
static void SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state);
|
||||
static void headstage_data_length_extension();
|
||||
|
||||
#ifndef FEATURE_OAD_ONCHIP
|
||||
static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID);
|
||||
@@ -409,11 +408,6 @@ static void SimpleBLEPeripheral_init(void) {
|
||||
GATT_RegisterForMsgs(self);
|
||||
|
||||
HCI_LE_ReadMaxDataLenCmd();
|
||||
|
||||
HCI_LE_WriteSuggestedDefaultDataLenCmd(251, 2120); // this is used for data length extension
|
||||
|
||||
uint8_t prepare_write_req = 6;
|
||||
GATTServApp_SetParameter(GATT_PARAM_NUM_PREPARE_WRITES, 1, &prepare_write_req);
|
||||
}
|
||||
|
||||
#ifndef DEVICE_NAME
|
||||
@@ -446,8 +440,9 @@ static void SimpleBLEPeripheral_init(void) {
|
||||
|
||||
#endif
|
||||
|
||||
static char *date = __DATE__;
|
||||
static void headstage_init_device_info() {
|
||||
static void headstage_init_device_info() {
|
||||
static char *date = __DATE__;
|
||||
|
||||
uint8_t year = 10 * (date[9] - '0') + (date[10] - '0');
|
||||
uint8_t month = 0;
|
||||
|
||||
@@ -504,21 +499,14 @@ static void headstage_init_device_info() {
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t scanRspData[64];
|
||||
uint8_t scanRspData[B_MAX_ADV_LEN];
|
||||
uint8_t *p = scanRspData;
|
||||
*p++ = sizeof(DEVICE_NAME);
|
||||
*p++ = GAP_ADTYPE_LOCAL_NAME_COMPLETE;
|
||||
// unsafe_memcpy(p, DEVICE_NAME, sizeof(DEVICE_NAME));
|
||||
for (unsigned int i = 0; i < sizeof(DEVICE_NAME) - 1; i++) {
|
||||
*p++ = DEVICE_NAME[i];
|
||||
}
|
||||
unsafe_memcpy(p, DEVICE_NAME, sizeof(DEVICE_NAME) - 1);
|
||||
*p++ = 11;
|
||||
*p++ = GAP_ADTYPE_MANUFACTURER_SPECIFIC;
|
||||
// unsafe_memcpy(p, "BPHS", 4);
|
||||
*p++ = 'B';
|
||||
*p++ = 'P';
|
||||
*p++ = 'H';
|
||||
*p++ = 'S';
|
||||
unsafe_memcpy(p, "BPHS", 4);
|
||||
*p++ = MAJOR_PRODUCT_NUMBER;
|
||||
*p++ = MINOR_PRODUCT_NUMBER;
|
||||
*p++ = MAJOR_VERSION_NUMBER;
|
||||
@@ -555,14 +543,11 @@ static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1) {
|
||||
// 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);
|
||||
// headstage_watchdog_clear();
|
||||
|
||||
if (errno == ICALL_ERRNO_SUCCESS) {
|
||||
ICall_EntityID dest;
|
||||
ICall_ServiceEnum src;
|
||||
ICall_HciExtEvt * message = NULL;
|
||||
if (EVENT_MASK > 0) {
|
||||
headstage_event_handle();
|
||||
}
|
||||
|
||||
if (ICall_fetchServiceMsg(&src, &dest, (void **)&message) == ICALL_ERRNO_SUCCESS) {
|
||||
uint8 safeToDealloc = TRUE;
|
||||
@@ -600,6 +585,10 @@ static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1) {
|
||||
}
|
||||
}
|
||||
|
||||
if (EVENT_MASK > 0) {
|
||||
headstage_event_handle();
|
||||
}
|
||||
|
||||
#ifdef FEATURE_OAD
|
||||
while (!Queue_empty(oad_queue_handle)) {
|
||||
oadTargetWrite_t *oadWriteEvt = Queue_get(oad_queue_handle);
|
||||
@@ -635,15 +624,7 @@ static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr *message) {
|
||||
// Process GATT message
|
||||
return SimpleBLEPeripheral_processGATTMsg((gattMsgEvent_t *)message);
|
||||
|
||||
case HCI_GAP_EVENT_EVENT: { // GAP event
|
||||
switch (message->event) {
|
||||
case HCI_EXT_SET_MAX_DATA_LENGTH_EVENT: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
case HCI_GAP_EVENT_EVENT: // GAP event
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
@@ -678,10 +659,6 @@ static uint8_t SimpleBLEPeripheral_processGATTMsg(gattMsgEvent_t *message) {
|
||||
|
||||
} else if (message->method == ATT_MTU_UPDATED_EVENT) {
|
||||
// MTU size updated
|
||||
headstage_debug_buffer[10] = 0xff;
|
||||
headstage_set_debug_information();
|
||||
} else if (message->method == ATT_HANDLE_VALUE_CFM) {
|
||||
// quick pass
|
||||
}
|
||||
|
||||
// Free message payload. Needed only for ATT Protocol messages
|
||||
@@ -710,11 +687,12 @@ static void SimpleBLEPeripheral_sendAttRsp(void) {
|
||||
|
||||
// Try to retransmit ATT response till either we're successful or
|
||||
// the ATT Client times out (after 30s) and drops the connection.
|
||||
|
||||
status = GATT_SendRsp(pAttRsp->connHandle, pAttRsp->method, &(pAttRsp->msg));
|
||||
|
||||
if ((status != blePending) && (status != MSG_BUFFER_NOT_AVAIL)) {
|
||||
// Disable connection event end notice
|
||||
HCI_EXT_ConnEventNoticeCmd(pAttRsp->connHandle, self, 0);
|
||||
|
||||
// We're done with the response message
|
||||
SimpleBLEPeripheral_freeAttRsp(status);
|
||||
} else {
|
||||
@@ -761,13 +739,13 @@ static void SimpleBLEPeripheral_freeAttRsp(uint8_t status) {
|
||||
*/
|
||||
static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *message) {
|
||||
switch (message->hdr.event) {
|
||||
case SBP_STATE_CHANGE_EVT:
|
||||
SimpleBLEPeripheral_processStateChangeEvt((gaprole_States_t)message->hdr.state);
|
||||
break;
|
||||
case SBP_STATE_CHANGE_EVT:
|
||||
SimpleBLEPeripheral_processStateChangeEvt((gaprole_States_t)message->hdr.state);
|
||||
break;
|
||||
|
||||
case SBP_CHAR_CHANGE_EVT:
|
||||
headstage_characteristic_updated(message->hdr.state);
|
||||
break;
|
||||
case SBP_CHAR_CHANGE_EVT:
|
||||
headstage_characteristic_updated(message->hdr.state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,77 +773,93 @@ static void SimpleBLEPeripheral_stateChangeCB(gaprole_States_t newState) {
|
||||
*/
|
||||
static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState) {
|
||||
switch (newState) {
|
||||
case GAPROLE_STARTED: { // Started but not advertising
|
||||
uint8_t ownAddress[B_ADDR_LEN];
|
||||
uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
|
||||
case GAPROLE_STARTED: { // Started but not advertising
|
||||
uint8_t ownAddress[B_ADDR_LEN];
|
||||
uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
|
||||
|
||||
GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);
|
||||
GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);
|
||||
|
||||
// use 6 bytes of device address for 8 bytes of system ID value
|
||||
systemId[0] = ownAddress[0];
|
||||
systemId[1] = ownAddress[1];
|
||||
systemId[2] = ownAddress[2];
|
||||
// use 6 bytes of device address for 8 bytes of system ID value
|
||||
systemId[0] = ownAddress[0];
|
||||
systemId[1] = ownAddress[1];
|
||||
systemId[2] = ownAddress[2];
|
||||
|
||||
// set middle bytes to zero
|
||||
systemId[4] = 0x00;
|
||||
systemId[3] = 0x00;
|
||||
// set middle bytes to zero
|
||||
systemId[4] = 0x00;
|
||||
systemId[3] = 0x00;
|
||||
|
||||
// shift three bytes up
|
||||
systemId[7] = ownAddress[5];
|
||||
systemId[6] = ownAddress[4];
|
||||
systemId[5] = ownAddress[3];
|
||||
// shift three bytes up
|
||||
systemId[7] = ownAddress[5];
|
||||
systemId[6] = ownAddress[4];
|
||||
systemId[5] = ownAddress[3];
|
||||
|
||||
DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
|
||||
DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
case GAPROLE_CONNECTED: { // In a connection
|
||||
linkDBInfo_t linkInfo;
|
||||
uint8_t numActive = 0;
|
||||
numActive = linkDB_NumActive();
|
||||
|
||||
// Use numActive to determine the connection handle of the last
|
||||
// connection
|
||||
if (linkDB_GetInfo(numActive - 1, &linkInfo) == SUCCESS) {
|
||||
} else {
|
||||
uint8_t peerAddress[B_ADDR_LEN];
|
||||
|
||||
GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress);
|
||||
}
|
||||
|
||||
case GAPROLE_CONNECTED: { // In a connection
|
||||
linkDBInfo_t linkInfo;
|
||||
uint8_t numActive = 0;
|
||||
numActive = linkDB_NumActive();
|
||||
// connected
|
||||
GAPRole_GetParameter(GAPROLE_CONNHANDLE, &CONNECT_HANDLE);
|
||||
|
||||
headstage_led_spi_color(COLOR_CYAN);
|
||||
/*
|
||||
headstage_led_spi_color(COLOR_GREEN);
|
||||
|
||||
uint16_t cxnHandle;
|
||||
uint16_t requestedPDUSize = 251;
|
||||
uint16_t requestTxTime = 2120;
|
||||
GAPRole_GetParameter(GAPROLE_CONNHANDLE, &cxnHandle);
|
||||
uint16_t cxnHandle;
|
||||
uint16_t requestedPDUSize = 251;
|
||||
uint16_t requestTxTime = 2120;
|
||||
|
||||
if (SUCCESS != HCI_LE_SetDataLenCmd(cxnHandle, requestedPDUSize, requestTxTime)) {
|
||||
}
|
||||
// Use numActive to determine the connection handle of the last
|
||||
// connection
|
||||
if (linkDB_GetInfo(numActive - 1, &linkInfo) == SUCCESS) {
|
||||
} else {
|
||||
uint8_t peerAddress[B_ADDR_LEN];
|
||||
GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress);
|
||||
}
|
||||
flag_notify(EVT_CONNECTED);
|
||||
break;
|
||||
if(SUCCESS != HCI_LE_SetDataLenCmd(cxnHandle, requestedPDUSize, requestTxTime)) {
|
||||
}
|
||||
*/
|
||||
|
||||
case GAPROLE_WAITING:
|
||||
// Device is started but not advertising, is in waiting period before advertising again
|
||||
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
|
||||
break;
|
||||
flag_notify(EVT_CONNECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
case GAPROLE_WAITING_AFTER_TIMEOUT:
|
||||
// Device just timed out from a connection but is not yet advertising, is in waiting period before advertising again
|
||||
// disconnected
|
||||
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
|
||||
headstage_led_spi_color(COLOR_RED);
|
||||
CONNECT_HANDLE = 0xFFFF;
|
||||
case GAPROLE_WAITING: {
|
||||
// Device is started but not advertising, is in waiting period before advertising again
|
||||
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
|
||||
|
||||
// disconnected
|
||||
uint8_t disconnect = CONNECT_HANDLE != CONNECT_HANDLE_UNCONNECTED;
|
||||
CONNECT_HANDLE = CONNECT_HANDLE_UNCONNECTED;
|
||||
|
||||
if (disconnect) {
|
||||
flag_notify(EVT_DISCONNECTED);
|
||||
break;
|
||||
case GAPROLE_ERROR: // Error occurred - invalid state
|
||||
headstage_led_spi_color(COLOR_RED);
|
||||
break;
|
||||
case GAPROLE_INIT: // Waiting to be started
|
||||
case GAPROLE_ADVERTISING: // Currently Advertising
|
||||
case GAPROLE_CONNECTED_ADV: // In a connection and advertising
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GAPROLE_WAITING_AFTER_TIMEOUT:
|
||||
// Device just timed out from a connection but is not yet advertising, is in waiting period before advertising again
|
||||
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
|
||||
|
||||
// disconnected over timeout
|
||||
// TODO headstage_led_spi_color(COLOR_RED);
|
||||
|
||||
break;
|
||||
|
||||
case GAPROLE_ERROR: // Error occurred - invalid state
|
||||
// TODO headstage_led_spi_color(COLOR_RED);
|
||||
break;
|
||||
case GAPROLE_INIT: // Waiting to be started
|
||||
case GAPROLE_ADVERTISING: // Currently Advertising
|
||||
case GAPROLE_CONNECTED_ADV: // In a connection and advertising
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+124
-124
@@ -304,57 +304,57 @@ bStatus_t SimpleProfile_RegisterAppCBs(simpleProfileCBs_t *appCallbacks) {
|
||||
*/
|
||||
bStatus_t SimpleProfile_SetParameter(uint8 param, uint8 len, void *value) {
|
||||
switch (param) {
|
||||
case SIMPLEPROFILE_CHAR1:
|
||||
if (len <= SIMPLEPROFILE_CHAR1_LEN) {
|
||||
memcpy(simpleProfileChar1, value, len);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
case SIMPLEPROFILE_CHAR1:
|
||||
if (len <= SIMPLEPROFILE_CHAR1_LEN) {
|
||||
memcpy(simpleProfileChar1, value, len);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
|
||||
case SIMPLEPROFILE_CHAR2:
|
||||
if (len <= SIMPLEPROFILE_CHAR2_LEN) {
|
||||
memcpy(simpleProfileChar2, value, len);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
case SIMPLEPROFILE_CHAR2:
|
||||
if (len <= SIMPLEPROFILE_CHAR2_LEN) {
|
||||
memcpy(simpleProfileChar2, value, len);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
|
||||
case SIMPLEPROFILE_CHAR3:
|
||||
if (len <= SIMPLEPROFILE_CHAR3_LEN) {
|
||||
memcpy(simpleProfileChar3, value, len);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
case SIMPLEPROFILE_CHAR3:
|
||||
if (len <= SIMPLEPROFILE_CHAR3_LEN) {
|
||||
memcpy(simpleProfileChar3, value, len);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
|
||||
case SIMPLEPROFILE_CHAR4:
|
||||
if (len <= SIMPLEPROFILE_CHAR4_LEN) {
|
||||
memcpy(simpleProfileChar4, value, len);
|
||||
case SIMPLEPROFILE_CHAR4:
|
||||
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);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
// See if Notification has been enabled
|
||||
GATTServApp_ProcessCharCfg(simpleProfileChar4Config, //
|
||||
simpleProfileChar4,
|
||||
FALSE,
|
||||
simpleProfileAttrTbl,
|
||||
GATT_NUM_ATTRS(simpleProfileAttrTbl),
|
||||
INVALID_TASK_ID,
|
||||
simpleProfile_ReadAttrCB);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
|
||||
case SIMPLEPROFILE_CHAR5:
|
||||
if (len <= SIMPLEPROFILE_CHAR5_LEN) {
|
||||
memcpy(simpleProfileChar5, value, len);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
case SIMPLEPROFILE_CHAR5:
|
||||
if (len <= SIMPLEPROFILE_CHAR5_LEN) {
|
||||
memcpy(simpleProfileChar5, value, len);
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return bleInvalidRange;
|
||||
}
|
||||
|
||||
default:
|
||||
return INVALIDPARAMETER;
|
||||
default:
|
||||
return INVALIDPARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,28 +373,28 @@ bStatus_t SimpleProfile_SetParameter(uint8 param, uint8 len, void *value) {
|
||||
*/
|
||||
bStatus_t SimpleProfile_GetParameter(uint8 param, void *value) {
|
||||
switch (param) {
|
||||
case SIMPLEPROFILE_CHAR1:
|
||||
memcpy(value, simpleProfileChar1, SIMPLEPROFILE_CHAR1_LEN);
|
||||
break;
|
||||
case SIMPLEPROFILE_CHAR1:
|
||||
memcpy(value, simpleProfileChar1, SIMPLEPROFILE_CHAR1_LEN);
|
||||
break;
|
||||
|
||||
case SIMPLEPROFILE_CHAR2:
|
||||
memcpy(value, simpleProfileChar2, SIMPLEPROFILE_CHAR2_LEN);
|
||||
break;
|
||||
case SIMPLEPROFILE_CHAR2:
|
||||
memcpy(value, simpleProfileChar2, SIMPLEPROFILE_CHAR2_LEN);
|
||||
break;
|
||||
|
||||
case SIMPLEPROFILE_CHAR3:
|
||||
memcpy(value, simpleProfileChar3, SIMPLEPROFILE_CHAR3_LEN);
|
||||
break;
|
||||
case SIMPLEPROFILE_CHAR3:
|
||||
memcpy(value, simpleProfileChar3, SIMPLEPROFILE_CHAR3_LEN);
|
||||
break;
|
||||
|
||||
case SIMPLEPROFILE_CHAR4:
|
||||
memcpy(value, simpleProfileChar4, SIMPLEPROFILE_CHAR4_LEN);
|
||||
break;
|
||||
case SIMPLEPROFILE_CHAR4:
|
||||
memcpy(value, simpleProfileChar4, SIMPLEPROFILE_CHAR4_LEN);
|
||||
break;
|
||||
|
||||
case SIMPLEPROFILE_CHAR5:
|
||||
memcpy(value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN);
|
||||
break;
|
||||
case SIMPLEPROFILE_CHAR5:
|
||||
memcpy(value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN);
|
||||
break;
|
||||
|
||||
default:
|
||||
return INVALIDPARAMETER;
|
||||
default:
|
||||
return INVALIDPARAMETER;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@@ -433,31 +433,31 @@ static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle, //
|
||||
// 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_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_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_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;
|
||||
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;
|
||||
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
|
||||
@@ -496,59 +496,59 @@ static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle, //
|
||||
uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]);
|
||||
|
||||
switch (uuid) {
|
||||
case SIMPLEPROFILE_CHAR3_UUID:
|
||||
case SIMPLEPROFILE_CHAR3_UUID:
|
||||
|
||||
// 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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
// 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 SIMPLEPROFILE_CHAR5_UUID:
|
||||
if (offset == 0) {
|
||||
if (len >= SIMPLEPROFILE_CHAR5_LEN) {
|
||||
status = ATT_ERR_INVALID_VALUE_SIZE;
|
||||
}
|
||||
} else {
|
||||
status = ATT_ERR_ATTR_NOT_LONG;
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
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
|
||||
|
||||
@@ -84,7 +84,7 @@ extern "C" {
|
||||
#define SIMPLEPROFILE_CHAR1_LEN 2
|
||||
#define SIMPLEPROFILE_CHAR2_LEN 10
|
||||
#define SIMPLEPROFILE_CHAR3_LEN 20
|
||||
#define SIMPLEPROFILE_CHAR4_LEN 200
|
||||
#define SIMPLEPROFILE_CHAR4_LEN 20
|
||||
#define SIMPLEPROFILE_CHAR5_LEN 20
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Reference in New Issue
Block a user