Compare commits

...

66 Commits

Author SHA1 Message Date
Yichin wong f5018b5c37 Update README.md 2019-08-29 16:43:37 +00:00
Yichin wong 2a17781fde Update README.md 2019-08-15 04:28:40 +00:00
Yichin wong 67d52bcd75 Update README.md 2019-08-15 04:25:11 +00:00
Ta-Shun Su b96505d79c fix README style 2019-07-25 18:15:39 +08:00
Ta-Shun Su 7083101d79 fix README style 2019-07-25 18:05:14 +08:00
Ta-Shun Su ee70b207ca update README 2019-07-25 18:03:11 +08:00
Ta-Shun Su 314bb70489 update README 2019-07-25 17:57:05 +08:00
Ta-Shun Su 459f4850ef update test 2019-07-25 14:16:28 +08:00
Ta-Shun Su dbc2e3a568 save 2019-07-25 11:56:09 +08:00
Ta-Shun Su 1f4cee9279 headstage_notify.h 2019-07-25 11:54:16 +08:00
Ta-Shun Su f18f05cd1d headstage.h for uni 2019-07-25 11:46:33 +08:00
Ta-Shun Su 93816a8d36 led.h for GPIO, fix from neulive1.2 2019-07-25 11:30:11 +08:00
Ta-Shun Su 18a8fde7de Merge branch 'neulive1.2/master' 2019-07-25 11:17:37 +08:00
yichin 7742ab0c9c fix scan data error 2019-06-25 18:21:04 +08:00
Ta-Shun Su 1d1e08771d add old sti instruction generator 2019-06-13 14:44:11 +08:00
Ta-Shun Su 916e27ba33 save 2019-06-06 15:50:05 +08:00
Ta-Shun Su 598c3e2629 improve python test code with VIS 2019-06-06 14:47:57 +08:00
Ta-Shun Su ca39a15e60 add test 2019-06-05 19:08:24 +08:00
yichin 2c992d8526 compile pass for sti 2019-06-05 17:28:53 +08:00
Ta-Shun Su 127742b194 save 2019-06-05 17:19:57 +08:00
Ta-Shun Su dff979cbe6 Merge branch 'neuliveSTI/1210' 2019-06-05 17:17:41 +08:00
Ta-Shun Su 3b13a0ff90 reformat 2019-06-05 17:14:18 +08:00
yichin 1e061f2511 sti adc for vsen 2019-06-05 16:14:42 +08:00
yichin cc2648585c add adc pin define from LP 2019-06-05 16:07:25 +08:00
Ta-Shun Su b965f81fc4 notify format 2019-06-03 17:03:01 +08:00
Ta-Shun Su b5ddf300b9 reformat 2019-06-03 16:45:37 +08:00
Ta-Shun Su 22175f379f Merge branch 'neuliveSTI/1210' 2019-06-03 16:32:19 +08:00
yichin 6ff966df58 sti comment debug code 2019-06-03 16:29:49 +08:00
yichin 65f159fad2 fix disconnect event 2019-06-03 16:29:24 +08:00
yichin 515fc57307 sti adc 2019-06-03 16:22:17 +08:00
yichin b84fbb6044 sti clock 2019-06-03 15:51:08 +08:00
Ta-Shun Su d1cdaf7041 reformat 2019-06-03 15:37:09 +08:00
yichin d824b1fbd9 save 2019-06-03 15:31:07 +08:00
yichin 0df352d6ff sti clock 2019-06-03 12:48:23 +08:00
yichin c27b6a0ac7 sti notify format 2019-06-03 12:36:28 +08:00
yichin e1152f6713 bug fix 2019-06-03 12:03:25 +08:00
yichin e6ab11b004 sti use one callback to control two channel which has same parameter 2019-06-03 11:06:22 +08:00
yichin e3e40d25e9 save 2019-05-28 19:18:57 +08:00
yichin 495d4deb91 save 2019-05-28 18:53:55 +08:00
yichin aa662f4a7b save 2019-05-27 19:59:06 +08:00
yichin 21f17ab7a3 tow channel test 2019-05-27 18:26:25 +08:00
yichin 6000816833 save 2019-05-27 18:17:43 +08:00
yichin 95116252c8 save 2019-05-27 17:54:29 +08:00
yichin 28e8a66221 save 2019-05-27 17:26:58 +08:00
yichin 3249e7e1e2 save 2019-05-27 14:03:13 +08:00
yichin d5d97db086 fix bug 2019-05-27 13:28:16 +08:00
yichin c806a7e09f fix bug 2019-05-27 12:47:07 +08:00
yichin 95e563e04f fix bug 2019-05-27 11:53:41 +08:00
Ta-Shun Su 747ebf5f8b impl debug instruction 2019-05-27 11:15:56 +08:00
yichin fb942c8e40 more debug instruction 2019-05-27 11:10:00 +08:00
yichin fdc2f05d46 add led signal 2019-05-27 11:04:23 +08:00
Ta-Shun Su 3c2823cc13 save 2019-05-27 10:57:58 +08:00
yichin 9ba9131a51 Merge remote-tracking branch 'origin/neuliveSTI/1210' into neuliveSTI/1210 2019-05-27 10:25:28 +08:00
yichin bd64c60b40 save 2019-05-27 10:25:13 +08:00
Ta-Shun Su bb7e609665 add gptimer python 2019-05-27 10:24:43 +08:00
Ta-Shun Su 9c4794c868 save 2019-05-25 20:56:41 +08:00
Ta-Shun Su 019c32faf5 add error 2019-05-25 20:29:04 +08:00
Ta-Shun Su 96b6e4d1b9 save 2019-05-25 19:54:06 +08:00
yichin 105d01e636 save 2019-05-24 19:02:16 +08:00
yichin 71fcc98862 save 2019-05-24 18:29:46 +08:00
yichin c63656ac97 save 2019-05-24 17:39:06 +08:00
Ta-Shun Su 47a24ccef3 Merge remote-tracking branch 'origin/neuliveSTI/1210' into neuliveSTI/1210 2019-05-24 16:36:30 +08:00
Ta-Shun Su 2ee3abf193 improve devlib/util.py 2019-05-24 16:35:25 +08:00
Ta-Shun Su d9039070ad save 2019-05-24 16:32:01 +08:00
yichin f69fd4a40f save 2019-05-24 16:29:32 +08:00
yichin a6287ad7e3 fix bug 2019-05-24 15:12:19 +08:00
35 changed files with 2305 additions and 1146 deletions
+4 -1
View File
@@ -5,4 +5,7 @@ xdctools_*/
ccsv8/
# CSS build files
FlashROM/
FlashROM/
# python cache
__pycache__/
+3
View File
@@ -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>
+205 -1
View File
@@ -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.
-50
View File
@@ -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;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)
+99 -7
View File
@@ -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='')
+22
View File
@@ -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))
+115
View File
@@ -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, {})
+133
View File
@@ -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,7 +1,7 @@
def main():
file = open('C:/ti/python_test_code/uni/att_notify.psd', 'r')
print(file.read())
file.close()
with open('C:/ti/python_test_code/uni/att_notify.psd', 'r') as file:
print(file.read())
if __name__ == '__main__':
main()
+33
View File
@@ -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)
+98 -96
View File
@@ -1,16 +1,47 @@
import unittest
import random
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
@@ -20,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
@@ -58,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, 1, 2)), count_channel_without_re(to_channel_table(0, 1, 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__':
@@ -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,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">
@@ -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>
@@ -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>
@@ -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">
@@ -513,6 +513,158 @@ const PWM_Config PWM_config[BOOSTXL_CC2650MA_PWMCOUNT + 1] = {
* ============================= PWM end ======================================
*/
/*
* ============================= ADC begin ======================================
*/
#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=====================================
*/
@@ -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
@@ -242,13 +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 ====
@@ -283,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 ====
@@ -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
@@ -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(&param); \
param.period = 48000*(_period); \
param.startFlag = false; \
clock_handle = Clock_create(headstage_clock_callback, 1, &param, NULL); \
#define headstage_clock_open(p) \
do { \
Clock_Params param; \
Clock_Params_init(&param); \
param.period = 0; \
param.startFlag = false; \
clock_handle = Clock_create(headstage_clock_callback, 0, &param, NULL); \
uint32_t _period = (p)*1000 / Clock_tickPeriod; \
Clock_setPeriod(clock_handle, _period); \
} while (0)
#define headstage_clock_set_frequency(frequency) \
@@ -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,38 +191,51 @@ 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
*/
#include "headstage_pin.h"
static void headstage_led_spi_transmit (){
for(int8_t i = 0; i < 8; i++) {
#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;
headstage_pin_output(PIN_LED_CLK,1);
CPUdelay( 16*400 );// 2500hz
headstage_pin_output(PIN_LED_OUT, SET_LED);
for (int8_t j = 15; j >= 0; j--) {
bool high = ((d & (1 << j)) > 0) ? 1 : 0;
headstage_pin_output(PIN_LED_CLK, 1);
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){
headstage_led_set_color(headstage_spi_led_txbuf, SPI_LED_REPEAT, 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();
}
#endif // HEADSTAGE_LED_USE_GPIO
#endif // HEADSTAGE_LED_H
@@ -31,7 +31,7 @@ optional implement
#include <xdc/runtime/Timestamp.h>
#define headstage_time_stamp_us() (32 * Timestamp_get32())
#define headstage_time_stamp() Timestamp_get32()
#define headstage_time_stamp_ms() (Timestamp_get32() / 32)
/*========================
@@ -73,4 +73,18 @@ static void headstage_notify_send() {
#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
@@ -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
@@ -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"
/*=================================
@@ -53,7 +53,6 @@
#include "headstage_led.h"
#include "headstage_arm.h"
#include "headstage_watchdog.h"
#include "tni/headstage_notify.h"
#include "uni/headstage_spi.h"
#include "uni/headstage_pwm.h"
#include "uni/headstage_adc.h"
@@ -236,43 +235,39 @@ static uint16_t sti_channel_table[4] = {
* 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}
};
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}
};
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
@@ -293,8 +288,7 @@ static uint16_t amp_channel_table[13] = { //
{0x0E},
{0x01},
{0x02},
{0x0D}
};
{0x0D}};
#else
static uint16_t amp_channel_table[12] = { //
{0x02},
@@ -308,8 +302,7 @@ static uint16_t amp_channel_table[12] = { //
{0x06},
{0x0b},
{0x01},
{0x0C}
};
{0x0C}};
#endif
static uint16_t amp_gain_table[] = {
@@ -498,13 +491,12 @@ static void rearrange_channel_mux_table() {
}
}
int8_t offset = last_enable_channel - channel_mux_index ;
int8_t offset = last_enable_channel - channel_mux_index;
while (channel_mux_index >= 0) {
INSTRUCTION.channel_mux[channel_mux_index] = INSTRUCTION.channel_mux[channel_mux_index + offset];
channel_mux_index--;
}
}
/*======================
@@ -586,13 +578,11 @@ static void headstage_uni_event() {
}
static void headstage_spi_ask_callback(SPI_Handle handle, SPI_Transaction* transaction) {
if ( UMC_STATE.reset_flag == 0)
flag_notify(EVT_UMC_ASK);
if (UMC_STATE.reset_flag == 0) flag_notify(EVT_UMC_ASK);
}
static void headstage_spi_lsk_callback(SPI_Handle handle, SPI_Transaction* transaction) {
if ( UMC_STATE.reset_flag == 0)
flag_notify(EVT_UMC_LSK);
if (UMC_STATE.reset_flag == 0) flag_notify(EVT_UMC_LSK);
}
static void headstage_reset() {
@@ -608,7 +598,6 @@ static void headstage_reset() {
headstage_cpu_delay_ms(1);
headstage_pin_output(PIN_RESET, 1);
flag_disable(EVT_UMC_LSK);
}
/*===========================
@@ -623,18 +612,18 @@ static void headstage_init() {
headstage_spi_open();
headstage_pwm_open();
// headstage_i2c_open();
// headstage_i2c_open();
// headstage_watchdog_open();
// if(headstage_watchdog_handle == NULL)
// {
// headstage_led_spi_color(COLOR_RED);
// }
// headstage_watchdog_open();
// if(headstage_watchdog_handle == NULL)
// {
// headstage_led_color(COLOR_RED);
// }
headstage_pin_output(PIN_RESET, 1); // initialize DBS chip
headstage_pin_output(PIN_STI_SEL, 0); // chip select is ok
headstage_pin_output(PIN_VGRP, 1); //
headstage_pin_output(PIN_FASTSET, 0); //
headstage_pin_output(PIN_RESET, 1); // initialize DBS chip
headstage_pin_output(PIN_STI_SEL, 0); // chip select is ok
headstage_pin_output(PIN_VGRP, 1); //
headstage_pin_output(PIN_FASTSET, 0); //
}
static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t* instruction) {
@@ -651,19 +640,19 @@ static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t* instructi
uint8_t sti_chn = (instruction[3] & 0b11110000) >> 4;
uint8_t frequency = (instruction[3] & 0b00001111);
INSTRUCTION.sti_waveform = sti_waveform;
INSTRUCTION.frequency = frequency;
INSTRUCTION.amp_low_band_freq = amp_lbf;
INSTRUCTION.chopper = chopper;
INSTRUCTION.fast_settle = fast_settle;
INSTRUCTION.sti_volt = sti_volt;
INSTRUCTION.sti_channel_pmos = sti_chp;
INSTRUCTION.sti_channel_nmos = sti_chn;
INSTRUCTION.sti_waveform = sti_waveform;
INSTRUCTION.frequency = frequency;
INSTRUCTION.amp_low_band_freq = amp_lbf;
INSTRUCTION.chopper = chopper;
INSTRUCTION.fast_settle = fast_settle;
INSTRUCTION.sti_volt = sti_volt;
INSTRUCTION.sti_channel_pmos = sti_chp;
INSTRUCTION.sti_channel_nmos = sti_chn;
break;
}
case RIS_SET_PARA: {
uint8_t amp_gain = (instruction[0] & 0x1C) >> 2;
uint8_t pulse_width = ((instruction[0] & 0x03) << 2) | ((instruction[1] & 0xC0)>> 6);
uint8_t pulse_width = ((instruction[0] & 0x03) << 2) | ((instruction[1] & 0xC0) >> 6);
uint8_t sti_times = (instruction[1] & 0x3F);
uint8_t sti_freq = (instruction[2] & 0x3F);
uint8_t mode = (instruction[2] & 0xC0) >> 6;
@@ -678,33 +667,33 @@ static void headstage_update_ris_instruction(uint8_t ins_len, uint8_t* instructi
INSTRUCTION.mode = mode;
INSTRUCTION.sti_freq = sti_freq;
if (instruction[3] & 0b10000000) INSTRUCTION.channel_table[amp_channel_table[cha]-1] = TRUE;
if (instruction[3] & 0b01000000) INSTRUCTION.channel_table[amp_channel_table[chb]-1] = TRUE;
if (instruction[3] & 0b00100000) INSTRUCTION.channel_table[amp_channel_table[chc]-1] = TRUE;
if (instruction[3] & 0b00010000) INSTRUCTION.channel_table[amp_channel_table[chd]-1] = TRUE;
if (instruction[3] & 0b10000000) INSTRUCTION.channel_table[amp_channel_table[cha] - 1] = TRUE;
if (instruction[3] & 0b01000000) INSTRUCTION.channel_table[amp_channel_table[chb] - 1] = TRUE;
if (instruction[3] & 0b00100000) INSTRUCTION.channel_table[amp_channel_table[chc] - 1] = TRUE;
if (instruction[3] & 0b00010000) INSTRUCTION.channel_table[amp_channel_table[chd] - 1] = TRUE;
break;
}
// 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 = 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
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 = 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++) {
// INSTRUCTION.channel_table[i] = (4 <= i && i <= 8);
// }
// this for-loop is used for setting the amplifier channel
// for (unsigned int i = 0; i < REC_CHANNEL_COUNT; i++) {
// INSTRUCTION.channel_table[i] = (4 <= i && i <= 8);
// }
break;
}
case RIS_RECONFIG:
@@ -746,8 +735,8 @@ static void headstage_update_vis_instruction(uint8_t vis_oper) {
headstage_pwm_start(headstage_system_pwm_handle);
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);
UMC_STATE.reset_flag = 0;
headstage_led_color(COLOR_BLUE);
flag_notify(EVT_UMC_LSK);
}
@@ -796,14 +785,13 @@ static void headstage_uni_test_data_append_notify_buffer(uint8_t* dat_buf) {
headstage_notify_send();
}
// todo: check data length extension with this function -> this function should be
// 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 ((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);
@@ -812,10 +800,9 @@ static void headstage_uni_umc_data_append_notify_buffer(uint8_t* dat_buf) {
uint8_t channel;
if(INSTRUCTION.enable_channel_number == 1) {
if (INSTRUCTION.enable_channel_number == 1) {
channel = reverse_channel[INSTRUCTION.last_enable_channel];
}
else if (dat_buf[0] == 0xc1) {
} 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;
@@ -823,8 +810,8 @@ static void headstage_uni_umc_data_append_notify_buffer(uint8_t* dat_buf) {
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);
// 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();
@@ -1045,51 +1032,50 @@ static void headstage_umc_state_transfer_lsk() {
}
break;
/*
conservative instruction need golden key to trigger DBS
*/
/*
conservative instruction need golden key to trigger DBS
*/
case UMC_STATE_WAIT_START:
if(headstage_debug_buffer[1] > 18){
headstage_spi_lsk_transaction(7);
switch (INSTRUCTION.mode) {
if (headstage_debug_buffer[1] > 18) {
headstage_spi_lsk_transaction(7);
switch (INSTRUCTION.mode) {
default:
break;
case 0:
// continuous mode
headstage_state = UMC_STATE_CONTINUOUS;
UMC_STATE.trigger_times = 0;
break;
default:
break;
case 0:
// continuous mode
headstage_state = UMC_STATE_CONTINUOUS;
UMC_STATE.trigger_times = 0;
break;
case 1:
// trigger mode
headstage_state = UMC_STATE_TRIGGER;
UMC_STATE.trigger_times = 0;
break;
case 1:
// trigger mode
headstage_state = UMC_STATE_TRIGGER;
UMC_STATE.trigger_times = 0;
break;
case 2:
// limited mode
headstage_state = UMC_STATE_LIMITED;
UMC_STATE.trigger_times = INSTRUCTION.sti_times;
break;
}
} else if(headstage_debug_buffer[1] > 10){
headstage_debug_buffer[1] += 1;
tx_put_u32(0, UMC_GOLDEN_KEY);
headstage_spi_ask_transaction(4);
} else {
headstage_debug_buffer[1] += 1;
tx_put_u32(0, build_configure_instruction(CONFIG_DONE, 0xFF));
headstage_spi_ask_transaction(4);
case 2:
// limited mode
headstage_state = UMC_STATE_LIMITED;
UMC_STATE.trigger_times = INSTRUCTION.sti_times;
break;
}
} else if (headstage_debug_buffer[1] > 10) {
headstage_debug_buffer[1] += 1;
tx_put_u32(0, UMC_GOLDEN_KEY);
headstage_spi_ask_transaction(4);
} else {
headstage_debug_buffer[1] += 1;
tx_put_u32(0, build_configure_instruction(CONFIG_DONE, 0xFF));
headstage_spi_ask_transaction(4);
}
break;
case UMC_STATE_TRIGGER:
headstage_uni_umc_data_append_notify_buffer(spi_rxbuf);
// headstage_state = UMC_STATE_WAIT_TRIGGER;
// headstage_state = UMC_STATE_WAIT_TRIGGER;
// headstage_cpu_delay_ms(1);
// headstage_cpu_delay_ms(1);
// headstage_spi_lsk_transaction(3);
// headstage_spi_lsk_transaction(3);
break;
@@ -1100,9 +1086,9 @@ static void headstage_umc_state_transfer_lsk() {
case UMC_STATE_CONTINUOUS:
headstage_uni_umc_data_append_notify_buffer(spi_rxbuf);
// headstage_cpu_delay_ms(1);
// headstage_cpu_delay_ms(1);
// headstage_spi_lsk_transaction(3);
// headstage_spi_lsk_transaction(3);
break;
case UMC_STATE_LIMITED:
@@ -1113,9 +1099,9 @@ static void headstage_umc_state_transfer_lsk() {
headstage_state = UMC_STATE_WAIT_START;
}
// headstage_cpu_delay_ms(1);
// headstage_cpu_delay_ms(1);
// headstage_spi_lsk_transaction(3);
// headstage_spi_lsk_transaction(3);
break;
case UMC_STATE_INTERRUPT:
break;
@@ -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(&params); \
ADC_Params_init(&param); \
headstage_adc_handle_0 = ADC_open(CC2650_ADC0, &param); \
headstage_adc_handle_1 = ADC_open(CC2650_ADC1, &param); \
headstage_adc_handle_2 = ADC_open(CC2650_ADC2, &param); \
} while (0)
#endif // HEADSTAGE_ADC_H
#endif // HEADSTAGE_ADC_H
@@ -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(&params);
@@ -32,19 +29,21 @@ static void headstage_gptimer_open() {
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
gptimer_handle_p0 = GPTimerCC26XX_open(Board_GPTIMER0A, &params);
gptimer_handle_s0 = GPTimerCC26XX_open(Board_GPTIMER0B, &params);
gptimer_handle_p1 = GPTimerCC26XX_open(Board_GPTIMER1A, &params);
gptimer_handle_p1 = GPTimerCC26XX_open(Board_GPTIMER0B, &params);
GPTimerCC26XX_Params_init(&params);
params.width = GPT_CONFIG_16BIT;
params.mode = GPT_MODE_ONESHOT_DOWN;
params.debugStallMode = GPTimerCC26XX_DEBUG_STALL_OFF;
gptimer_handle_s0 = GPTimerCC26XX_open(Board_GPTIMER1A, &params);
gptimer_handle_s1 = GPTimerCC26XX_open(Board_GPTIMER1B, &params);
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
@@ -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
@@ -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
@@ -8,44 +8,19 @@
#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 == NOT_BUF_OFFSET_INIT + 2) {
uint32_t current = headstage_time_stamp_us();
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;
}
@@ -54,13 +29,19 @@ static uint8_t headstage_notify_append_data(uint8_t channel, uint8_t *data_value
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;
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();
}
@@ -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;
}
@@ -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
@@ -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,8 +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
}
#ifndef DEVICE_NAME
@@ -443,80 +440,73 @@ static void SimpleBLEPeripheral_init(void) {
#endif
static char *date = __DATE__;
static void headstage_init_device_info() {
static char *date = __DATE__;
uint8_t year = 10 * (date[9] - '0') + (date[10] - '0');
uint8_t month = 0;
switch (date[0]) {
case 'J':
// Jan, January
// Jun, June
// Jul, July
if (date[1] == 'a') {
month = 1;
} else if (date[2] == 'n') {
month = 6;
} else {
month = 7;
}
break;
case 'F':
// Feb, February
month = 2;
break;
case 'M':
// Mar, March
// May, May
if (date[2] == 'r') {
month = 3;
} else {
month = 5;
}
break;
case 'A':
// Apr, April
// Ang, August
if (date[1] == 'p') {
month = 4;
} else {
month = 8;
}
break;
case 'S':
// Sep, September
month = 9;
break;
case 'O':
// Oct, October
month = 10;
break;
case 'N':
// Nov, November
month = 11;
break;
case 'D':
// Dec, December
month = 12;
break;
case 'J':
// Jan, January
// Jun, June
// Jul, July
if (date[1] == 'a') {
month = 1;
} else if (date[2] == 'n') {
month = 6;
} else {
month = 7;
}
break;
case 'F':
// Feb, February
month = 2;
break;
case 'M':
// Mar, March
// May, May
if (date[2] == 'r') {
month = 3;
} else {
month = 5;
}
break;
case 'A':
// Apr, April
// Ang, August
if (date[1] == 'p') {
month = 4;
} else {
month = 8;
}
break;
case 'S':
// Sep, September
month = 9;
break;
case 'O':
// Oct, October
month = 10;
break;
case 'N':
// Nov, November
month = 11;
break;
case 'D':
// Dec, December
month = 12;
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;
@@ -553,7 +543,7 @@ 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;
@@ -594,6 +584,7 @@ static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1) {
}
}
}
if (EVENT_MASK > 0) {
headstage_event_handle();
}
@@ -629,22 +620,13 @@ static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1) {
*/
static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr *message) {
switch (message->event) {
case GATT_MSG_EVENT:
// Process GATT message
return SimpleBLEPeripheral_processGATTMsg((gattMsgEvent_t *)message);
case GATT_MSG_EVENT:
// 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;
}
}
default:
return TRUE;
case HCI_GAP_EVENT_EVENT: // GAP event
default:
return TRUE;
}
}
@@ -677,9 +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] = 0x0f;
headstage_set_debug_information();
// headstage_data_length_extension();
}
// Free message payload. Needed only for ATT Protocol messages
@@ -708,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 {
@@ -823,41 +803,57 @@ static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState)
uint8_t numActive = 0;
numActive = linkDB_NumActive();
headstage_led_spi_color(COLOR_GREEN);
uint16_t cxnHandle;
uint16_t requestedPDUSize = 251;
uint16_t requestTxTime = 2120;
GAPRole_GetParameter(GAPROLE_CONNHANDLE, &cxnHandle);
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);
}
// connected
GAPRole_GetParameter(GAPROLE_CONNHANDLE, &CONNECT_HANDLE);
/*
headstage_led_spi_color(COLOR_GREEN);
uint16_t cxnHandle;
uint16_t requestedPDUSize = 251;
uint16_t requestTxTime = 2120;
if(SUCCESS != HCI_LE_SetDataLenCmd(cxnHandle, requestedPDUSize, requestTxTime)) {
}
*/
flag_notify(EVT_CONNECTED);
break;
}
case GAPROLE_WAITING:
case GAPROLE_WAITING: {
// Device is started but not advertising, is in waiting period before advertising again
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
break;
// disconnected
uint8_t disconnect = CONNECT_HANDLE != CONNECT_HANDLE_UNCONNECTED;
CONNECT_HANDLE = CONNECT_HANDLE_UNCONNECTED;
if (disconnect) {
flag_notify(EVT_DISCONNECTED);
}
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;
flag_notify(EVT_DISCONNECTED);
// disconnected over timeout
// TODO headstage_led_spi_color(COLOR_RED);
break;
case GAPROLE_ERROR: // Error occurred - invalid state
headstage_led_spi_color(COLOR_RED);
// TODO headstage_led_spi_color(COLOR_RED);
break;
case GAPROLE_INIT: // Waiting to be started
case GAPROLE_ADVERTISING: // Currently Advertising
@@ -939,24 +935,3 @@ static void SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state) {
Util_enqueueMsg(application_message_queue, semaphore, (uint8 *)message);
}
}
static void headstage_data_length_extension(){
while(1){
while (!Queue_empty(application_message_queue))
{
sbpEvt_t *pMsg = (sbpEvt_t *)Util_dequeueMsg(application_message_queue);
if (pMsg)
{
// Process message.
SimpleBLEPeripheral_processAppMsg(pMsg);
// Free the space from the message.
ICall_free(pMsg);
}
}
if (EVENT_MASK > 0) {
headstage_event_handle();
}
}
}