first commit
This commit is contained in:
commit
2650ca4b5e
|
|
@ -0,0 +1,3 @@
|
|||
env/
|
||||
hub_manager.py~
|
||||
arc.txt
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
cd ~/Code/acroname
|
||||
|
||||
cat > umber_env.sh << 'EOF'
|
||||
# --- Umber Networks / Fi-Wi Dev Environment ---
|
||||
ACRO_BASE="$HOME/Code/acroname"
|
||||
if [ -d "$ACRO_BASE/env" ]; then
|
||||
source "$ACRO_BASE/env/bin/activate"
|
||||
fi
|
||||
# Acroname Hub Management for Fi-Wi Rig
|
||||
export ACRONAME_PATH="$HOME/Code/acroname/hub_manager.py"
|
||||
alias hub-status='$ACRONAME_PATH status all'
|
||||
alias hub-on='$ACRONAME_PATH on'
|
||||
alias hub-off='$ACRONAME_PATH off'
|
||||
alias hub-verify='$ACRONAME_PATH verify'
|
||||
alias hub-setup='$ACRONAME_PATH setup'
|
||||
alias hub-reboot='$ACRONAME_PATH reboot'
|
||||
alias hub-reboot-force='$ACRONAME_PATH reboot-force'
|
||||
EOF
|
||||
|
||||
git add umber_env.sh
|
||||
git commit -m "Add Fi-Wi dev environment setup and hub aliases"
|
||||
git push
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Define the environment name
|
||||
VENV_NAME="env"
|
||||
|
||||
echo "--- Starting Python VENV setup on $(hostname) ---"
|
||||
|
||||
# 1. Update package list and ensure venv/pip are installed
|
||||
sudo apt update
|
||||
sudo apt install -y python3-venv python3-pip
|
||||
|
||||
# 2. Create the virtual environment
|
||||
if [ ! -d "$VENV_NAME" ]; then
|
||||
echo "Creating virtual environment: $VENV_NAME"
|
||||
python3 -m venv $VENV_NAME
|
||||
else
|
||||
echo "Virtual environment '$VENV_NAME' already exists."
|
||||
fi
|
||||
|
||||
# 3. Activate the environment
|
||||
source $VENV_NAME/bin/activate
|
||||
|
||||
# 4. Upgrade pip and install brainstem
|
||||
echo "Upgrading pip and installing BrainStem SDK..."
|
||||
pip install --upgrade pip
|
||||
pip install brainstem
|
||||
|
||||
# 5. Optional: Install common networking tools for your iperf2 testing
|
||||
# pip install numpy matplotlib # if you plan on plotting results later
|
||||
|
||||
echo "--- Setup Complete ---"
|
||||
echo "To start using the environment, run: source $VENV_NAME/bin/activate"
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
/****************************************************************
|
||||
* Filename: brainstem_network.cpp
|
||||
* Prepared By: James Dudley
|
||||
* Date Prepared: March 12, 2018
|
||||
* Date Revised: March 12, 2018
|
||||
* Revision: 0.0.1
|
||||
***************************************************************/
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#define USB_CHANNEL 0
|
||||
#define RAIL0_SET_VOLTAGE 2200000 // Set voltage for MTM-PM-1 Rail 0
|
||||
#define RAIL1_SET_VOLTAGE 2800000 // Set voltage for MTM-IO-SERIAL Rail 1
|
||||
#define CYCLE_TIME 20 // Time to pause between readings, ms
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
// Create each MTM object
|
||||
// Apply a module offset of 24 to the MTM-PM-1 module (determined by the DIP switch
|
||||
// on the development board
|
||||
aMTMIOSerial ioserial;
|
||||
aMTMPM1 pm;
|
||||
pm.setModuleAddress(aMTMPM1_MODULE_BASE_ADDRESS + 24);
|
||||
aMTMUSBStem stem;
|
||||
|
||||
// Initialize error tracker
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Discover and connect to MTM-IO-SERIAL object
|
||||
// First, get a list of all available USB modules (Note: MTM-PM-1 shows up because there's
|
||||
// a pass-through USB channel on the MTM-IO-SERIAL, which is connected to the MTM-PM-1 edge
|
||||
// connector USB on the development board)
|
||||
list<linkSpec> spec_list;
|
||||
err = Link::sDiscover(USB, &spec_list);
|
||||
|
||||
//
|
||||
list<linkSpec>::iterator it;
|
||||
for (it = spec_list.begin(); it != spec_list.end(); ++it) {
|
||||
if (it->model == aMODULE_TYPE_MTMIOSerial_1) {
|
||||
err = ioserial.connect(USB, it->serial_num);
|
||||
if (err != aErrNone) {
|
||||
printf("Error connecting to MTM-IO-Serial: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ioserial.isConnected()) {
|
||||
printf("Error finding MTM-IO-SERIAL module: no MTM-IO-SERIAL link Spec discovered/n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = pm.connectThroughLinkModule(&ioserial);
|
||||
if (err != aErrNone) {
|
||||
printf("Error connecting to MTM-PM-1: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
err = stem.connectThroughLinkModule(&ioserial);
|
||||
if (err != aErrNone) {
|
||||
printf("Error connecting to MTM-USBStem: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = ioserial.system.routeToMe(1);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting MTM-IO-SERIAL routeToMe: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 1 - Set MTM-PM-1 Rail 0 and measure the voltage using MTM-USBSTEM A2D0
|
||||
err = pm.rail[0].setVoltage(RAIL0_SET_VOLTAGE);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting Rail 0 voltage to %.3fV: %d\n", (float) RAIL0_SET_VOLTAGE / 1e6, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = pm.rail[0].setEnable(1);
|
||||
if (err != aErrNone) {
|
||||
printf("Error enabling Rail 0: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aTime_MSSleep(CYCLE_TIME);
|
||||
|
||||
int32_t a2d0_voltage;
|
||||
err = stem.analog[0].getVoltage(&a2d0_voltage);
|
||||
if (err != aErrNone) {
|
||||
printf("Error reading A2D0 voltage: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
printf("MTM-PM-1 Rail 0: %.3fV\n", (float) RAIL0_SET_VOLTAGE / 1e6);
|
||||
printf("MTM-USBSTEM A2D0: %.3fV\n", (float) a2d0_voltage / 1e6);
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
|
||||
// 2 - (optional) Toggle MTM-IO-SERIAL USB channel on/off
|
||||
err = ioserial.usb.setPortEnable(USB_CHANNEL);
|
||||
if (err != aErrNone) {
|
||||
printf("Error enabling USB channel %d: %d\n", USB_CHANNEL, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Verify USB device enumeration (optional) and press Enter to continue...\n");
|
||||
std::cin.get();
|
||||
|
||||
err = ioserial.usb.setPortDisable(USB_CHANNEL);
|
||||
if (err != aErrNone) {
|
||||
printf("Error disabling USB channel %d: %d\n", USB_CHANNEL, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// 3 - Set MTM-IO-SERIAL Rail 1 and measure the voltage using MTM-USBSTEM A2D1
|
||||
err = ioserial.rail[1].setVoltage(RAIL1_SET_VOLTAGE);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting Rail 1 voltage to %.3f: %d\n", (float) RAIL1_SET_VOLTAGE / 1e6, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = ioserial.rail[1].setEnable(1);
|
||||
if (err != aErrNone) {
|
||||
printf("Error enabling Rail 1: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aTime_MSSleep(CYCLE_TIME);
|
||||
|
||||
int32_t a2d1_voltage;
|
||||
err = stem.analog[1].getVoltage(&a2d1_voltage);
|
||||
if (err != aErrNone) {
|
||||
printf("Error reading A2D1 voltage: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
printf("MTM-IO-SERIAL Rail 1: %.3fV\n", (float) RAIL1_SET_VOLTAGE / 1e6);
|
||||
printf("MTM-USBSTEM A2D1: %.3fV\n", (float) a2d1_voltage / 1e6);
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
|
||||
stem.disconnect();
|
||||
pm.disconnect();
|
||||
ioserial.disconnect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
###############################################################################
|
||||
# Filename: brainstem_network.py
|
||||
# Prepared By: James Dudley
|
||||
# Date Prepared: March 7, 2018
|
||||
# Date Revised: March 7, 2018
|
||||
# Revision: 0.0.1
|
||||
###############################################################################
|
||||
|
||||
import brainstem # Import BrainStem API
|
||||
from brainstem.result import Result # For easy access to error constants
|
||||
from time import sleep, time
|
||||
|
||||
USB_CHANNEL = 0
|
||||
RAIL0_SET_VOLTAGE = 2200000 # Set voltage for MTM-PM-1 Rail 0
|
||||
RAIL1_SET_VOLTAGE = 2800000 # Set voltage for MTM-IO-SERIAL Rail 1
|
||||
CYCLE_TIME = 0.02 # Time to pause between readings, seconds
|
||||
|
||||
# Generic function to run BrainStem commands with error checking
|
||||
def step(func, func_str, *args):
|
||||
print '>> ' + func_str[0].upper() + func_str[1:] # Capitalize first letter of string
|
||||
res = func(*args)
|
||||
err = val = res
|
||||
if isinstance(val, Result):
|
||||
err = res.error
|
||||
val = res.value
|
||||
else:
|
||||
err = Result.NO_ERROR
|
||||
|
||||
if err is not Result.NO_ERROR:
|
||||
raise Exception('Error %s: %d' % (func_str, err))
|
||||
|
||||
return val
|
||||
|
||||
|
||||
def main():
|
||||
# Create each MTM object
|
||||
# Apply a module offset of 24 to the MTM-PM-1 module (determined by the DIP switch on the development board)
|
||||
ioserial = brainstem.stem.MTMIOSerial() # Uses default module address
|
||||
# Module offset is applied simply to demonstrate module offset, and is not strictly required in this case
|
||||
# Make sure the DIP switch for MTM-PM-1 is set to 1-1-0-0 (0b1100 * 2 = offset of 24)
|
||||
pm = brainstem.stem.MTMPM1(brainstem.stem.MTMPM1.BASE_ADDRESS + 24)
|
||||
stem = brainstem.stem.MTMUSBStem() # Uses default module address
|
||||
|
||||
# Initialize error tracker
|
||||
err = Result.NO_ERROR
|
||||
|
||||
try:
|
||||
# Discover and connect to MTM-IO-SERIAL object
|
||||
# First, get a list of all available USB modules (Note: MTM-PM-1 shows up because there's a pass-through
|
||||
# USB channel on the MTM-IO-SERIAL, which is connected to the MTM-PM-1 edge connector USB on the development board)
|
||||
spec_array = step(brainstem.discover.findAllModules, 'discover USB modules', brainstem.link.Spec.USB)
|
||||
# Next, iterate through each link Spec in the array and connect if it's the MTM-IO-SERIAL module
|
||||
for spec in spec_array:
|
||||
if spec.model == brainstem.defs.MODEL_MTM_IOSERIAL:
|
||||
step(ioserial.connectFromSpec, 'connecting to MTM-IO-SERIAL from spec', spec)
|
||||
break
|
||||
connection_status = step(ioserial.isConnected, 'checking MTM-IO-SERIAL connection status')
|
||||
if connection_status is not True:
|
||||
raise Excepetion('Error finding MTM-IO-SERIAL module: no MTM-IO-SERIAL link Spec discovered')
|
||||
|
||||
# Connect the MTM-PM-1 and MTM-USBSTEM modules over the BrainStem network,
|
||||
# using the MTM-IO-SERIAL as the primary module.
|
||||
step(pm.connectThroughLinkModule, 'connecting to MTM-PM-1 over BS network', ioserial)
|
||||
step(stem.connectThroughLinkModule, 'connecting to MTM-USBSTEM over BS network', ioserial)
|
||||
|
||||
# Set both modules to route through the MTM-IO-SERIAL module (turn "ON" ioserial.routeToMe)
|
||||
step(ioserial.system.routeToMe, 'setting MTM-IO-SERIAL routeToMe', 1)
|
||||
|
||||
# Try out a few examples of functionality from each MTM module
|
||||
|
||||
# 1 - Set MTM-PM-1 Rail 0 and measure the voltage using MTM-USBSTEM A2D0
|
||||
step(pm.rail[0].setVoltage, 'setting Rail 0 voltage to %.3fV' % (RAIL0_SET_VOLTAGE/1.e6), RAIL0_SET_VOLTAGE)
|
||||
step(pm.rail[0].setEnable, 'enabling Rail 0', 1)
|
||||
sleep(CYCLE_TIME)
|
||||
a2d0_voltage = step(stem.analog[0].getVoltage, 'reading A2D0 voltage')
|
||||
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
print 'MTM-PM-1 Rail 0: %.3fV' % (RAIL0_SET_VOLTAGE/1.e6)
|
||||
print 'MTM-USBSTEM A2D0: %.3fV' % (a2d0_voltage / 1.e6)
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
|
||||
# 2 - (optional) Toggle MTM-IO-SERIAL USB channel on/off
|
||||
step(ioserial.usb.setPortEnable, 'enabling USB channel %d' % USB_CHANNEL, USB_CHANNEL)
|
||||
raw_input('Verify USB device enumeration (optional) and press Enter to continue...')
|
||||
step(ioserial.usb.setPortDisable, 'disabling USB channel %d' % USB_CHANNEL, USB_CHANNEL)
|
||||
|
||||
# 3 - Set MTM-IO-SERIAL Rail 1 and measure the voltage using MTM-USBSTEM A2D1
|
||||
step(ioserial.rail[1].setVoltage, 'setting Rail 1 voltage to %.3fV' % (RAIL1_SET_VOLTAGE/1.e6), RAIL1_SET_VOLTAGE)
|
||||
step(ioserial.rail[1].setEnable, 'enabling Rail 1', 1)
|
||||
sleep(CYCLE_TIME)
|
||||
a2d1_voltage = step(stem.analog[1].getVoltage, 'reading A2D1 voltage')
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
print 'MTM-IO-SERIAL Rail 1: %.3fV' % (RAIL1_SET_VOLTAGE/1.e6)
|
||||
print 'MTM-USBSTEM A2D1: %.3fV' % (a2d1_voltage / 1.e6)
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
|
||||
except Exception as exc:
|
||||
print exc
|
||||
|
||||
finally:
|
||||
stem.disconnect() # Clean up possible remaining connections
|
||||
pm.disconnect()
|
||||
ioserial.disconnect()
|
||||
del stem # Clean up MTM objects
|
||||
del pm
|
||||
del ioserial
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/****************************************************************
|
||||
* Filename: continuity_test.cpp
|
||||
* Prepared By: James Dudley
|
||||
* Date Prepared: March 5, 2018
|
||||
* Date Revised: March 5, 2018
|
||||
* Revision: 0.0.1
|
||||
***************************************************************/
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
#define CYCLE_TIME 20 // Time to pause between readings, ms
|
||||
|
||||
uint8_t continuity_pairs[][2] = {{0, 9}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {5, 14}};
|
||||
uint8_t n_cp = 6;
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
// Create BrainStem object
|
||||
aMTMUSBStem stem;
|
||||
|
||||
// Initialize error tracker
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Discover and connect to MTM-USBStem object
|
||||
// Connects to the first USB module discovered
|
||||
err = stem.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
printf("Error connecting to MTM-USBStem: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set DIO configurations
|
||||
uint8_t idx_cp = 0;
|
||||
for (idx_cp = 0; idx_cp < n_cp; idx_cp++) {
|
||||
uint8_t output_dio = continuity_pairs[idx_cp][0];
|
||||
uint8_t input_dio = continuity_pairs[idx_cp][1];
|
||||
|
||||
err = stem.digital[output_dio].setConfiguration(1);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting DIO%d configuration to output: %d\n", output_dio, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = stem.digital[input_dio].setConfiguration(5);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting DIO%d configuration to input with pull-down: %d\n", input_dio, err);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Test continuity between pairs
|
||||
uint8_t continuity_array[n_cp][3];
|
||||
for (idx_cp = 0; idx_cp < n_cp; idx_cp++) {
|
||||
uint8_t output_dio = continuity_pairs[idx_cp][0];
|
||||
uint8_t input_dio = continuity_pairs[idx_cp][1];
|
||||
|
||||
// Check continuity by raising the output HI (1) then LO (0) and verifying
|
||||
// the corresponding input follows
|
||||
uint8_t bContinuous = 1;
|
||||
int8_t state = 1;
|
||||
for (state = 1; state >= 0; state--) {
|
||||
err = stem.digital[output_dio].setState(state);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting DIO%d to %d: %d\n", output_dio, state, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aTime_MSSleep(CYCLE_TIME);
|
||||
|
||||
uint8_t read_state = 0;
|
||||
err = stem.digital[input_dio].getState(&read_state);
|
||||
if (err != aErrNone) {
|
||||
printf("Error getting DIO%d state: %d\n", input_dio, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state != read_state) {
|
||||
bContinuous = 0;
|
||||
}
|
||||
}
|
||||
|
||||
continuity_array[idx_cp][0] = bContinuous;
|
||||
continuity_array[idx_cp][1] = output_dio;
|
||||
continuity_array[idx_cp][2] = input_dio;
|
||||
}
|
||||
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
for (idx_cp = 0; idx_cp < n_cp; idx_cp++) {
|
||||
if (continuity_array[idx_cp][0] == 1) {
|
||||
printf("DIO%d -- DIO%d: Continuous\n", continuity_array[idx_cp][1], continuity_array[idx_cp][2]);
|
||||
} else {
|
||||
printf("DIO%d -- DIO%d: Discontinuous\n", continuity_array[idx_cp][1], continuity_array[idx_cp][2]);
|
||||
}
|
||||
}
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
|
||||
stem.disconnect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
###############################################################################
|
||||
# Filename: continuity_test.py
|
||||
# Prepared By: James Dudley
|
||||
# Date Prepared: March 5, 2018
|
||||
# Date Revised: March 5, 2018
|
||||
# Revision: 0.0.1
|
||||
###############################################################################
|
||||
|
||||
import brainstem # Import BrainStem API
|
||||
from brainstem.result import Result # For easy access to error constants
|
||||
from time import sleep, time
|
||||
|
||||
CONTINUITY_PAIRS = [[0, 9], [1, 10], [2, 11], [3, 12], [4, 13], [5, 14]] # [output, input]
|
||||
CYCLE_TIME = 0.2 # Time to pause between readings, seconds
|
||||
|
||||
# Generic function to run BrainStem commands with error checking
|
||||
def step(func, func_str, *args):
|
||||
print '>> ' + func_str[0].upper() + func_str[1:] # Capitalize first letter of string
|
||||
res = func(*args)
|
||||
err = val = res
|
||||
if isinstance(err, Result):
|
||||
err = res.error
|
||||
val = res.value
|
||||
|
||||
if err is not Result.NO_ERROR:
|
||||
raise Exception('Error %s: %d' % (func_str, err))
|
||||
|
||||
return val
|
||||
|
||||
|
||||
def main():
|
||||
# Create MTM-USBSTEM object
|
||||
stem = brainstem.stem.MTMUSBStem() # Uses default module address
|
||||
|
||||
# Initialize error tracker
|
||||
err = Result.NO_ERROR
|
||||
|
||||
try:
|
||||
# Discover and connect to MTM-PM-1 object
|
||||
# Connects to the first USB module discovered
|
||||
step(stem.discoverAndConnect, 'connecting to MTM-USBStem', brainstem.link.Spec.USB)
|
||||
|
||||
# Set DIO configurations
|
||||
for pair in CONTINUITY_PAIRS:
|
||||
output_dio = pair[0]
|
||||
input_dio = pair[1]
|
||||
step(stem.digital[output_dio].setConfiguration, 'configuring DIO%d as output' % output_dio, 1) # Configuration value from datasheet
|
||||
step(stem.digital[input_dio].setConfiguration, 'configuring DIO%d as input with pull-down' % input_dio, 5) # Configuration value from datasheet
|
||||
|
||||
# Test continuity between pairs
|
||||
continuity_array = []
|
||||
for pair in CONTINUITY_PAIRS:
|
||||
output_dio = pair[0]
|
||||
input_dio = pair[1]
|
||||
|
||||
# Check continuity by raising the output HI (1), then LO (0) and verifying
|
||||
# the corresponding input follows
|
||||
bContinuous = True
|
||||
for state in [1, 0]:
|
||||
step(stem.digital[output_dio].setState, 'setting DIO%d to %d' % (output_dio, state), state)
|
||||
|
||||
sleep(CYCLE_TIME)
|
||||
|
||||
read_state = step(stem.digital[input_dio].getState, 'getting DIO%d state' % input_dio)
|
||||
|
||||
if read_state != state:
|
||||
bContinuous = False
|
||||
|
||||
continuity_array.append([bContinuous, output_dio, input_dio])
|
||||
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
for idx in continuity_array:
|
||||
if idx[0]:
|
||||
print 'DIO%d -- DIO%d: Continuous' % (idx[1], idx[2])
|
||||
else:
|
||||
print 'DIO%d -- DIO%d: Discontinuous' % (idx[1], idx[2])
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
|
||||
except Exception as exc:
|
||||
print exc
|
||||
|
||||
finally:
|
||||
stem.disconnect() # Clean up possible remaining connections
|
||||
del stem # Clean up MTM-USBSTEM object
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/****************************************************************
|
||||
* Filename: led_test.cpp
|
||||
* Prepared By: James Dudley
|
||||
* Date Prepared: February 26, 2018
|
||||
* Date Revised: February 26, 2018
|
||||
* Revision: 0.0.1
|
||||
***************************************************************/
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
#define RESISTOR_VALUE 412
|
||||
#define POWER_VOLTAGE 5000000
|
||||
#define DAC 16
|
||||
#define CURRENT 14
|
||||
#define VOLTAGE 0
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
// Create BrainStem object
|
||||
aMTMDAQ1 daq;
|
||||
|
||||
// Initialize error tracker
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Discover and connect to MTM-DAQ-1 object
|
||||
// Connects to the first USB module discovered
|
||||
err = daq.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
printf("Error connecting to MTM-DAQ-1: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Run the test twice, once with LED power enabled, once with it disabled
|
||||
int8_t enable = 2;
|
||||
for (enable = 1; enable >= 0; enable--) {
|
||||
// Set MTM-DAQ-1 DAC0 (analog 16) to 5V and enable to power LED
|
||||
err = daq.analog[DAC].setVoltage(POWER_VOLTAGE);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting DAC voltage: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
err = daq.analog[DAC].setEnable(enable);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting DAC enable to %d: %d\n", enable, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set measurement ranges
|
||||
err = daq.analog[VOLTAGE].setRange(12);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting Position B analog range to +/-10.24V: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
err = daq.analog[CURRENT].setRange(9);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting Position A->B analog range to +/-5.12V: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aTime_MSSleep(1000); // leave the LED on/off for a second
|
||||
|
||||
// Read voltage measurements
|
||||
int32_t v;
|
||||
err = daq.analog[VOLTAGE].getVoltage(&v);
|
||||
if (err != aErrNone) {
|
||||
printf("Error reading Position B voltage: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
int32_t v_current;
|
||||
err = daq.analog[CURRENT].getVoltage(&v_current);
|
||||
if (err != aErrNone) {
|
||||
printf("Error reading Position A->B differential voltage: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate current
|
||||
int32_t i = v_current / RESISTOR_VALUE; // I = V / R
|
||||
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
if (enable) {
|
||||
printf("MTM-DAQ-1 DAC0 status: enabled\n");
|
||||
} else {
|
||||
printf("MTM-DAQ-1 DAC0 status: disabled\n"); }
|
||||
printf("Position B voltage (uV): %d\n", v);
|
||||
printf("Position B voltage (V): %.3f\n", (float) v / 1e6);
|
||||
printf("Position A->B voltage (uV): %d\n", v_current);
|
||||
printf("Position A->B current (uA): %d\n", i);
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
}
|
||||
|
||||
err = daq.analog[DAC].setEnable(0);
|
||||
if (err != aErrNone) {
|
||||
printf("Error disabling DAC: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
daq.disconnect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
###############################################################################
|
||||
# Filename: led_test.py
|
||||
# Prepared By: James Dudley
|
||||
# Date Prepared: February 26, 2018
|
||||
# Date Revised: February 26, 2018
|
||||
# Revision: 0.0.1
|
||||
###############################################################################
|
||||
|
||||
import brainstem # import BrainStem API
|
||||
from brainstem.result import Result # for easy access to error constants
|
||||
from time import sleep
|
||||
|
||||
RESISTOR_VALUE = 412 # Current-limiting resistor value, Ohms
|
||||
POWER_VOLTAGE = 5000000 # LED power voltage setpoint, uV
|
||||
DAC = 16 # Analog output index for LED power
|
||||
CURRENT = 14 # Differential analog input index for current measurement
|
||||
VOLTAGE = 0 # Single-ended analog input index for voltage measurement
|
||||
|
||||
# Generic function to run BrainStem commands with error checking
|
||||
def step(func, func_str, *args):
|
||||
print '>> ' + func_str[0].upper() + func_str[1:] # Capitalize first letter of string
|
||||
res = func(*args)
|
||||
err = val = res
|
||||
if isinstance(err, Result):
|
||||
err = res.error
|
||||
val = res.value
|
||||
|
||||
if err is not Result.NO_ERROR:
|
||||
raise Exception('Error %s: %d' % (func_str, err))
|
||||
|
||||
return val
|
||||
|
||||
|
||||
def main():
|
||||
# Create MTM-DAQ-1 object
|
||||
daq = brainstem.stem.MTMDAQ1() # Uses default module address
|
||||
|
||||
# Initialize error tracker
|
||||
err = Result.NO_ERROR
|
||||
|
||||
try:
|
||||
# Discover and connect to MTM-DAQ-1 object
|
||||
# Connects to the first USB module discovered
|
||||
step(daq.discoverAndConnect, 'connecting to MTM-DAQ-1', brainstem.link.Spec.USB)
|
||||
|
||||
# Run the test twice, once with LED power enabled, once with it disabled
|
||||
for enable, enable_str in zip([1, 0],['enabled', 'disabled']):
|
||||
# Set MTM-DAQ-1 DAC0 (analog 16) to 5V and enable to power LED
|
||||
step(daq.analog[DAC].setVoltage,'setting DAC voltage', POWER_VOLTAGE) # uV
|
||||
step(daq.analog[DAC].setEnable,'setting DAC enable to %s' % enable_str, enable) # enable DAC0
|
||||
|
||||
# Set measurement ranges
|
||||
step(daq.analog[VOLTAGE].setRange, 'setting Position B analog range to +/-10.24V', 12) # range value from datasheet
|
||||
step(daq.analog[CURRENT].setRange, 'setting Position A->B analog range to +/-5.12V', 9) # range value from datasheet
|
||||
|
||||
sleep(1) # Leave the LED on/off for a second
|
||||
|
||||
# Read voltage measurements
|
||||
v = step(daq.analog[VOLTAGE].getVoltage, 'reading Position B voltage')
|
||||
v_current = step(daq.analog[CURRENT].getVoltage, 'reading Position A-B differential voltage')
|
||||
|
||||
# Calculate current
|
||||
i = v_current / RESISTOR_VALUE # I = V / R
|
||||
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
print 'MTM-DAQ-1 DAC0 status: %s' % enable_str
|
||||
print 'Position B voltage (uV): %d' % v
|
||||
print 'Position B voltage (V): %.3f' % (v / 1e6)
|
||||
print 'Position A->B voltage (uV): %d' % v_current
|
||||
print 'Position A->B current (uA): %d' % i
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
|
||||
step(daq.analog[DAC].setEnable, 'disabling DAC', 0)
|
||||
|
||||
except Exception as exc:
|
||||
print exc
|
||||
|
||||
finally:
|
||||
daq.disconnect() # Clean up possible remaining connections
|
||||
del daq # Clean up MTM-DAQ-1 object
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/****************************************************************
|
||||
* Filename: led_test.cpp
|
||||
* Prepared By: James Dudley
|
||||
* Date Prepared: February 26, 2018
|
||||
* Date Revised: February 26, 2018
|
||||
* Revision: 0.0.1
|
||||
***************************************************************/
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
#define RAIL 1 // Power rail to use for test
|
||||
#define VOLTAGE 3300000 // Set voltage for Rail 0
|
||||
#define CYCLE_TIME 20 // Time to pause between readings, ms
|
||||
#define TOTAL_TIME 5000 // Time to keep test running, seconds
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
// Create BrainStem object
|
||||
aMTMPM1 pm;
|
||||
|
||||
// Initialize error tracker
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Discover and connect to MTM-PM-1 object
|
||||
// Connects to the first USB module discovered
|
||||
err = pm.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
printf("Error connecting to MTM-PM-1: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (RAIL == 0) {
|
||||
// Set Rail voltage
|
||||
err = pm.rail[RAIL].setVoltage(VOLTAGE);
|
||||
if (err != aErrNone) {
|
||||
printf("Error setting Rail %d voltage to %d: %d\n", RAIL, VOLTAGE, err);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable Rail
|
||||
err = pm.rail[RAIL].setEnable(1);
|
||||
if (err != aErrNone) {
|
||||
printf("Error enabling Rail %d: %d\n", RAIL, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t time = 0;
|
||||
while (time < TOTAL_TIME) {
|
||||
time += CYCLE_TIME;
|
||||
// Get MTM-PM-1 Rail enable state
|
||||
uint8_t enable;
|
||||
err = pm.rail[RAIL].getEnable(&enable);
|
||||
if (err != aErrNone) {
|
||||
printf("Error getting Rail %d enable state: %d\n", RAIL, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read MTM-PM-1 Rail voltage
|
||||
int32_t v_rail;
|
||||
err = pm.rail[RAIL].getVoltage(&v_rail);
|
||||
if (err != aErrNone) {
|
||||
printf("Error reading 'sensor' voltage: %d\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
if (enable == 0) {
|
||||
printf("Enable State: OFF\n");
|
||||
} else {
|
||||
printf("Enable State: ON\n");
|
||||
}
|
||||
printf("Rail voltage (V): %.3f\n", (float) v_rail / 1e6);
|
||||
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
|
||||
|
||||
aTime_MSSleep(CYCLE_TIME);
|
||||
}
|
||||
|
||||
err = pm.rail[RAIL].setEnable(0);
|
||||
if (err != aErrNone) {
|
||||
printf("Error disabling Rail %d: %d\n", RAIL, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pm.disconnect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
###############################################################################
|
||||
# Filename: short_test.py
|
||||
# Prepared By: James Dudley
|
||||
# Date Prepared: March 2, 2018
|
||||
# Date Revised: March 2, 2018
|
||||
# Revision: 0.0.1
|
||||
###############################################################################
|
||||
|
||||
import brainstem # Import BrainStem API
|
||||
from brainstem.result import Result # For easy access to error constants
|
||||
from time import sleep, time
|
||||
|
||||
RAIL = 1 # Power rail to use for test
|
||||
VOLTAGE = 3300000 # Set voltage for Rail 0
|
||||
CYCLE_TIME = 0.2 # Time to pause between readings, seconds
|
||||
TOTAL_TIME = 5 # Time to keep test running, seconds
|
||||
|
||||
# Generic function to run BrainStem commands with error checking
|
||||
def step(func, func_str, *args):
|
||||
print '>> ' + func_str[0].upper() + func_str[1:] # Capitalize first letter of string
|
||||
res = func(*args)
|
||||
err = val = res
|
||||
if isinstance(err, Result):
|
||||
err = res.error
|
||||
val = res.value
|
||||
|
||||
if err is not Result.NO_ERROR:
|
||||
raise Exception('Error %s: %d' % (func_str, err))
|
||||
|
||||
return val
|
||||
|
||||
|
||||
def main():
|
||||
# Create MTM-PM-1 object
|
||||
pm = brainstem.stem.MTMPM1() # Uses default module address
|
||||
|
||||
# Initialize error tracker
|
||||
err = Result.NO_ERROR
|
||||
|
||||
try:
|
||||
# Discover and connect to MTM-PM-1 object
|
||||
# Connects to the first USB module discovered
|
||||
step(pm.discoverAndConnect, 'connecting to MTM-PM-1', brainstem.link.Spec.USB)
|
||||
|
||||
if RAIL is 0:
|
||||
# Set Rail voltage
|
||||
step(pm.rail[RAIL].setVoltage,'setting Rail %d voltage to %d' % (RAIL, VOLTAGE), 1)
|
||||
|
||||
# Enable Rail
|
||||
step(pm.rail[RAIL].setEnable,'enabling Rail %d' % RAIL, 1)
|
||||
|
||||
enable_str = ['OFF', 'ON']
|
||||
tStart = tNow = time()
|
||||
while tNow < tStart + TOTAL_TIME:
|
||||
tNow = time()
|
||||
# Get MTM-PM-1 Rail enable state
|
||||
enable = step(pm.rail[RAIL].getEnable, 'reading Rail %d enable state' % RAIL)
|
||||
|
||||
# Read MTM-PM-1 Rail voltage
|
||||
v = step(pm.rail[RAIL].getVoltage, 'reading Rail %d voltage' % RAIL)
|
||||
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
print 'Enable State: %s' % enable_str[enable]
|
||||
print 'Rail voltage (V): %.3f' % (v / 1.e6)
|
||||
print '* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *'
|
||||
|
||||
sleep(CYCLE_TIME)
|
||||
|
||||
step(pm.rail[RAIL].setEnable, 'disabling Rail %d' % RAIL, 0)
|
||||
|
||||
except Exception as exc:
|
||||
print exc
|
||||
|
||||
finally:
|
||||
pm.disconnect() # Clean up possible remaining connections
|
||||
del pm # Clean up MTM-PM-1 object
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
//
|
||||
// main.c
|
||||
// BrainStem2Example C
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdio.h>
|
||||
#include "BrainStem2/BrainStem-C.h"
|
||||
#include "BrainStem2/aProtocoldefs.h"
|
||||
|
||||
aErr getPacket32(aLinkRef stem, uint8_t command, uint8_t option, uint32_t *responseValue);
|
||||
aErr getFirmwareVersion(aLinkRef stem);
|
||||
aErr toggleUserLED(aLinkRef stem);
|
||||
aErr getInputVoltage(aLinkRef stem);
|
||||
|
||||
uint8_t moduleAddress = 0;
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
linkSpec* spec = NULL;
|
||||
aLinkRef stem = 0;
|
||||
aErr err = aErrNone;
|
||||
uint8_t count = 0;
|
||||
uint32_t voltage = 0;
|
||||
|
||||
//Set the global module address (device specific: i.e. 40pin = 2, MTMStem = 4)
|
||||
//Pitfall: Software and Hardware offsets contribute to this value.
|
||||
moduleAddress = 6; // USBHub3p
|
||||
|
||||
printf("Finding the first BrainStem USB module.\n");
|
||||
|
||||
printf("\n");
|
||||
|
||||
spec = aDiscovery_FindFirstModule(USB, LOCALHOST_IP_ADDRESS);
|
||||
|
||||
if (spec != NULL && spec->t.usb.usb_id != 0) {
|
||||
printf("Connecting to BrainStem module %08X\n", spec->t.usb.usb_id);
|
||||
|
||||
// If the link creation fails, a reference identifier of 0 is returned.
|
||||
stem = aLink_CreateUSB(spec->t.usb.usb_id);
|
||||
if (stem == 0) {
|
||||
fprintf(stderr, "Error creating link.\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else{
|
||||
fprintf(stderr, "No BrainStem module was discovered.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
aLinkSpec_Destroy(&spec);
|
||||
|
||||
printf("BrainStem module connected.\n");
|
||||
|
||||
// Wait up to 300 milliseconds for the connection to be established.
|
||||
// Start returns after a transport is established, but communications
|
||||
// may not be ready. When using the C library layer it is up to the user
|
||||
// to check that the connetion is ready and running.
|
||||
|
||||
while ((aLink_GetStatus(stem) != RUNNING) && (count < 30)) {
|
||||
count++;
|
||||
aTime_MSSleep(10);
|
||||
}
|
||||
|
||||
if (count >= 30 && aLink_GetStatus(stem) != RUNNING) {
|
||||
printf("BrainStem connection failed!\n");
|
||||
aLink_Destroy(&stem);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Connected after %d milliseconds.\n", count * 10);
|
||||
|
||||
printf("\n");
|
||||
|
||||
// Get and print the module firmware version
|
||||
printf("Get the module firmware version.\n");
|
||||
err = getFirmwareVersion(stem);
|
||||
if (err != aErrNone) { printf("Error in getFirmwareVersion(): %d\n", err); }
|
||||
|
||||
printf("\n");
|
||||
|
||||
// Get and print the module input voltage
|
||||
// use the generalized getUEI32 interface
|
||||
printf("Get the module input voltage.\n");
|
||||
err = getInputVoltage(stem);
|
||||
if (err != aErrNone) { printf("Error in getInputVoltage(): %d\n", err); }
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("Get the module input voltage with generic interface.\n");
|
||||
err = getPacket32(stem, cmdSYSTEM, systemInputVoltage, &voltage);
|
||||
if (err == aErrNone) { printf("System input voltage: %.3fV\n", (float)voltage/1.0e6); }
|
||||
else { printf("Error in getPacket32(): %d\n", err); }
|
||||
|
||||
printf("\n");
|
||||
|
||||
// Blink the User LED.
|
||||
printf("Toggling the User LED.\n");
|
||||
err = toggleUserLED(stem);
|
||||
if (err != aErrNone) { printf("Error in toggleUserLED(): %d\n", err); }
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (stem != 0) {
|
||||
// Clean up our resources.
|
||||
err = aLink_Destroy(&stem);
|
||||
}
|
||||
|
||||
if (err != aErrNone) { return 1; }
|
||||
else { return 0; }
|
||||
|
||||
}
|
||||
|
||||
// Match for systemVersion
|
||||
static uint8_t sSystemVersion(const aPacket* p, const void* vpRef) {
|
||||
return (p->data[0] == cmdSYSTEM && (p->data[1] & ueiOPTION_MASK) == systemVersion);
|
||||
}
|
||||
aErr getFirmwareVersion(aLinkRef stem){
|
||||
// Set up some packet and data arrays
|
||||
uint8_t pData[aBRAINSTEM_MAXPACKETBYTES];
|
||||
aPacket* packet = NULL;
|
||||
aPacket* response = NULL;
|
||||
aErr err = aErrNone;
|
||||
uint32_t version = 0;
|
||||
|
||||
// Get the module's firmware version
|
||||
pData[0] = cmdSYSTEM;
|
||||
pData[1] = ueiOPTION_GET | systemVersion;
|
||||
pData[2] = ueiSPECIFIER_RETURN_HOST;
|
||||
|
||||
// build a packet with the command
|
||||
packet = aPacket_CreateWithData(moduleAddress,
|
||||
3, // pData length in bytes
|
||||
pData);
|
||||
if (packet != NULL) {
|
||||
// send the command to the module via the link we created
|
||||
err = aLink_PutPacket(stem, packet);
|
||||
if (err != aErrNone) { printf("Error with aLink_PutPacket: %d\n", err); }
|
||||
err = aPacket_Destroy(&packet);
|
||||
if (err != aErrNone) { printf("Error with aPacket_Destroy: %d\n", err); }
|
||||
|
||||
// We await a response here. We could exit or perform some corrective.
|
||||
// action.
|
||||
response = aLink_AwaitFirst(stem, sSystemVersion , NULL, 2000);
|
||||
if (response == NULL) {
|
||||
printf("Error awaiting packet\n");
|
||||
return aErrIO;
|
||||
}
|
||||
|
||||
// grab the version from the response packet
|
||||
version = ((response->data[3])<<24) | ((response->data[4])<<16) |
|
||||
((response->data[5])<<8) | ((response->data[6]));
|
||||
|
||||
//We can, and should, destroy the packet here to clean up.
|
||||
err = aPacket_Destroy(&response);
|
||||
if (err != aErrNone) { printf("Error with aPacket_Destroy: %d\n", err); }
|
||||
} else {
|
||||
// the creation of a packet failed
|
||||
err = aErrMemory;
|
||||
printf("Could not create packet\n");
|
||||
}
|
||||
|
||||
// for pretty-printing, throw out the patch build-hash information;
|
||||
// keep just the patch-version nibble
|
||||
printf("Firmware version: %d.%d.%d\n", aVersion_ParseMajor(version),
|
||||
aVersion_ParseMinor(version), aVersion_ParsePatch(version));
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// Match packet proc. Here we match a systemLED set response.
|
||||
static uint8_t sSystemLED(const aPacket* p, const void* vpRef) {
|
||||
return (p->data[0] == cmdSYSTEM && (p->data[1] & ueiOPTION_MASK) == systemLED);
|
||||
}
|
||||
aErr toggleUserLED(aLinkRef stem){
|
||||
// Set up some packet and data arrays
|
||||
uint8_t pData[4];
|
||||
aPacket* packet = NULL;
|
||||
aPacket* response = NULL;
|
||||
uint8_t i = 0;
|
||||
aErr err = aErrNone;
|
||||
|
||||
for( i = 0; i <= 10; i++) {
|
||||
// create a command to turn the LED to bOn
|
||||
pData[0] = cmdSYSTEM;
|
||||
pData[1] = ueiOPTION_SET | systemLED;
|
||||
pData[2] = ueiSPECIFIER_RETURN_HOST;
|
||||
pData[3] = i%2;
|
||||
|
||||
// build a packet with the command
|
||||
packet = aPacket_CreateWithData(moduleAddress,
|
||||
4, // pData length in bytes
|
||||
pData);
|
||||
if (packet != NULL) {
|
||||
// send the command to the module via the link we created
|
||||
err = aLink_PutPacket(stem, packet);
|
||||
if (err != aErrNone) { printf("Error with aLink_PutPacket: %d\n", err); }
|
||||
err = aPacket_Destroy(&packet);
|
||||
if (err != aErrNone) { printf("Error with aPacket_Destroy: %d\n", err); }
|
||||
// We await a response here. We could exit or perform some corrective.
|
||||
// action.
|
||||
response = aLink_AwaitFirst(stem, sSystemLED , NULL, 2000);
|
||||
if (response == NULL) {
|
||||
printf("error awaiting packet\n");
|
||||
return aErrIO;
|
||||
}
|
||||
//We can, and should, destroy the packet here to clean up.
|
||||
err = aPacket_Destroy(&response);
|
||||
if (err != aErrNone) { printf("Error with aPacket_Destroy: %d\n", err); }
|
||||
} else {
|
||||
// the creation of a packet failed
|
||||
err = aErrMemory;
|
||||
}
|
||||
|
||||
if (err != aErrNone) {
|
||||
fprintf(stderr, "Error %d communicating with BrainStem module, exiting.\n", err);
|
||||
break;
|
||||
}
|
||||
// We use the Acroname aTime utility here to avoid platform specific sleep issues.
|
||||
aTime_MSSleep(250);
|
||||
} // end for i < 10
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// Match for systemInputVoltage
|
||||
static uint8_t sSystemInputVoltage(const aPacket* p, const void* vpRef) {
|
||||
return (p->data[0] == cmdSYSTEM && (p->data[1] & ueiOPTION_MASK) == systemInputVoltage);
|
||||
}
|
||||
aErr getInputVoltage(aLinkRef stem){
|
||||
// Set up some packet and data arrays
|
||||
uint8_t pData[4];
|
||||
aPacket* packet = NULL;
|
||||
aPacket* response = NULL;
|
||||
aErr err = aErrNone;
|
||||
uint32_t voltage = 0;
|
||||
|
||||
// Get the module's firmware version
|
||||
pData[0] = cmdSYSTEM;
|
||||
pData[1] = ueiOPTION_GET | systemInputVoltage;
|
||||
pData[2] = ueiSPECIFIER_RETURN_HOST;
|
||||
|
||||
// build a packet with the command
|
||||
packet = aPacket_CreateWithData(moduleAddress,
|
||||
3, // pData length in bytes
|
||||
pData);
|
||||
if (packet != NULL) {
|
||||
// send the command to the module via the link we created
|
||||
err = aLink_PutPacket(stem, packet);
|
||||
if (err != aErrNone) { printf("Error with aLink_PutPacket: %d\n", err); }
|
||||
err = aPacket_Destroy(&packet);
|
||||
if (err != aErrNone) { printf("Error with aPacket_Destroy: %d\n", err); }
|
||||
|
||||
// We await a response here. We could exit or perform some corrective.
|
||||
// action.
|
||||
response = aLink_AwaitFirst(stem, sSystemInputVoltage , NULL, 2000);
|
||||
//response = aLink_AwaitPacket(stem, 2000);
|
||||
if (response == NULL) {
|
||||
printf("error awaiting packet\n");
|
||||
return aErrIO;
|
||||
}
|
||||
|
||||
// grab the voltage from the response packet
|
||||
voltage = ((response->data[3])<<24) | ((response->data[4])<<16) |
|
||||
((response->data[5])<<8) | ((response->data[6]));
|
||||
|
||||
//We can, and should, destroy the packet here to clean up.
|
||||
err = aPacket_Destroy(&response);
|
||||
if (err != aErrNone) { printf("Error with aPacket_Destroy: %d\n", err); }
|
||||
} else {
|
||||
// the creation of a packet failed
|
||||
err = aErrMemory;
|
||||
}
|
||||
|
||||
// print out the voltage
|
||||
printf("System input voltage: %.3f\n", (float)voltage/1.0e6);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// The above functions are the brute force way to do BrainStem packet handling.
|
||||
// Clearly these can be abstracted into a generic interface (a UEI). The
|
||||
// following sets up a generic packet filter for a given command/option. One
|
||||
// should also check for error packets with matching command/option. This is
|
||||
// left as an exercise for the reader. (Hint: put it in the packet filter and
|
||||
// handle the error packet after the filter).
|
||||
static uint8_t sPacketFilter(const aPacket* packet, const void* vpRef) {
|
||||
aPacket* query = (aPacket*)vpRef;
|
||||
return (packet->address == query->address &&
|
||||
packet->data[0] == query->data[0] &&
|
||||
packet->data[1] == query->data[1]);
|
||||
}
|
||||
aErr getPacket32(aLinkRef stem, uint8_t command, uint8_t option, uint32_t *responseValue){
|
||||
uint8_t pData[4];
|
||||
aPacket* packet = NULL;
|
||||
aPacket* response = NULL;
|
||||
aErr err = aErrNone;
|
||||
|
||||
if(!responseValue){
|
||||
return aErrMemory;
|
||||
}
|
||||
|
||||
// Get the module's firmware version
|
||||
pData[0] = command;
|
||||
pData[1] = ueiOPTION_GET | option;
|
||||
pData[2] = ueiSPECIFIER_RETURN_HOST;
|
||||
|
||||
// build a packet with the command
|
||||
packet = aPacket_CreateWithData(moduleAddress,
|
||||
3, // pData length in bytes
|
||||
pData);
|
||||
if (packet == NULL) {
|
||||
// the creation of a packet failed
|
||||
return aErrMemory;
|
||||
}
|
||||
|
||||
// send the command to the module via the link we created
|
||||
err = aLink_PutPacket(stem, packet);
|
||||
if (err != aErrNone) { printf("Error with aLink_PutPacket: %d\n", err); }
|
||||
err = aPacket_Destroy(&packet);
|
||||
if (err != aErrNone) { printf("Error with aPacket_Destroy: %d\n", err); }
|
||||
|
||||
// We await a response here.
|
||||
// Change the packet to ba a val (response) type with the same cmd/option
|
||||
pData[0] = command;
|
||||
pData[1] = ueiOPTION_VAL | option;
|
||||
pData[2] = ueiSPECIFIER_RETURN_HOST;
|
||||
packet = aPacket_CreateWithData(moduleAddress,
|
||||
3, // pData length in bytes
|
||||
pData);
|
||||
if (packet == NULL) {
|
||||
// the creation of a packet failed
|
||||
return aErrMemory;
|
||||
}
|
||||
|
||||
response = aLink_AwaitFirst(stem, sPacketFilter, packet, 1000);
|
||||
aPacket_Destroy(&packet);
|
||||
if (response == NULL) {
|
||||
printf("error awaiting packet\n");
|
||||
return aErrIO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// grab the version from the response packet
|
||||
// data[0] = command
|
||||
// data[1] = operation|option
|
||||
// data[2] = reply|index
|
||||
// data[3] = high data byte
|
||||
// data[4..] = data bytes...
|
||||
// https://acroname.com/reference/brainstem/appendix/uei.html
|
||||
*responseValue = ((response->data[3])<<24) | ((response->data[4])<<16) |
|
||||
((response->data[5])<<8) | ((response->data[6]));
|
||||
|
||||
//Destroy the response packet here to clean up
|
||||
err = aPacket_Destroy(&response);
|
||||
if (err != aErrNone) { printf("Error with aPacket_Destroy: %d\n", err); }
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
BrainStem 2.0 C Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic example of communication with a BrainStem USB module using the
|
||||
BrainStem Universal Entity Interface (UEI) to read the firmware version, toggle
|
||||
the user LED and measure the input voltage.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CC = gcc
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -Llib/ -lBrainStem2
|
||||
INCLUDES := -Ilib
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CC) $(CFLAGS) BrainStem2Example/main.c $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CC) $(CFLAGS) -DNDEBUG BrainStem2Example/main.c $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
// Created by Acroname Inc. on 1/16/15.
|
||||
// Copyright (c) 2015 Acroname Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BrainStem2/BrainStem-C.h"
|
||||
#include <stdio.h> // standard input / output functions
|
||||
|
||||
#define LIST_LENGTH (128U)
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
DeviceNode_t list[LIST_LENGTH];
|
||||
uint32_t itemsCreated = 0;
|
||||
aErr err = getDownstreamDevices(list, LIST_LENGTH, &itemsCreated);
|
||||
printf("Items Created: %d\n", itemsCreated);
|
||||
|
||||
if (err == aErrNone) {
|
||||
for (uint32_t x = 0; x < itemsCreated; x++) {
|
||||
printf("SN: %X\n", list[x].hubSerialNumber);
|
||||
printf("Port: %X\n", list[x].hubPort);
|
||||
printf(" -VendorID: 0x%04X\n", list[x].idVendor);
|
||||
printf(" -ProductID: 0x%04X\n", list[x].idProduct);
|
||||
printf(" -Serial Number: %s\n", list[x].serialNumber);
|
||||
printf(" -Product: %s\n", list[x].productName);
|
||||
printf(" -Manufacturer: %s\n", list[x].manufacturer);
|
||||
printf(" -Speed: %d\n", list[x].speed);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
else if (err == aErrParam) { printf("One of the parameters you passed in is not valid. \n"); }
|
||||
else if (err == aErrMemory) { printf("Device list does not have enough room. \n"); }
|
||||
else if (err == aErrNotFound) { printf("No Acroname devices were found. \n"); }
|
||||
else { printf("Unknown error case: %d\n", err); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
===============================================================================
|
||||
BrainStem 2.0 C Port Mapping Example
|
||||
===============================================================================
|
||||
|
||||
This examples shows how a user can query the downstream device information
|
||||
of Acronames USB hubs.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CC = gcc
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -Llib/ -lBrainStem2
|
||||
INCLUDES := -Ilib
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CC) $(CFLAGS) BrainStem2Example/main.c $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CC) $(CFLAGS) -DNDEBUG BrainStem2Example/main.c $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// main.c
|
||||
// BrainStem2Example
|
||||
//
|
||||
// Created by Acroname Inc. on 1/16/15.
|
||||
// Copyright (c) 2015 Acroname Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BrainStem2/BrainStem-C.h" //aTime_MSSleep
|
||||
#include "BrainStem2_CCA/CCA_All.h"
|
||||
#include <stdio.h> // standard input / output functions
|
||||
|
||||
#define SYSTEM_INDEX (0U)
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
unsigned int id = 0; //Stem ID. Will be assigned by the module_createStem call.
|
||||
struct Result result;
|
||||
|
||||
//- If autoNetworking is True then moduleAddress has no meaning. Set it to 0
|
||||
//- If model is set and the serial number in discoverAndConnect is 0 then
|
||||
// connection will only occur if the model matches the one provided.
|
||||
// We use 0 here for simplicity.
|
||||
module_createStem(&id, &result, 0, true, 0);
|
||||
|
||||
//- linkType of 1 is used for USB.
|
||||
//- If serialNumber = 0 a connection will be made to the first device that is
|
||||
// found which has a matching model (unless model is 0).
|
||||
//- Special care should be taken when working with multiple stems to ensure
|
||||
// you are connected to the one you expect.
|
||||
module_discoverAndConnect(&id, &result, 1, 0);
|
||||
if(result.error) {
|
||||
printf("Error trying to connect - Error: %d\n", result.error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
system_getSerialNumber(&id, &result, SYSTEM_INDEX);
|
||||
if(aErrNone == result.error) {
|
||||
printf("Serial Number: 0x%08X\n", result.value);
|
||||
}
|
||||
|
||||
printf("Toggling the user LED\n");
|
||||
static const uint8_t TOGGLES = 10;
|
||||
for(uint8_t x = 0; x < TOGGLES; x++) {
|
||||
system_getLED(&id, &result, 0);
|
||||
if(aErrNone == result.error ) {
|
||||
printf("Loop: %d/%d - Current LED State: %d - Changing to %d\n", x+1, TOGGLES, result.value, !result.value);
|
||||
}
|
||||
|
||||
system_setLED(&id, &result, SYSTEM_INDEX, !result.value);
|
||||
|
||||
aTime_MSSleep(1000);
|
||||
}
|
||||
|
||||
system_getInputVoltage(&id, &result, 0);
|
||||
if(aErrNone == result.error) {
|
||||
printf("System Voltage: %.2fVDC\n", result.value/1000000.0);
|
||||
}
|
||||
|
||||
//Disconnect and cleanup memory.
|
||||
module_disconnectAndDestroyStem(&id, &result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
BrainStem 2.0 CCA Example
|
||||
===============================================================================
|
||||
|
||||
This example shows how to use the CCA API.
|
||||
The CCA (C++ to C Abstraction) API provides a C interface while also
|
||||
proving high level features of the C++ interface.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared objects into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CC = gcc
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -Llib/ -lBrainStem2 -lBrainStem2_CCA
|
||||
INCLUDES := -Ilib
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CC) $(CFLAGS) BrainStem2Example/main.c $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
cp lib/libBrainStem2_CCA.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CC) $(CFLAGS) -DNDEBUG BrainStem2Example/main.c $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
cp lib/libBrainStem2_CCA.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2-Client-Cpp-Example
|
||||
//
|
||||
// Created by Acroname Inc. on 5/20/2023.
|
||||
// Copyright (c) 2023 Acroname Inc. All rights reserved.
|
||||
//
|
||||
|
||||
//This example is intended to highlight the multi-process and
|
||||
//network capabilities of BrainStem modules. This application
|
||||
//is intended to be used in conjunction with BrainStem2-Server-Cpp-Example
|
||||
//however, it will work with any application or even HubTool
|
||||
//if configured properly.
|
||||
|
||||
//Note 1:
|
||||
// The actual server is created by the first process to connect to the device.
|
||||
// This means if you run this application first it would create/own
|
||||
// the server. This is intended to smooth over the user experience
|
||||
// but is important to remember when closing applications. If
|
||||
// The "Server" application is closed it will result in the "Clients"
|
||||
// losing access to the device.
|
||||
|
||||
//Note 2:
|
||||
// This application was created with the aUSBHub3p object. If
|
||||
// your devices differs (say a USBCSwitch) you will need to change
|
||||
// all instances of aUSBHub3p to aUSBCSwitch in order to connect to
|
||||
// the device. This is a result of discoveryAndConnect as it will
|
||||
// only connect to a device that matches the object type. It is
|
||||
// possible to use the generic "Module" object; however, this was avoided
|
||||
// in order to present a simplified example.
|
||||
|
||||
//Note 3:
|
||||
// If you intended to connect to a device that is not connected
|
||||
// to your local machine or on your local intranet (local network)
|
||||
// you will need to define a linkSpec with the intended ip and port
|
||||
// number of the device and then use "connectFromSpec".
|
||||
// Discovery works through broadcast and multicast packets;
|
||||
// neither of which work for the internet (global network).
|
||||
// For more connection types see the "Discovery-and-Connection"
|
||||
|
||||
//Note 4:
|
||||
// Additional network details are described in _configure_aEther().
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Macros
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Types
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Function Prototypes
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _configure_aEther(Acroname::BrainStem::Module& m);
|
||||
void _print_aEtherConfig(Acroname::BrainStem::Module& m);
|
||||
void _printProgramInfo(void);
|
||||
void _printFailedConnection(void);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Public Data
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Data
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Public Function Implementations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
aErr e = aErrNone;
|
||||
|
||||
aUSBHub3p stem;
|
||||
//If your module is different, replace it with the appropriate module
|
||||
//Such as a USBCSwitch as shown below.
|
||||
//aUSBCSwitch stem;
|
||||
|
||||
_configure_aEther(stem);
|
||||
e = stem.discoverAndConnect(USB);
|
||||
|
||||
if(aErrNone == e) {
|
||||
_printProgramInfo(); printf("\n");
|
||||
_print_aEtherConfig(stem);
|
||||
|
||||
//Loop for a long time so that we can see the interactions
|
||||
//of the client and server.
|
||||
static const uint32_t NUM_LOOPS = 10000;
|
||||
for(uint32_t x = 0; x < NUM_LOOPS; x++) {
|
||||
if(x % 20 == 0) { printf("Loop: %d\n", x); }
|
||||
|
||||
uint32_t voltage = 0;
|
||||
e = stem.system.getInputVoltage(&voltage);
|
||||
printf("System Input Voltage: %0.3f VDC - error: %d\n",
|
||||
double(voltage)/1000000, e);
|
||||
}
|
||||
|
||||
stem.disconnect();
|
||||
}
|
||||
else { _printFailedConnection(); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Function Implementations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void
|
||||
_printProgramInfo(void) {
|
||||
printf("The aUSBHub3p client has been started.\n");
|
||||
}
|
||||
|
||||
void
|
||||
_configure_aEther(Acroname::BrainStem::Module& m) {
|
||||
//NOTE: Network configuration MUST be done before connecting.
|
||||
Acroname::BrainStem::aEtherConfig config;
|
||||
aErr err = m.getConfig(&config);
|
||||
if(err == aErrNone) {
|
||||
//Controls the exposure of the device. By default,
|
||||
//the device is only exposed on the localhost.
|
||||
//True = localhost(default); False = Public;
|
||||
//config.localOnly = false; //uncomment to test non-default values
|
||||
|
||||
//Controls how strictly we honor the linkType (USB, NETWORK).
|
||||
//Fallback allows for a smoother user experience when getting
|
||||
//familiar with the device; however, it might be helpful to disable
|
||||
//this so that you can control who is the server and who is the client.
|
||||
//For instance if stem.discoverAndConnect(USB) fails it will automatically
|
||||
//try stem.discoverAndConnect(Network) and vise-versa.
|
||||
//True = fallback (default); False = NO fallback
|
||||
//config.fallback = false; //uncomment to test non-default values
|
||||
|
||||
//Controls if the Client-Server model is used. If you prefer to restrict
|
||||
//the device to a single process you can disable this capability.
|
||||
//By default the stem is enabled for multi-process use.
|
||||
//True = Client-Server (default); False = Direct connection (not multi-process)
|
||||
//config.enabled = false; //uncomment to test non-default values
|
||||
|
||||
//Allows the user to select what network interface the stem will be exposed to.
|
||||
//Default = LOCALHOST_IP_ADDRESS; (0 is also accepted for LOCALHOST_IP_ADDRESS);
|
||||
//Available interfaces can be found with aDiscovery_GetIPv4Interfaces
|
||||
//NOTE 1:
|
||||
// If config.localOnly == true; This value is ignored.
|
||||
// If config.localOnly == false; The stem will automatically pick
|
||||
// the highest priority network interface and will ignore 0 and
|
||||
// LOCALHOST_IP_ADDRESS values. However, you may override this value.
|
||||
//config.networkInterface = LOCALHOST_IP_ADDRESS;
|
||||
|
||||
//Apply the configuration.
|
||||
aErr err = m.setConfig(config);
|
||||
if(err) { printf("setConfig Error: %d\n", err); }
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_print_aEtherConfig(Acroname::BrainStem::Module& m) {
|
||||
Acroname::BrainStem::aEtherConfig config;
|
||||
aErr err = m.getConfig(&config);
|
||||
|
||||
char sInterface[INET_ADDRSTRLEN];
|
||||
aDiscovery_ConvertIPv4Interface(config.networkInterface, sInterface, INET_ADDRSTRLEN);
|
||||
|
||||
printf("Current aEther Config (error: %d):\n", err);
|
||||
printf("\t Local Only: %d\n" \
|
||||
"\t Fallback: %d\n" \
|
||||
"\t Server Enabled: %d\n" \
|
||||
"\t Assigned Port: %d\n" \
|
||||
"\t Network Interface: %d (%s)\n", \
|
||||
config.localOnly,
|
||||
config.fallback,
|
||||
config.enabled,
|
||||
config.assignedPort,
|
||||
config.networkInterface,
|
||||
sInterface);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_printFailedConnection(void) {
|
||||
printf("Failed to discover Module\n");
|
||||
printf(" - Confirm device is connected to your machine\n");
|
||||
printf(" - Confirm object type. This examples default is \"aUSBHub3p\"\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
===============================================================================
|
||||
BrainStem2-Client-Cpp-Example Readme
|
||||
===============================================================================
|
||||
|
||||
This example is intended to highlight the multi-process and
|
||||
network capabilities of BrainStem modules. This application
|
||||
is intended to be used in conjunction with BrainStem2-Server-Cpp-Example
|
||||
however, it will work with any application or even HubTool
|
||||
if configured properly.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug:
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
.PHONY : release
|
||||
release:
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2A2DBulkCapture
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
//Constants
|
||||
static const int BULK_CAPTURE_CHANNEL = 0;
|
||||
static const int NUM_SAMPLES = 8000;
|
||||
static const int SAMPLE_RATE = 200000;
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
aErr err = aErrNone;
|
||||
uint8_t captureState = bulkCaptureIdle;
|
||||
|
||||
printf("Creating MTMStem Object\n");
|
||||
aMTMUSBStem stem;
|
||||
|
||||
// Connect to the hardware.
|
||||
// The only difference for TCP/IP modules is to change 'USB' to 'TCP';
|
||||
printf("Attempting to connect\n");
|
||||
err = stem.discoverAndConnect(USB);
|
||||
if (err == aErrNone) printf("Connected\n");
|
||||
else { printf("Error connecting to device\n"); return 1; }
|
||||
|
||||
printf("\n");
|
||||
printf("Configuring Bulk capture\n");
|
||||
printf("Analog Channel: %d\n", BULK_CAPTURE_CHANNEL);
|
||||
printf("Number of Samples: %d\n", NUM_SAMPLES);
|
||||
printf("Sample Rate: %d\n", SAMPLE_RATE);
|
||||
printf("\n");
|
||||
err = stem.analog[BULK_CAPTURE_CHANNEL].setBulkCaptureNumberOfSamples(NUM_SAMPLES);
|
||||
err = stem.analog[BULK_CAPTURE_CHANNEL].setBulkCaptureSampleRate(SAMPLE_RATE);
|
||||
|
||||
printf("\n");
|
||||
printf("Starting bulk capture\n");
|
||||
stem.analog[BULK_CAPTURE_CHANNEL].initiateBulkCapture();
|
||||
//Wait for Bulk Capture to finnish.
|
||||
//You can go do other stuff if you would like... Including other BrainStem functions.
|
||||
//but you will need to check that it is finnished before unloading the data
|
||||
do {
|
||||
err = stem.analog[BULK_CAPTURE_CHANNEL].getBulkCaptureState(&captureState);
|
||||
if(captureState == bulkCaptureError) {
|
||||
printf("There was an Error with Bulk Capture\n");
|
||||
break;
|
||||
}
|
||||
aTime_MSSleep(100);
|
||||
} while(captureState != bulkCaptureFinished);
|
||||
|
||||
//Find out how many samples are in the ram slot
|
||||
size_t nSize = 0;
|
||||
err = stem.store[storeRAMStore].getSlotSize(0, &nSize);
|
||||
|
||||
if (nSize && (err == aErrNone)) {
|
||||
|
||||
uint8_t *rawData = new uint8_t[nSize];
|
||||
uint16_t combinedValue = 0;
|
||||
size_t nSizeUnloaded = 0;
|
||||
printf("Unloading data from the device:\n");
|
||||
err = stem.store[storeRAMStore].unloadSlot(0, nSize, rawData, &nSizeUnloaded);
|
||||
|
||||
// Process 8bit values 2 bytes at a time for a 16bit value (Little Endian)
|
||||
// i.e.
|
||||
// val[0] = XXXXXXXX = LSB's
|
||||
// val[1] = YYYYYYYY = MSB's
|
||||
// combinedVal = YYYYYYYY XXXXXXXX for a 16 bit value
|
||||
// Repeat until all the data has been processed
|
||||
// Note: ",2" increments loop counter "i" by 2
|
||||
for(unsigned int x = 0; x < nSize; x+=2) {
|
||||
combinedValue = 0;
|
||||
combinedValue = rawData[x] + (rawData[x+1] << 8);
|
||||
printf("Sample: %d, \t\tVoltage: %.3f, \tRaw: %d\n", x/2,
|
||||
(combinedValue/65535.0)*3.3,
|
||||
combinedValue);
|
||||
}//end for
|
||||
delete[] rawData;
|
||||
rawData = NULL;
|
||||
}//end if
|
||||
|
||||
printf("Disconnecting from device");
|
||||
err = stem.disconnect();
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
BrainStem2 A2D Bulk Capture C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a C++ example for the BrainStem 2.0 library to demonstrate bulk capturing
|
||||
A2D readings. When run, the module triggers a bulk reading on analog input 0,
|
||||
retrieves the values from the RAM store slot and pipes the readings to STDOUT.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_Brainstem2A2DBulkCapture/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Brainstem2A2DBulkCapture Cpp
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
|
@ -0,0 +1,387 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStemConnectionExample
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2019 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
#include <iostream>
|
||||
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
//declarations
|
||||
void discoverAndConnect_Example();
|
||||
void sDiscover_Example();
|
||||
void findFirstModule_Example();
|
||||
void findModule_Example();
|
||||
void connectFromSpec_Example();
|
||||
void connectThroughLinkModule_Example();
|
||||
|
||||
//Main:
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//This example shows the various ways to discover and connect to BrainStem
|
||||
//modules/devices.
|
||||
//NOTE: Not all functions will be successful. Many of the examples will
|
||||
// require slight modification in order to work with your device.
|
||||
// Please refer to the individual notes/comments in and around
|
||||
// each function.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
int main(int arc, const char* arg[]) {
|
||||
|
||||
discoverAndConnect_Example();
|
||||
|
||||
sDiscover_Example();
|
||||
|
||||
findFirstModule_Example();
|
||||
|
||||
findModule_Example();
|
||||
|
||||
connectFromSpec_Example();
|
||||
|
||||
connectThroughLinkModule_Example();
|
||||
|
||||
cout << "Finished!" << endl;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// discoverAndConnect_Example:
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// This is the most common form of connection. The discovery and connection
|
||||
// process is enveloped into a single function.
|
||||
//
|
||||
// PITFALL: This function requires that the object type matches the device
|
||||
// you are attempting to connect to and will likely require modification
|
||||
// in order to work properly.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
void discoverAndConnect_Example() {
|
||||
|
||||
// Used to catch errors connecting
|
||||
aErr err = aErrNone;
|
||||
// declaring SN variable
|
||||
uint32_t serial_number = 0;
|
||||
|
||||
// TODO:
|
||||
// Uncomment the object that matches your device.
|
||||
|
||||
//a40PinModule stem;
|
||||
//aEtherStem stem;
|
||||
//aMTMStemModule stem;
|
||||
//aMTMEtherStem stem;
|
||||
//aMTMIOSerial stem;
|
||||
//aMTMPM1 stem;
|
||||
//aMTMRelay stem;
|
||||
//aMTMUSBStem stem;
|
||||
//aMTMDAQ1 stem;
|
||||
//aMTMDAQ2 stem;
|
||||
//aUSBHub2x4 stem;
|
||||
aUSBHub3p stem;
|
||||
//aUSBHub3c stem;
|
||||
//aUSBCSwitch stem;
|
||||
//aUSBStem stem;
|
||||
|
||||
//When no serial number is provided discoverAndConnect will attempt to
|
||||
//connect to the first module it finds. If multiple BrainStem devices
|
||||
//are connected to your machine it is unknown which device will be
|
||||
//discovered first.
|
||||
//Under the hood this function uses findFirstModule()
|
||||
|
||||
cout << "Example: discoverAndConnect(USB);" << endl;
|
||||
err = stem.discoverAndConnect(USB);
|
||||
// Connection failure
|
||||
if (err != aErrNone) {
|
||||
cout << "Unable to find BrainStem Module. Error: "<< err << "." << endl;
|
||||
cout << "Are you using the correct Module/Object type?" << endl;
|
||||
}
|
||||
// successful connection
|
||||
else {
|
||||
cout << "Found and Connected to a BrainStem Module." << endl;
|
||||
stem.system.getSerialNumber(&serial_number);
|
||||
}
|
||||
stem.disconnect();
|
||||
cout << endl;
|
||||
|
||||
//discoverAndConnect has an overload which accepts a Serial Number.
|
||||
//The example immediately above will attempt to fetch the serial number
|
||||
//and use it in this example. Feel free to drop in the
|
||||
//serial number of your device.
|
||||
//Under the hood this function uses a combination of sDiscover() and
|
||||
//connectFromSpec().
|
||||
|
||||
// Put the serial number of your device here.
|
||||
uint32_t user_serial_number = serial_number;
|
||||
|
||||
cout << "Example: discoverAndConnect(USB, Serial_Number);" << endl;
|
||||
err = stem.discoverAndConnect(USB, user_serial_number);
|
||||
// unsuccessful connection
|
||||
if (err != aErrNone) {
|
||||
cout << "Unable to find BrainStem Module, Serial Number: " << user_serial_number << ", Error: " << err << endl;
|
||||
cout << "Are you using the Module/Object type?" << endl;
|
||||
}
|
||||
// successful connection
|
||||
else {
|
||||
cout << "Found and Connected to a BrainStem Module." << endl;
|
||||
}
|
||||
stem.disconnect();
|
||||
cout << "Finished with discoverAndConnect example." << endl <<
|
||||
"--------------------------------------------------------" << endl;
|
||||
}// end example
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// sDiscover_Example:
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Highlights how to discover and interrogate multiple BrainStem devices
|
||||
// without connecting to them.
|
||||
// This is especially helpful for device agnostic applications.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void sDiscover_Example(){
|
||||
|
||||
list<linkSpec> specList;
|
||||
|
||||
//USB
|
||||
cout << "Example: Link::sDiscover(USB, specList);" << endl << endl;
|
||||
specList.clear();
|
||||
Acroname::BrainStem::Link::sDiscover(linkType::USB, &specList);
|
||||
for (auto it = specList.begin(); it != specList.end(); it++) {
|
||||
cout << "Model: " << it->model << endl;
|
||||
cout << "Module: " << it->module << endl;
|
||||
cout << "Serial Number: " << it->serial_num << endl;
|
||||
cout << "Router: " << it->router << endl;
|
||||
cout << "Router Serial Number: " << it->router_serial_num << endl;
|
||||
cout << "USB ID: " << it->t.usb.usb_id << endl << endl;
|
||||
}
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
//TCPIP
|
||||
cout << "Example: Link::sDiscover(TCPIP, specList);" << endl << endl;
|
||||
specList.clear();
|
||||
Acroname::BrainStem::Link::sDiscover(linkType::TCPIP, &specList);
|
||||
for (auto it = specList.begin(); it != specList.end(); it++) {
|
||||
cout << "Model: " << it->model << endl;
|
||||
cout << "Module: " << it->module << endl;
|
||||
cout << "Serial Number: " << it->serial_num << endl;
|
||||
cout << "Router: " << it->router << endl;
|
||||
cout << "Router Serial Number: " << it->router_serial_num << endl;
|
||||
cout << "USB ID: " << it->t.usb.usb_id << endl << endl;
|
||||
}
|
||||
cout << "Finished with sDiscover example." << endl <<
|
||||
"--------------------------------------------------------" << endl;
|
||||
}// end example
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// findFirstModule_Example:
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// This example is similar to Discover and Connect, except it connects
|
||||
// the first BrainStem it finds, rather than connecting to a specific
|
||||
// device type.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void findFirstModule_Example() {
|
||||
|
||||
linkSpec *spec = nullptr;
|
||||
|
||||
cout << "Example: findFirstModule(USB);" << endl << endl;
|
||||
spec = aDiscovery_FindFirstModule(linkType::USB, LOCALHOST_IP_ADDRESS);
|
||||
if (spec != nullptr) {
|
||||
cout << "Model: " << spec->model << endl;
|
||||
cout << "Module: " << spec->module << endl;
|
||||
cout << "Serial Number: " << spec->serial_num << endl;
|
||||
cout << "Router: " << spec->router << endl;
|
||||
cout << "Router Serial Number: " << spec->router_serial_num << endl;
|
||||
cout << "USB ID: " << spec->t.usb.usb_id << endl << endl;
|
||||
aLinkSpec_Destroy(&spec); //The spec should be cleaned up when finished.
|
||||
}
|
||||
else { cout << "No USB BrainStem device was found." << endl << endl; }
|
||||
|
||||
|
||||
cout << "Example: findFirstModule(TCPIP);" << endl << endl;
|
||||
spec = nullptr;
|
||||
spec = aDiscovery_FindFirstModule(linkType::TCPIP, LOCALHOST_IP_ADDRESS);
|
||||
if (spec != nullptr) {
|
||||
cout << "Model: " << spec->model << endl;
|
||||
cout << "Module: " << spec->module << endl;
|
||||
cout << "Serial Number: " << spec->serial_num << endl;
|
||||
cout << "Router: " << spec->router << endl;
|
||||
cout << "Router Serial Number: " << spec->router_serial_num << endl;
|
||||
cout << "USB ID: " << spec->t.usb.usb_id << endl << endl;
|
||||
aLinkSpec_Destroy(&spec); //The spec should be cleaned up when finished.
|
||||
}
|
||||
else { cout << "No TCPIP BrainStem device was found." << endl; }
|
||||
|
||||
cout << "Finished with findFirstModule example." << endl <<
|
||||
"--------------------------------------------------------" << endl;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// findModule_Example:
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// This example will connect to any BrainStem device given its serial
|
||||
// number. It will not connect without a SN.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void findModule_Example() {
|
||||
|
||||
//TODO:
|
||||
//Plug in the serial number of your device.
|
||||
|
||||
uint32_t serial_number = 0xB971001E; //Replace with your devices Serial Number.
|
||||
linkSpec *spec = nullptr;
|
||||
|
||||
cout << "Example: findModule(USB, Serial_Number);" << endl << endl;
|
||||
spec = aDiscovery_FindModule(linkType::USB, serial_number, LOCALHOST_IP_ADDRESS);
|
||||
if(spec != nullptr) {
|
||||
cout << "Model: " << spec->model << endl;
|
||||
cout << "Module: " << spec->module << endl;
|
||||
cout << "Serial Number: " << spec->serial_num << endl;
|
||||
cout << "Router: " << spec->router << endl;
|
||||
cout << "Router Serial Number: " << spec->router_serial_num << endl;
|
||||
cout << "USB ID: " << spec->t.usb.usb_id << endl << endl;
|
||||
aLinkSpec_Destroy(&spec); //The spec should be cleaned up when finished.
|
||||
}
|
||||
else { cout << "No USB BrainStem device with serial number " << serial_number << " was found." << endl; }
|
||||
|
||||
|
||||
//For TCP/IP devices. Will not be successful with USB based devices.
|
||||
cout << "Example: findModule(TCPIP, Serial_Number);" << endl << endl;
|
||||
spec = nullptr;
|
||||
spec = aDiscovery_FindModule(linkType::TCPIP, serial_number, LOCALHOST_IP_ADDRESS);
|
||||
if (spec != nullptr) {
|
||||
cout << "Model: " << spec->model << endl;
|
||||
cout << "Module: " << spec->module << endl;
|
||||
cout << "Serial Number: " << spec->serial_num << endl;
|
||||
cout << "Router: " << spec->router << endl;
|
||||
cout << "Router Serial Number: " << spec->router_serial_num << endl;
|
||||
cout << "USB ID: " << spec->t.usb.usb_id << endl << endl;
|
||||
aLinkSpec_Destroy(&spec); //The spec should be cleaned up when finished.
|
||||
}
|
||||
else { cout << "No TCPIP BrainStem device with serial number " << serial_number << " was found." << endl; }
|
||||
|
||||
cout << "Finished with findModule example." << endl <<
|
||||
"--------------------------------------------------------" << endl;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
// connectFromSpec_Example:
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Many of the discovery functions will return a linkSpec object.
|
||||
// This function shows how to use that object to connect to a BrainStem
|
||||
// device.
|
||||
// The benefit of this connection method is that it does not care
|
||||
// about which BrainStem object/module you use.
|
||||
// i.e. you can connect to a USBHub3p from a USBStem object. However,
|
||||
// the USBStem object does not possess a USB Entity and therfor will not be
|
||||
// able to control the USBHub3p correctly. This is typically not
|
||||
// recommended.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void connectFromSpec_Example() {
|
||||
|
||||
aErr err = aErrNone;
|
||||
|
||||
aUSBHub3p stem;
|
||||
|
||||
cout << "Example: connectFromSpec(linkSpec);" << endl << endl;
|
||||
linkSpec* spec = aDiscovery_FindFirstModule(linkType::USB, LOCALHOST_IP_ADDRESS);
|
||||
if (spec != nullptr) {
|
||||
|
||||
err = stem.connectFromSpec(*spec);
|
||||
if (err != aErrNone) {
|
||||
cout << "Unable to connect to BrianStem Module. Error: " << err << endl;
|
||||
}
|
||||
else {
|
||||
cout << "Found and Connected to BrainStem Module" << endl;
|
||||
stem.disconnect();
|
||||
}
|
||||
aLinkSpec_Destroy(&spec); //The spec should be cleaned up when finished.
|
||||
}
|
||||
else { cout << "No BrainStem devices were found." << endl; }
|
||||
|
||||
cout << "Finished with connectFromSpec example." << endl <<
|
||||
"--------------------------------------------------------" << endl;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// connectThroughLinkModule_Example():
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// This function allows a device to share the connection of another device.
|
||||
// This feature is only available for Acroname's MTM and 40pin devices.
|
||||
//
|
||||
// In this example we have a MTMUSBStem and a MTMDAQ2 connected to a BrainStem
|
||||
// development board. The board is powered and ONLY the MTMUSBStem is connected
|
||||
// to the computer via USB cable. The MTMDAQ2 will connect to the PC through the
|
||||
// MTMUSBStem via the BrainStem Network (I2C) which is wired through the
|
||||
// development board.
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
void connectThroughLinkModule_Example() {
|
||||
|
||||
aErr err = aErrNone;
|
||||
|
||||
aUSBHub3p stem;
|
||||
|
||||
cout << "Example: connectThroughLinkModule;" << endl << endl;
|
||||
|
||||
// Create the devices required for this example
|
||||
aMTMUSBStem mtmstem;
|
||||
aMTMDAQ2 mtmdaq2;
|
||||
|
||||
err = mtmstem.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
cout << "Unable to connect to MTMUSBStem Module. Error: " << err << endl;
|
||||
}
|
||||
else {
|
||||
cout << "Found and Connected to MTMUSBStem Module" << endl;
|
||||
|
||||
// Set the route functionality to route all BrainStem Network
|
||||
// traffic to the MTMStem.
|
||||
err = mtmstem.system.routeToMe(1);
|
||||
if(err != aErrNone){
|
||||
cout << "Error routing Traffic to MTMUSBStem. Error: "<< err <<endl;
|
||||
}
|
||||
|
||||
// Now that the MTMUSBStem connection is up and running we can
|
||||
// use its connection to connect to the MTMDAQ2
|
||||
err = mtmdaq2.connectThroughLinkModule(&mtmstem);
|
||||
if (err != aErrNone) {
|
||||
cout << "Unable to connect to MTMDAQ2 Module. Error: " << err << endl;
|
||||
}
|
||||
else {
|
||||
cout << "Connected to MTMDAQ2 Module" << endl;
|
||||
uint8_t LED;
|
||||
string LEDStatus;
|
||||
|
||||
// Once connected you can use the devices normally.
|
||||
LED = 0;
|
||||
err = mtmstem.system.getLED(&LED);
|
||||
if(err == aErrNone) {
|
||||
LEDStatus = (LED == 0 ? "Off" : "On");
|
||||
cout << "MTMUSBStem's User LED: " << LEDStatus << " Error: " << err << endl;
|
||||
}
|
||||
|
||||
LED = 0;
|
||||
err = mtmdaq2.system.getLED(&LED);
|
||||
if(err == aErrNone) {
|
||||
LEDStatus = (LED == 0 ? "Off" : "On");
|
||||
cout << "MTMDAQ2's User LED: " << LEDStatus << " Error: " << err << endl;
|
||||
}
|
||||
|
||||
// You should disconnect in the reverse order in which you connected.
|
||||
mtmdaq2.disconnect();
|
||||
}
|
||||
mtmstem.system.routeToMe(0);
|
||||
mtmstem.disconnect();
|
||||
}
|
||||
|
||||
cout << "Finished with connectThroughLinkModule_Example." << endl <<
|
||||
"--------------------------------------------------------" << endl;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
BrainStem2 C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is an example for the BrainStem 2.0 library to show different ways to connect
|
||||
to BrainStem devices. When run, the executable will connect to user specified
|
||||
devices (as determined by the c++ code.)
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This example walks through some of the basic features of the 40pin USBStem.
|
||||
// More information about the BrainStem API can be found at:
|
||||
// http://acroname.com/reference
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
int main(int argc, const char * argv[]) {
|
||||
// Create BrainStem object
|
||||
aErr err = aErrNone;
|
||||
aUSBStem stem;
|
||||
|
||||
// Find first device and connect.
|
||||
err = stem.discoverAndConnect(USB);
|
||||
// Find a specific device and connect with SN=1234ABCD
|
||||
//err = stem.discoverAndConnect(USB, 0x1234ABCD);
|
||||
|
||||
if (err != aErrNone) {
|
||||
printf("Error connecting to BrainStem (%d).\n", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Reading the BrainStem input voltage.\n\t");
|
||||
uint32_t inputVoltage=0;
|
||||
stem.system.getInputVoltage(&inputVoltage);
|
||||
printf("Input voltage: %.3f\n\n", inputVoltage/1.0e6);
|
||||
|
||||
printf("Flashing the user LED.\n\n");
|
||||
// Toggle the user LED
|
||||
for (int i = 0; i < 10; i++) {
|
||||
stem.system.setLED( i%2 );
|
||||
aTime_MSSleep(250);
|
||||
}
|
||||
|
||||
printf("Reading the analog inputs\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint16_t a2dValue=0;
|
||||
// set the analog to be an input
|
||||
stem.analog[i].setConfiguration(analogConfigurationInput);
|
||||
stem.analog[i].getValue(&a2dValue);
|
||||
printf("%d: %d ", i, a2dValue);
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
printf("Reading the digital inputs\n");
|
||||
printf("\tDigital inputs:");
|
||||
for (int i = 0; i < 15; i++) {
|
||||
uint8_t state=254;
|
||||
// set the analog to be an input
|
||||
stem.digital[i].setConfiguration(digitalConfigurationInput);
|
||||
stem.digital[i].getState(&state);
|
||||
printf(" %d", i);
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
printf("Writing data to I2C[1]\n\n");
|
||||
uint8_t dataout[4]={0,1,2,3};
|
||||
uint8_t addr = 123;
|
||||
stem.i2c[1].setSpeed(2);
|
||||
stem.i2c[1].write(addr, 4, dataout);
|
||||
|
||||
// Disconnect from the module
|
||||
stem.disconnect();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
BrainStem2 C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example using the 40-pin USBStem Module. When run, this
|
||||
example demonstrates reading the input voltage, flashing the user LED, reading
|
||||
the analog and digital inputs and writing data to I2C.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Shell
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
===============================================================================
|
||||
BrainStem2 C++ Empty Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a empty C++ example for the BrainStem 2.0 library. The example has
|
||||
the necessary includes for communicating with BrainStem modules.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Shell/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Shell
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Shell/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Shell
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Shell/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Shell
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2-DevantechI2C-Cpp-Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Devantech CMPSXX sample code
|
||||
// This reads from different compass registers in a single byte transaction
|
||||
// as well as a mulitple byte transaction.
|
||||
// See Devantech's product page for additional register locations and values:
|
||||
// for CMPS11:
|
||||
// http://www.robot-electronics.co.uk/htm/cmps11i2c.htm
|
||||
// for CMPS03
|
||||
// http://www.robot-electronics.co.uk/htm/cmps3tech.htm
|
||||
|
||||
void CMPSXX_Test(a40PinModule &stem);
|
||||
|
||||
void CMPSXX_Test(a40PinModule &stem)
|
||||
{
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Factory default compass address
|
||||
uint8_t cmpsxx_addr = 0xC0;
|
||||
uint8_t dataout[4];
|
||||
uint8_t datain[6];
|
||||
uint8_t bus = 0;
|
||||
|
||||
printf("Communicating with CMPSXX module at default I2C address: 0x%02X\n", cmpsxx_addr);
|
||||
|
||||
// Define the register address we want to set
|
||||
dataout[0] = 0; // software version
|
||||
|
||||
// Set the bus speed setting on the I2C object to 100Khz
|
||||
err = stem.i2c[bus].setSpeed(i2cSpeed_100Khz);
|
||||
|
||||
// Set the compass module register pointer
|
||||
err = stem.i2c[bus].write(cmpsxx_addr, 1, dataout);
|
||||
|
||||
// if we had an error, we likely don't have it wired up, correct address,...
|
||||
if (err != aErrNone)
|
||||
printf("Failure communicating with CMPXX at default I2C address: 0x%02X\n", cmpsxx_addr);
|
||||
|
||||
// Read the compass firwmare version as a single byte
|
||||
if (err == aErrNone)
|
||||
err = stem.i2c[bus].read(cmpsxx_addr, 1, datain);
|
||||
|
||||
// Print the results back to us
|
||||
if (err == aErrNone)
|
||||
printf(" CMPSXX firmware version: %d\n", datain[0]);
|
||||
else // end of if for printing result
|
||||
printf("Error reading version: %d\n", err);
|
||||
|
||||
// read the compass bearing register
|
||||
|
||||
// Define the register address we want to set
|
||||
dataout[0] = 1; // compass bearing register location
|
||||
|
||||
// Set the compass module register pointer
|
||||
err = stem.i2c[bus].write(cmpsxx_addr, 1, dataout);
|
||||
|
||||
// Read multiple (4) bytes from the compass
|
||||
if (err == aErrNone)
|
||||
err = stem.i2c[bus].read(cmpsxx_addr, 4, datain);
|
||||
|
||||
// print the results when we get no error
|
||||
if (err == aErrNone) {
|
||||
|
||||
printf(" Devantech CMPSXX bearing as byte [0-255] : %d\n", datain[0]);
|
||||
printf(" Devantech CMPSXX bearing as word [0-3599]: %d\n", datain[1] << 8 | datain[2]);
|
||||
|
||||
} else { // end of if for printing result
|
||||
printf("Error reading multiple bytes: %d\n", err);
|
||||
}
|
||||
} // end CMPSXX_Test
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
|
||||
printf("Creating a 40 Pin module\n");
|
||||
|
||||
// Create an instance of a 40Pin module. Adjust appropriately for target
|
||||
// hardware
|
||||
a40PinModule stem;
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Connect to the hardware.
|
||||
// The only difference for TCP/IP modules is to change 'USB' to 'TCP';
|
||||
//err = stem.discoverAndConnect(USB, 0x40F5849A); // for a known serial number
|
||||
err = stem.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
printf("Error %d encountered connectoring to BrainStem module\n", err);
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
uint32_t serial_num;
|
||||
stem.system.getSerialNumber(&serial_num);
|
||||
printf("Connected to BrainStem module [%08X].\n", serial_num);
|
||||
}
|
||||
|
||||
// Communicate and test a Devantech CMPSXX module
|
||||
if (err == aErrNone)
|
||||
CMPSXX_Test(stem);
|
||||
|
||||
// Disconnect
|
||||
err = stem.disconnect();
|
||||
if (err == aErrNone) {
|
||||
printf("Disconnnected from BrainStem module.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
===============================================================================
|
||||
BrainStem2-DevantechI2C-Cpp-Example C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the talking to Devantech I2C devices.
|
||||
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2-DevantechI2C-Cpp-Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# BrainStem2-DevantechI2C-Cpp-Example Cpp
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2-DevantechI2C-Cpp-Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2-DevantechI2C-Cpp/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2-DevantechI2C-Cpp
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2-DevantechI2C-Cpp/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2-DevantechI2C-Cpp
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
//Note: This example assumes you have a device connected to the rail 0 and is
|
||||
// capable of allowing 5VDC @ 100mA.
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
std::cout << "Creating a MTMLoad1 module" << std::endl;
|
||||
|
||||
// Create an instance of the MTMLoad1 module
|
||||
aMTMLoad1 stem;
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Connect to the hardware.
|
||||
// The only difference for TCP/IP modules is to change "USB" to "TCP";
|
||||
// err = stem.discoverAndConnect(USB, 0x40F5849A); // for a known serial number
|
||||
err = stem.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered connecting to BrainStem module" << std::endl;
|
||||
return 1;
|
||||
|
||||
}
|
||||
else {
|
||||
uint32_t sn;
|
||||
err = stem.system.getSerialNumber(&sn);
|
||||
printf("Connected to BrainStem module. SN: 0x%08X. Error: %d\n", sn, err);
|
||||
}
|
||||
|
||||
//Operational modes are defined in aProtocoldefs.h (development/lib/BrainStem2/)
|
||||
//Device specific configurations/capabilities can be found in the product datasheet.
|
||||
//0x01 = (railOperationalModeConstantCurrent_Value(0x00) | railOperationalModeLinear_Value(0x01))
|
||||
stem.rail[0].setOperationalMode(railOperationalModeConstantCurrent_Value | railOperationalModeLinear_Value);
|
||||
|
||||
printf("Setting load rail 0 to draw 0.1A\n");
|
||||
stem.rail[0].setCurrentSetpoint(100000); //Current is in microamps
|
||||
|
||||
printf("Setting load rail 0 max voltage to 5.0V\n");
|
||||
stem.rail[0].setVoltageMaxLimit(5000000);
|
||||
|
||||
printf("Enabling load rail 0\n");
|
||||
stem.rail[0].setEnable(true);
|
||||
|
||||
printf("Allowing time for the rail to stabilize\n");
|
||||
aTime_MSSleep(1000); //Sleep for 1 second.
|
||||
|
||||
int32_t voltage = 0;
|
||||
err = stem.rail[0].getVoltage(&voltage);
|
||||
printf("Voltage: %d microvolts, Error: %d\n", voltage, err);
|
||||
|
||||
int32_t current = 0;
|
||||
err = stem.rail[0].getCurrent(¤t);
|
||||
printf("Current: %d microamps, Error: %d\n", current, err);
|
||||
|
||||
printf("Disabling load rail 0\n");
|
||||
stem.rail[0].setEnable(false);
|
||||
|
||||
// Disconnect
|
||||
err = stem.disconnect();
|
||||
if (err == aErrNone) {
|
||||
std::cout << "Disconnected from BrainStem module." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
MTM-Load-1 C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the MTM-Load-1. When executed, this example
|
||||
programs the MTM-Load-1 to provide a constant 0.1 A load, enables the voltage rail
|
||||
to 5 volts and measures the actual voltage and current draw of the load.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2-Server-Cpp-Example
|
||||
//
|
||||
// Created by Acroname Inc. on 5/20/2023.
|
||||
// Copyright (c) 2023 Acroname Inc. All rights reserved.
|
||||
//
|
||||
|
||||
//This example is intended to highlight the multi-process and
|
||||
//network capabilities of BrainStem modules. This application
|
||||
//is intended to be used in conjunction with a "client" example (Any API)
|
||||
//however, it will work with any application or even HubTool
|
||||
//if configured properly.
|
||||
|
||||
//Note 1:
|
||||
// Although this is labeled as the "Server" application this
|
||||
// is a bit misleading. The actual server is created by the
|
||||
// first process to connect to the device.
|
||||
// This means you could run the "Client" or even HubTool first in
|
||||
// which it would create/own the server and this application would be
|
||||
// a client. This is intended to smooth over the user experience
|
||||
// but is important to remember when closing applications. If
|
||||
// The "Server" application is closed it will result in the "Clients"
|
||||
// losing access to the device.
|
||||
|
||||
//Note 2:
|
||||
// This application was created with the aUSBHub3p object. If
|
||||
// your devices differs (say a USBCSwitch) you will need to change
|
||||
// all instances of aUSBHub3p to aUSBCSwitch in order to connect to
|
||||
// the device. This is a result of discoveryAndConnect as it will
|
||||
// only connect to a device that matches the object type. It is
|
||||
// possible to use the generic "Module" object; however, this was avoided
|
||||
// in order to present a simplified example. For more connection types
|
||||
// see the "Discovery-and-Connection"
|
||||
|
||||
//Note 3:
|
||||
// If you intended to connect to a device that is not connected
|
||||
// to your local machine or on your local intranet (local network)
|
||||
// you will need to define a linkSpec with the intended ip and port
|
||||
// number of the device and then use "connectFromSpec".
|
||||
// Discovery works through broadcast and multicast packets;
|
||||
// neither of which work for the internet (global network).
|
||||
// For more connection types see the "Discovery-and-Connection"
|
||||
|
||||
//Note 4:
|
||||
// Additional network details are described in _configure_aEther().
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <future>
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Macros
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Types
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Function Prototypes
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<std::string> _parseArgs(const std::string &s, char delim);
|
||||
bool _handleCLI(Acroname::BrainStem::Module& m);
|
||||
void _configure_aEther(Acroname::BrainStem::Module& m);
|
||||
void _printProgramInfo(void);
|
||||
void _printCLIOutput(void);
|
||||
void _printFailedConnection(void);
|
||||
void _print_aEtherConfig(Acroname::BrainStem::Module& m);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Public Data
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Data
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Public Function Implementations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
aErr e = aErrNone;
|
||||
|
||||
aUSBHub3p stem;
|
||||
//If your module is different, replace it with the appropriate module
|
||||
//Such as a USBCSwitch as shown below.
|
||||
//aUSBCSwitch stem;
|
||||
|
||||
_configure_aEther(stem);
|
||||
e = stem.discoverAndConnect(USB);
|
||||
if(aErrNone == e) {
|
||||
_printProgramInfo(); printf("\n");
|
||||
_print_aEtherConfig(stem); printf("\n");
|
||||
_printCLIOutput();
|
||||
|
||||
//Start thread for CLI stuff.
|
||||
while(_handleCLI(stem)) { }
|
||||
stem.disconnect();
|
||||
}
|
||||
else { _printFailedConnection(); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Function Implementations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _configure_aEther(Acroname::BrainStem::Module& m) {
|
||||
//NOTE: Network configuration MUST be done before connecting.
|
||||
Acroname::BrainStem::aEtherConfig config;
|
||||
aErr err = m.getConfig(&config);
|
||||
if(err == aErrNone) {
|
||||
//Controls the exposure of the device. By default,
|
||||
//the device is only exposed on the localhost.
|
||||
//True = localhost(default); False = Public;
|
||||
//config.localOnly = false; //uncomment to test non-default values
|
||||
|
||||
//Controls how strictly we honor the linkType (USB, NETWORK).
|
||||
//Fallback allows for a smoother user experience when getting
|
||||
//familiar with the device; however, it might be helpful to disable
|
||||
//this so that you can control who is the server and who is the client.
|
||||
//For instance if stem.discoverAndConnect(USB) fails it will automatically
|
||||
//try stem.discoverAndConnect(Network) and vise-versa.
|
||||
//True = fallback (default); False = NO fallback
|
||||
//config.fallback = false; //uncomment to test non-default values
|
||||
|
||||
//Controls if the Client-Server model is used. If you prefer to restrict
|
||||
//the device to a single process you can disable this capability.
|
||||
//By default the stem is enabled for multi-process use.
|
||||
//True = Client-Server (default); False = Direct connection (not multi-process)
|
||||
//config.enabled = false; //uncomment to test non-default values
|
||||
|
||||
//Allows the user to select what network interface the stem will be exposed to.
|
||||
//Default = LOCALHOST_IP_ADDRESS; (0 is also accepted for LOCALHOST_IP_ADDRESS);
|
||||
//Available interfaces can be found with aDiscovery_GetIPv4Interfaces
|
||||
//NOTE: If config.localOnly == true; This value is ignored.
|
||||
// If config.localOnly == false; The stem will automatically pick
|
||||
// the highest priority network interface and will ignore 0 and
|
||||
// LOCALHOST_IP_ADDRESS values. However, you may override this value.
|
||||
//config.networkInterface = LOCALHOST_IP_ADDRESS;
|
||||
|
||||
//Apply the configuration.
|
||||
aErr err = m.setConfig(config);
|
||||
if(err) { printf("setConfig Error: %d\n", err); }
|
||||
}
|
||||
}
|
||||
|
||||
void _print_aEtherConfig(Acroname::BrainStem::Module& m) {
|
||||
Acroname::BrainStem::aEtherConfig config;
|
||||
aErr err = m.getConfig(&config);
|
||||
|
||||
char sInterface[INET_ADDRSTRLEN];
|
||||
aDiscovery_ConvertIPv4Interface(config.networkInterface, sInterface, INET_ADDRSTRLEN);
|
||||
|
||||
printf("Current aEther Config (error: %d):\n", err);
|
||||
printf("\t Local Only: %d\n" \
|
||||
"\t Fallback: %d\n" \
|
||||
"\t Server Enabled: %d\n" \
|
||||
"\t Assigned Port: %d\n" \
|
||||
"\t Network Interface: %d (%s)\n", \
|
||||
config.localOnly,
|
||||
config.fallback,
|
||||
config.enabled,
|
||||
config.assignedPort,
|
||||
config.networkInterface,
|
||||
sInterface);
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string>
|
||||
_parseArgs(const std::string &s, char delim) {
|
||||
std::vector<std::string> result;
|
||||
std::stringstream ss (s);
|
||||
std::string item;
|
||||
|
||||
while (getline (ss, item, delim)) {
|
||||
result.push_back (item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_handleCLI(Acroname::BrainStem::Module& m) {
|
||||
|
||||
std::string s;
|
||||
getline(std::cin, s);
|
||||
std::vector<std::string> args = _parseArgs(s, 0x20);
|
||||
aErr err = aErrNone;
|
||||
|
||||
bool commandFound = true;
|
||||
Acroname::BrainStem::SystemClass sys;
|
||||
sys.init(&m, 0);
|
||||
|
||||
if(args.size() == 1) {
|
||||
if(args.at(0) == "exit") { return false; }
|
||||
else if(args.at(0) == "led") {
|
||||
uint8_t led = 0;
|
||||
err = sys.getLED(&led);
|
||||
printf("Get LED value: %d - error: %d\n", led, err);
|
||||
}
|
||||
else if(args.at(0) == "voltage") {
|
||||
uint32_t voltage = 0;
|
||||
err = sys.getInputVoltage(&voltage);
|
||||
printf("System Input Voltage: %0.3f VDC - error: %d\n",
|
||||
double(voltage)/1000000, err);
|
||||
}
|
||||
else { commandFound = false; }
|
||||
}
|
||||
else if(args.size() == 2) {
|
||||
if(args.at(0) == "led") {
|
||||
unsigned int led = atoi(args.at(1).c_str());
|
||||
sys.setLED(led);
|
||||
printf("Set LED value: %d - error: %d\n", led, err);
|
||||
}
|
||||
else { commandFound = false; }
|
||||
}
|
||||
else { commandFound = false; }
|
||||
|
||||
|
||||
if(! commandFound) {
|
||||
printf("Unknown command with (%d) parameters\n", (uint32_t)args.size());
|
||||
_printCLIOutput();
|
||||
}
|
||||
|
||||
s.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
_printProgramInfo(void) {
|
||||
printf("The aUSBHub3p server has been started.\n");
|
||||
printf("You can now access this device from another process.\n");
|
||||
printf("Build and run the \"client\" example to see it in action.\n");
|
||||
printf("Additionally you can still issue commands to this process.\n");
|
||||
}
|
||||
|
||||
void
|
||||
_printCLIOutput(void) {
|
||||
printf("Commands: \n");
|
||||
printf("\t exit - Exits this application \n");
|
||||
printf("\t voltage - Gets the system input voltage\n");
|
||||
printf("\t led - Gets the current led value \n");
|
||||
printf("\t led <value> - Sets the led to the defined value (0/1)\n");
|
||||
}
|
||||
|
||||
void
|
||||
_printFailedConnection(void) {
|
||||
printf("Failed to discover Module\n");
|
||||
printf(" - Confirm device is connected to your machine\n");
|
||||
printf(" - Confirm object type. This examples default is \"aUSBHub3p\"\n");
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
===============================================================================
|
||||
BrainStem2-Server-Cpp-Example
|
||||
===============================================================================
|
||||
|
||||
This example is intended to highlight the multi-process and
|
||||
network capabilities of BrainStem modules. This application
|
||||
is intended to be used in conjunction with BrainStem2-Client-Cpp-Example
|
||||
however, it will work with any application or even HubTool
|
||||
if configured properly.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2 -pthread
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2019 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This Example shows basic interaction with the MTMUSBStem. Please see the
|
||||
// the product datasheet and the reference material at: http://acroname.com/reference
|
||||
// 1. Create a MTMUSBStem object and connect.
|
||||
// 2. Configure the MTMUSBStem to output a square wave via digital pin 6.
|
||||
// 3. Set the T3 Time for signal entity 2 to 100000000.
|
||||
// 4. Get and display the T3 Time for signal entity 2.
|
||||
// 5. Set the T2 Time for signal entity 2 to 50000000.
|
||||
// 6. Get and display the T2 Time for signal entity 2.
|
||||
// 7. Enable the signal output on signal entity 2.
|
||||
// 8. Configure the MTMUSBStem to receive a square wave via digital pin 4.
|
||||
// 9. Enable the signal input on signal entity 0.
|
||||
// 10. Get and display the T3 Time for signal entity 0.
|
||||
// 11. Get and display the T2 Time for signal entity 0.
|
||||
// 12. Calculate the Duty Cycle with the read T3 and T2 values.
|
||||
// 13. Disable the signal output on signal entity 2.
|
||||
// 14. Disable the signal input on signal entity 0.
|
||||
// 15. Disconnect from the MTMUSBStem object.
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
#include "BrainStem2/aMTMUSBStem.h"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
std::cout << "Creating a signal loopback, between digital pins 6 and 4, with a MTMUSBStem module" << std::endl << std::endl << std::endl;
|
||||
|
||||
// Lookup Table for Signal to Digital Mapping
|
||||
// The indicies refer to the signal [0-4], while the values
|
||||
// held in those indicies refer to the digital pins they
|
||||
// are associated with.
|
||||
// Note: This Lookup Table is for the MTMUSBStem only.
|
||||
// Digital Entity to Signal Entity mapping varies per
|
||||
// device. Please refer to the data sheet for the MTM
|
||||
// Device you are using to see its unique mapping.
|
||||
const int signalToDigitalMapping[] = {4, 5, 6, 7, 8};
|
||||
|
||||
// T Times to be set. Editable by user
|
||||
const uint32_t T3_TIME = 100000000;
|
||||
const uint32_t T2_TIME = 50000000;
|
||||
|
||||
// Signal Entity indexs to be used for input and output.
|
||||
const uint8_t SIGNAL_OUTPUT_IDX = 2;
|
||||
const uint8_t SIGNAL_INPUT_IDX = 0;
|
||||
|
||||
aMTMUSBStem usbstem; // Create an instance of a MTMUSBStem module
|
||||
aErr err = aErrNone; // aErr variable which will hold the return value of the last command executed
|
||||
|
||||
uint32_t readFromOutputT3Time = 0; // T3 Time read from signal entity 2
|
||||
uint32_t readFromOutputT2Time = 0; // T2 Time read from signal entity 2
|
||||
uint32_t readFromInputT3Time = 0; // T3 Time read from signal entity 0
|
||||
uint32_t readFromInputT2Time = 0; // T2 Time read from signal entity 0
|
||||
|
||||
// Connect to the hardware.
|
||||
// The only difference for TCP/IP modules is to change 'USB' to 'TCP';
|
||||
err = usbstem.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered connecting to BrainStem module. Aborting example!" << std::endl;
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
std::cout << "Connected to BrainStem module." << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
/*
|
||||
* Output
|
||||
*/
|
||||
|
||||
// Configure the MTMUSBStem to output a square wave via digital pin 6
|
||||
err = usbstem.digital[signalToDigitalMapping[SIGNAL_OUTPUT_IDX]].setConfiguration(digitalConfigurationSignalOutput);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to set the configuration for digital pin 6 on the MTMUSBStem. Aborting example!" << std::endl << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Set the T3 Time for signal entity 2 to 100000000
|
||||
err = usbstem.signal[SIGNAL_OUTPUT_IDX].setT3Time(T3_TIME);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to set the T3 Time for signal entity 2 on the MTMUSBStem. Aborting example!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get and display the T3 Time from signal entity 2
|
||||
err = usbstem.signal[SIGNAL_OUTPUT_IDX].getT3Time(&readFromOutputT3Time);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to get the T3 Time for signal entity 2 on the MTMUSBStem." << std::endl;
|
||||
}
|
||||
else if (readFromOutputT3Time == 0) {
|
||||
std::cout << "T3 Time cannot be 0. Aborting example!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
std::cout << "T3 Time from Output Pin: " << readFromOutputT3Time << std::endl;
|
||||
}
|
||||
|
||||
// Set the T2 Time for signal entity 2 to 50000000
|
||||
err = usbstem.signal[SIGNAL_OUTPUT_IDX].setT2Time(T2_TIME);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to set the T2 Time for signal entity 2 on the MTMUSBStem. Aborting example!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get and display the T2 Time from signal entity 2
|
||||
err = usbstem.signal[SIGNAL_OUTPUT_IDX].getT2Time(&readFromOutputT2Time);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to get the T2 Time for signal entity 2 on the MTMUSBStem" << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "T2 Time from Output Pin: " << readFromOutputT2Time << std::endl;
|
||||
}
|
||||
|
||||
err = usbstem.signal[SIGNAL_OUTPUT_IDX].setEnable(true);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to set the signal enabled state of signal entity 2 to true on the MTMUSBStem. Aborting example!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
/*
|
||||
* Input
|
||||
*/
|
||||
|
||||
// Configure the MTMUSBStem to receive a square wave via digital pin 4
|
||||
err = usbstem.digital[signalToDigitalMapping[SIGNAL_INPUT_IDX]].setConfiguration(digitalConfigurationSignalInput);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to set the configuration for digital pin 4 on the MTMUSBStem. Aborting example!" << std::endl << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Enable the signal input on signal entity 0
|
||||
err = usbstem.signal[SIGNAL_INPUT_IDX].setEnable(true);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to set the signal enabled state of signal entity 0 to true on the MTMUSBStem. Aborting example!" << std::endl << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sleep for 500ms so the ouput can stabilize
|
||||
* and the input can have time to calculate the
|
||||
* time high/low
|
||||
*/
|
||||
aTime_MSSleep(500);
|
||||
|
||||
// Get and display the T3 Time from signal entity 0
|
||||
err = usbstem.signal[SIGNAL_INPUT_IDX].getT3Time(&readFromInputT3Time);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to get the T3 Time for signal entity 0 on the MTMUSBStem. Aborting example!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else if (readFromInputT3Time == 0) {
|
||||
std::cout << "T3 Time cannot be 0. Aborting example!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
std::cout << "T3 Time from Input Pin: " << readFromInputT3Time << std::endl;
|
||||
}
|
||||
|
||||
// Get and display the T2 Time from signal entity 0
|
||||
err = usbstem.signal[SIGNAL_INPUT_IDX].getT2Time(&readFromInputT2Time);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to get the T2 Time for signal entity 0 on the MTMUSBStem. Aborting example!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
std::cout << "T2 Time from Input Pin: " << readFromInputT2Time << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
double dutyCycle = ((double)readFromInputT2Time / (double)readFromInputT3Time) * 100.0; // Calculate the Duty Cycle
|
||||
|
||||
std::cout << "Duty Cycle: "<< dutyCycle << std::endl << std::endl; // Display the Duty Cycle
|
||||
|
||||
// Disable the signal output on signal entity 2
|
||||
err = usbstem.signal[SIGNAL_OUTPUT_IDX].setEnable(false);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to set the signal enabled state of signal entity 2 to false on the MTMUSBStem" << std::endl;
|
||||
}
|
||||
|
||||
// Disable the signal input on signal entity 0
|
||||
err = usbstem.signal[SIGNAL_INPUT_IDX].setEnable(false);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered attempting to set the signal enabled state of signal entity 0 to false on the MTMUSBStem" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
usbstem.disconnect(); // Disconnect from the MTMUSBStem
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
===============================================================================
|
||||
MTM-USBStem C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the MTM-USBStem that demonstrates some of its
|
||||
digital signal capabilities.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
137
api/examples/c_cpp/BrainStem2-USBC-Switch-Cpp-Example/BrainStem2Example/main.cpp
Executable file
137
api/examples/c_cpp/BrainStem2-USBC-Switch-Cpp-Example/BrainStem2Example/main.cpp
Executable file
|
|
@ -0,0 +1,137 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This Example shows basic interaction with the USBC-Switch. Please see the
|
||||
// the product datasheet and the reference material at: http://acroname.com/reference
|
||||
// 1. Create a switch object and connect.
|
||||
// 2. Set up the mux channel to channel 0, enable the common side
|
||||
// via the USB entity, and enable the mux side.
|
||||
// 3. Disable the connection on the common side via the USB entity.
|
||||
// 4. Change the mux channel to channel 1.
|
||||
// 5. Enable the connection on the common side via the USB entity.
|
||||
// 6. Poll current and voltage once a second for MAX_LOOP seconds.
|
||||
// 7. Disable the connection on the mux side via mux.setEnable.
|
||||
// 8. Change the mux channel to channel 1.
|
||||
// 9. Enable the connection on the mux side via mux.setEnable.
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
// The common side USB is always channel 0 on the USBCSwitch.
|
||||
#define USBC_COMMON 0
|
||||
|
||||
// Defines for enabling and disabling the mux channel.
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
|
||||
// Number of times current and voltage will be printed.
|
||||
#define LOOP_MAX 5
|
||||
|
||||
#include "BrainStem2/aUSBCSwitch.h"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
std::cout << "Creating a USBCSwitch module" << std::endl;
|
||||
|
||||
// Create an instance of a USBCSwitch module.
|
||||
aUSBCSwitch cswitch;
|
||||
aErr err = aErrNone;
|
||||
uint8_t count;
|
||||
|
||||
// Connect to the hardware.
|
||||
// The only difference for TCP/IP modules is to change 'USB' to 'TCP';
|
||||
// err = cswitch.discoverAndConnect(USB, 0x40F5849A); // for a known serial number
|
||||
err = cswitch.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered connecting to BrainStem module" << std::endl;
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
std::cout << "Connected to BrainStem module." << std::endl;
|
||||
}
|
||||
|
||||
// Initial port setup.
|
||||
// Mux select channel 0, USB common side enabled, Mux side enabled.
|
||||
cswitch.mux.setChannel(0);
|
||||
cswitch.usb.setPortEnable(USBC_COMMON);
|
||||
cswitch.mux.setEnable(ENABLE);
|
||||
|
||||
// Using the USB channel disable the connection on the common side.
|
||||
err = cswitch.usb.setPortDisable(USBC_COMMON);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered disabling connection." << std::endl;
|
||||
return 1;
|
||||
} else { std::cout << "Disabled connection on the common (USB) side." << std::endl; }
|
||||
|
||||
// Change the mux channel to channel 1.
|
||||
err = cswitch.mux.setChannel(1);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered changing the channel." << std::endl;
|
||||
return 1;
|
||||
} else { std::cout << "Switched to mux channel 1." << std::endl; }
|
||||
|
||||
|
||||
// Using the usb entity enable the connection.
|
||||
err = cswitch.usb.setPortEnable(USBC_COMMON);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered enabling the connection." << std::endl;
|
||||
return 1;
|
||||
} else { std::cout << "Enabled the connection on the common (USB) side." << std::endl; }
|
||||
|
||||
// Loop for LOOP_MAX seconds printing current and voltage.
|
||||
for (count = 0; count < LOOP_MAX; count++) {
|
||||
int32_t microVolts = 0;
|
||||
int32_t microAmps = 0;
|
||||
err = cswitch.usb.getPortVoltage(USBC_COMMON, µVolts);
|
||||
if (err == aErrNone) { err = cswitch.usb.getPortCurrent(USBC_COMMON, µAmps); }
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered getting port voltage and current." << std::endl;
|
||||
return 1;
|
||||
} else {
|
||||
std::cout << "Port Voltage: " << microVolts << " uV, " << "Port Current: " << microAmps << " uA " << std::endl;
|
||||
}
|
||||
aTime_MSSleep(1000);
|
||||
}
|
||||
|
||||
// Using the mux, disable the connection.
|
||||
// Note : This has essentially the same effect as disabling the connection
|
||||
// at the common side, except that it will not affect any of the USB
|
||||
// port settings where the USB call directely affects these settings.
|
||||
err = cswitch.mux.setEnable(DISABLE);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered disabling the connection on the mux side." << std::endl;
|
||||
return 1;
|
||||
} else { std::cout << "Disabled the connection on the mux side." << std::endl; }
|
||||
|
||||
// Change the mux channel to channel 0.
|
||||
err = cswitch.mux.setChannel(0);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered changing the channel." << std::endl;
|
||||
return 1;
|
||||
} else { std::cout << "Switched to mux channel 0." << std::endl; }
|
||||
|
||||
// Using the mux, Enable the connection.
|
||||
err = cswitch.mux.setEnable(ENABLE);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered enabling the connection." << std::endl;
|
||||
return 1;
|
||||
} else { std::cout << "Enabled port via mux." << std::endl; }
|
||||
|
||||
err = cswitch.disconnect();
|
||||
if (err == aErrNone) {
|
||||
std::cout << "Disconnected from BrainStem module." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
USBC-Switch C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the USBC-Switch. It demonstrates enabling and
|
||||
disabling the common port and the selection of mux channels. It also measures
|
||||
voltage and current.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
2383
api/examples/c_cpp/BrainStem2-USBHub-CMD-Line-Example/AcronameHubCLI/cxxopts.hpp
Executable file
2383
api/examples/c_cpp/BrainStem2-USBHub-CMD-Line-Example/AcronameHubCLI/cxxopts.hpp
Executable file
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,968 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* */
|
||||
/* file: main.c */
|
||||
/* */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* */
|
||||
/* description: Example CLI application for basic hub functionality. */
|
||||
/* */
|
||||
/* */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* */
|
||||
/* Copyright (c) 2023 Acroname Inc. - All Rights Reserved */
|
||||
/* */
|
||||
/* This file is part of the BrainStem release. See the license.txt */
|
||||
/* file included with this package or go to */
|
||||
/* https://acroname.com/software/brainstem-development-kit */
|
||||
/* for full license details. */
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Includes
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
//The command line arguments are parsed using the open source cxxopts.hpp header
|
||||
//implementation. The original source of this file can be found at:
|
||||
//https://github.com/jarro2783/cxxopts
|
||||
//FYI: Windows Users std::min() and std::max() are used by cxxopts.hpp. This
|
||||
// can cause an issues when including windows.h which defines these as macros.
|
||||
// To combat this I added NOMINMAX to the preprocessor defines for this project.
|
||||
// Debug -> BrainStem2Example Properties -> Configuration Properties -> C/C++ -> preprocessor
|
||||
#include "cxxopts.hpp"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Macros
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Platform specific line feed.
|
||||
#if defined(_MSC_VER)
|
||||
#define _LF "\r\n"
|
||||
#define LF_LEN 2
|
||||
#else
|
||||
#define _LF "\n"
|
||||
#define LF_LEN 1
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Constants
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static const uint8_t MIN_MAJOR = 2;
|
||||
static const uint8_t MIN_MINOR = 10;
|
||||
static const uint8_t MIN_PATCH = 0;
|
||||
|
||||
|
||||
static const char* EXAMPLES_COMMANDS = _LF
|
||||
"Examples:" _LF
|
||||
"Note: When --serial is NOT used, the application will default to the first Acroname Hub found" _LF
|
||||
"\"AcronameHubCLI --ports 0 --enable 0\" - Disables Port 0" _LF
|
||||
"\"AcronameHubCLI --ports 0 --enable 1\" - Enables Port 0" _LF
|
||||
"\"AcronameHubCLI --ports=0,1,2 --enable 0\" - Disables Ports 0, 1 and 2" _LF
|
||||
"\"AcronameHubCLI --ports 1 --enable 1 --serial FEEDBEEF\" - Enables port 1 for device 0xFEEDBEEF" _LF
|
||||
"\"AcronameHubCLI --ports 1 --enable 1 --data\" - Enables port 1 data lines only" _LF
|
||||
"\"AcronameHubCLI --ports 1 --enable 0 --data\" - Disables port 1 data lines only" _LF
|
||||
"\"AcronameHubCLI --ports 2 --enable 1 --power\" - Enables port 2 power lines only" _LF
|
||||
"\"AcronameHubCLI --ports 2 --enable 0 --power\" - Disables port 2 power lines only" _LF
|
||||
"\"AcronameHubCLI --ports 3 --voltage --current\" - Gets the voltage and current of port 3" _LF
|
||||
;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Types
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum PORT_ACTIONS : uint8_t {
|
||||
kPORT_ACTIONS_ENABLE = 0,
|
||||
kPORT_ACTIONS_TOGGLE,
|
||||
kPORT_ACTIONS_DATA,
|
||||
kPORT_ACTIONS_UNKNOWN,
|
||||
kPORT_ACTIONS_LAST
|
||||
} PORT_ACTIONS_t;
|
||||
|
||||
|
||||
typedef struct CLIObject {
|
||||
std::shared_ptr<Acroname::BrainStem::Module> stem = nullptr;
|
||||
std::shared_ptr<cxxopts::Options> options = nullptr;
|
||||
std::shared_ptr<linkSpec> spec = nullptr;
|
||||
|
||||
unsigned long serialNumber = 0;
|
||||
std::vector<int> ports;
|
||||
int enable = 0;
|
||||
int upstream = 0;
|
||||
bool power = true;
|
||||
bool data = true;
|
||||
PORT_ACTIONS_t portsAction = kPORT_ACTIONS_UNKNOWN;
|
||||
cxxopts::ParseResult result;
|
||||
} CLIObject_t;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Function Prototypes
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static void _config_cxxopts(CLIObject_t& cliObj);
|
||||
|
||||
static bool _parse(CLIObject_t& cliObj, int argc, char* argv[]);
|
||||
static bool _parse_serial(CLIObject_t& cliObj);
|
||||
static bool _parse_port(CLIObject_t& cliObj);
|
||||
static bool _parse_upstream(CLIObject_t& cliObj);
|
||||
|
||||
//If (int < 0) A program error has occurred.
|
||||
//If (int > 0) A BrainStem error has occurred.
|
||||
//If (int == 0) Success.
|
||||
static int _process(CLIObject_t& cliObj);
|
||||
static int _process_createStem(CLIObject_t& cliObj);
|
||||
static aErr _process_reset(CLIObject_t& cliObj);
|
||||
static aErr _process_ports(CLIObject_t& cliObj);
|
||||
static aErr _process_upstream(CLIObject_t& cliObj);
|
||||
static aErr _process_verbose(CLIObject_t& cliObj);
|
||||
|
||||
static aErr _portAction_toggle(CLIObject_t& cliObj, const int& port);
|
||||
static aErr _portAction_enable(CLIObject_t& cliObj, const int& port);
|
||||
static aErr _portAction_voltage(CLIObject_t& cliObj, const int& port);
|
||||
static aErr _portAction_current(CLIObject_t& cliObj, const int& port);
|
||||
|
||||
static int _translate_UpstreamPort(uint8_t model, int providedPort);
|
||||
|
||||
static aErr _kickConnection(CLIObject_t& cliObj);
|
||||
|
||||
static void _verbose_printMode_USBHub3c(const uint32_t& mode, const int& port, const bool& showHeader = false);
|
||||
static void _verbose_printMode_USBHub3p(const uint32_t& mode, const int& port, const bool& showHeader = false);
|
||||
static void _verbose_printMode_USBHub2x4(const uint32_t& mode, const int& port, const bool& showHeader = false);
|
||||
static std::string _verbose_printMode_decodeModeString(const uint32_t& mode);
|
||||
static std::string _verbose_upstreamPortNumber(const uint32_t& model, const uint8_t& upstreamPort);
|
||||
|
||||
static bool _checkVersion(std::shared_ptr<Acroname::BrainStem::Module> stem);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Public Function Implementations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
CLIObject_t cliObj;
|
||||
aErr err = aErrNone;
|
||||
|
||||
try
|
||||
{
|
||||
_config_cxxopts(cliObj);
|
||||
|
||||
//Parse options/arguments.
|
||||
if(! _parse(cliObj, argc, argv)) { return -1; }
|
||||
|
||||
//Process options/arguments.
|
||||
int success = _process(cliObj);
|
||||
if((success >= 0) &&
|
||||
(success <= aErrUnknown))
|
||||
{
|
||||
err = (aErr)success;
|
||||
}
|
||||
else { return success; }
|
||||
|
||||
}
|
||||
catch (const cxxopts::OptionException& e) {
|
||||
std::cerr << "Error parsing options: " << e.what() << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return -2;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Unknown Exception Caught: " << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return -3;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_config_cxxopts(CLIObject_t& cliObj) {
|
||||
//Create cxxopts options object
|
||||
cliObj.options.reset(new cxxopts::Options("AcronameHubCLI.exe", "Acroname Programmable Hub Command Line Interface"));
|
||||
|
||||
cliObj.options->add_options()
|
||||
("h, help", "Prints this help message")
|
||||
("p, ports", "Port(s) in which a \"Port Action\" will be executed on. The default action is enable. This can be a comma-separated list.", cxxopts::value<std::vector<int>>())
|
||||
("e, enable", "0 = Disable; 1 = Enable (Port Action) ", cxxopts::value<int>()->default_value("1"))
|
||||
("t, toggle", "Toggle port(s) between enabled and disabled. (Port Action) ")
|
||||
("b, voltage", "Reports the voltage of a given port(s) (Port Action)")
|
||||
("c, current", "Reports the current of a given port(s) (Port Action)")
|
||||
("w, power", "Only apply enable or toggle actions to port power lines")
|
||||
("d, data", "Only apply enable or toggle actions to port data lines")
|
||||
("u, upstream", "Manually select an upstream port", cxxopts::value<int>())
|
||||
("a, auto", "Enable automatic upstream port selection. If this option is present, the -u/--upstream option is ignored.")
|
||||
("s, serial", "Hub serial number in hexadecimal representation. Use 0 for automatic discovery.", cxxopts::value<std::string>()->default_value("0"))
|
||||
("v, verbose", "Report port states after processing other options")
|
||||
("r, reset", "Reset the hub. All port options are ignored.")
|
||||
("x, examples", "Displays a list of common examples");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Function Implementations
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool
|
||||
_parse(CLIObject_t& cliObj, int argc, char* argv[]) {
|
||||
cliObj.result = cliObj.options->parse(argc, argv);
|
||||
|
||||
//Print arguments, if non were provided print the usage.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
std::cout << "Arguments: ";
|
||||
for (int x = 0; x < argc; x++) { std::cout << argv[x] << " "; }
|
||||
std::cout << std::endl;
|
||||
|
||||
if(argc == 1) { //First argument is always the app path.
|
||||
std::cout << "No arguments were provided. Printing usage" << std::endl;
|
||||
std::cout << cliObj.options->help() << std::endl;
|
||||
std::cout << EXAMPLES_COMMANDS << std::endl;
|
||||
return false;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Help
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if (cliObj.result.count("help")) {
|
||||
std::cout << cliObj.options->help() << std::endl;
|
||||
std::cout << EXAMPLES_COMMANDS << std::endl;
|
||||
return false;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Help
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if (cliObj.result.count("examples")) {
|
||||
std::cout << EXAMPLES_COMMANDS << std::endl;
|
||||
return false;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Serial
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(! _parse_serial(cliObj)) {
|
||||
return false;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Port
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(! _parse_port(cliObj)) {
|
||||
return false;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Enable - We need to check the value is within range.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
cliObj.enable = cliObj.result["enable"].as<int>();
|
||||
if ((1 != cliObj.enable) &&
|
||||
(0 != cliObj.enable))
|
||||
{
|
||||
std::cerr << "Incorrect value for enable" << std::endl;
|
||||
std::cerr << "Acceptable values are 0 for false and 1 for true" << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return false;
|
||||
}
|
||||
/// End Parse Enable/////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Toggle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Nothing specific needs to be handled or tested. Option will be checked in "work".
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Upstream - We need to check the value is within range.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(! _parse_upstream(cliObj)) {
|
||||
return false;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Power and Data
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// act on both power and data by default (both flags present or both flags absent)
|
||||
cliObj.power = true;
|
||||
cliObj.data = true;
|
||||
if (cliObj.result.count("power") && !cliObj.result.count("data")) {
|
||||
// only power flag present: only act on power lines
|
||||
cliObj.power = true;
|
||||
cliObj.data = false;
|
||||
}
|
||||
if (cliObj.result.count("data") && !cliObj.result.count("power")) {
|
||||
// only data flag present: only act on power lines
|
||||
cliObj.power = false;
|
||||
cliObj.data = true;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parser - Auto
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Nothing specific needs to be handled or tested. Option will be checked in "work".
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
_parse_serial(CLIObject_t& cliObj) {
|
||||
if (cliObj.result.count("serial")) {
|
||||
cliObj.serialNumber = std::stoul(cliObj.result["serial"].as<std::string>(), nullptr, 16);
|
||||
if (cliObj.serialNumber == 0) {
|
||||
cliObj.spec.reset(aDiscovery_FindFirstModule(USB, LOCALHOST_IP_ADDRESS));
|
||||
}
|
||||
else {
|
||||
cliObj.spec.reset(aDiscovery_FindModule(USB,
|
||||
(uint32_t)cliObj.serialNumber,
|
||||
LOCALHOST_IP_ADDRESS));
|
||||
}
|
||||
|
||||
//Ensure that we found something.
|
||||
if (cliObj.spec == NULL) {
|
||||
std::cerr << "Could not find any BrainStem Devices" << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//No serial number was provided. Use the first thing we find.
|
||||
cliObj.spec.reset(aDiscovery_FindFirstModule(USB, LOCALHOST_IP_ADDRESS));
|
||||
if (cliObj.spec == NULL) {
|
||||
std::cerr << "Could not find any BrainStem Devices" << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cliObj.spec->model != aMODULE_TYPE_USBHub3p) &&
|
||||
(cliObj.spec->model != aMODULE_TYPE_USBHub2x4) &&
|
||||
(cliObj.spec->model != aMODULE_TYPE_USBHub3c))
|
||||
{
|
||||
std::cerr << "The device that was found is not a hub. Model: " << aDefs_GetModelName(cliObj.spec->model) << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
_parse_port(CLIObject_t& cliObj) {
|
||||
if (cliObj.result.count("ports")) {
|
||||
|
||||
if (cliObj.result.count("enable")) {
|
||||
cliObj.portsAction = kPORT_ACTIONS_ENABLE;
|
||||
}
|
||||
else if(cliObj.result.count("toggle")) {
|
||||
cliObj.portsAction = kPORT_ACTIONS_TOGGLE;
|
||||
}
|
||||
else if((cliObj.result.count("voltage")) ||
|
||||
(cliObj.result.count("current")))
|
||||
{
|
||||
cliObj.portsAction = kPORT_ACTIONS_DATA;
|
||||
}
|
||||
else {
|
||||
//This should preserve backwards compatibility.
|
||||
//Specifically AcronameHubCLIE.exe --ports 1 -> This enables the port.
|
||||
//ie. (--enable not required).
|
||||
cliObj.portsAction = kPORT_ACTIONS_ENABLE;
|
||||
}
|
||||
|
||||
//We need to check the range based on the device type
|
||||
cliObj.ports = cliObj.result["ports"].as<std::vector<int>>();
|
||||
for (const auto& port : cliObj.ports) {
|
||||
if ((cliObj.spec->model == aMODULE_TYPE_USBHub3p) ||
|
||||
(cliObj.spec->model == aMODULE_TYPE_USBHub3c))
|
||||
{
|
||||
if ((port > 7) ||
|
||||
(port < 0))
|
||||
{
|
||||
std::cerr << "Incorrect port value: " << int(port) << std::endl;
|
||||
std::cerr << "The " << aDefs_GetModelName(cliObj.spec->model) << " ports range from 0-7" << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (cliObj.spec->model == aMODULE_TYPE_USBHub2x4) {
|
||||
if ((port > 3) ||
|
||||
(port < 0))
|
||||
{
|
||||
std::cerr << "Incorrect port value: " << int(port) << std::endl;
|
||||
std::cerr << "The " << aDefs_GetModelName(cliObj.spec->model) << " ports range from 0-3" << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}//end model check.
|
||||
}//end ports for loop
|
||||
}// end "ports" argument
|
||||
else {
|
||||
//These parameters require --ports.
|
||||
//Notify the user and exit.
|
||||
std::string s = "";
|
||||
if (cliObj.result.count("enable")) { s = "enable"; }
|
||||
else if(cliObj.result.count("toggle")) { s = "toggle"; }
|
||||
else if(cliObj.result.count("voltage")) { s = "voltage"; }
|
||||
else if(cliObj.result.count("current")) { s = "current"; }
|
||||
|
||||
if(s.size()) {
|
||||
std::cout << "Parameter: \"" << s << "\" must accompany the \"ports\" parameter" << std::endl;
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
_parse_upstream(CLIObject_t& cliObj) {
|
||||
if (cliObj.result.count("upstream")) {
|
||||
bool handleError = false;
|
||||
|
||||
cliObj.upstream = cliObj.result["upstream"].as<int>();
|
||||
if (cliObj.spec->model == aMODULE_TYPE_USBHub3c) {
|
||||
if(cliObj.upstream >= 6) {
|
||||
handleError = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((cliObj.upstream != 1) &&
|
||||
(cliObj.upstream != 0))
|
||||
{
|
||||
handleError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(handleError) {
|
||||
std::cerr << "Incorrect value for upstream" << std::endl;
|
||||
if (cliObj.spec->model == aMODULE_TYPE_USBHub3c) {
|
||||
std::cerr << "Acceptable values 0-5" << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Acceptable values are 0 for UP0 and 1 for UP1" << std::endl;
|
||||
}
|
||||
std::cerr << cliObj.options->help() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_process(CLIObject_t& cliObj) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
int success = _process_createStem(cliObj);
|
||||
if(0 != success) { return success; }
|
||||
|
||||
err = cliObj.stem->connectFromSpec(*cliObj.spec);
|
||||
if (aErrNone != err) {
|
||||
std::cerr << "Error connecting to the device. Error: " << err << std::endl;
|
||||
return err;
|
||||
}
|
||||
else {
|
||||
std::cout << "Sucessfully connected to " << aDefs_GetModelName(cliObj.spec->model);
|
||||
auto prevState = std::cout.flags();
|
||||
std::cout << " SN: 0x" << std::setfill('0') << std::setw(8) << std::hex << std::uppercase << cliObj.spec->serial_num << std::endl;
|
||||
std::cout.flags(prevState);
|
||||
}
|
||||
|
||||
if (cliObj.result.count("reset")) {
|
||||
return _process_reset(cliObj);
|
||||
}
|
||||
|
||||
if (aErrNone == err) { err = _process_ports(cliObj); }
|
||||
if (aErrNone == err) { err = _process_upstream(cliObj); }
|
||||
if (aErrNone == err) { err = _process_verbose(cliObj); }
|
||||
|
||||
if(cliObj.stem->isConnected()) { cliObj.stem->disconnect(); }
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
return (int)err;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_process_createStem(CLIObject_t& cliObj) {
|
||||
if (cliObj.spec->model == aMODULE_TYPE_USBHub3p) {
|
||||
cliObj.stem.reset(new Acroname::BrainStem::Module(aUSBHUB3P_MODULE, true, aMODULE_TYPE_USBHub3p));
|
||||
}
|
||||
else if (cliObj.spec->model == aMODULE_TYPE_USBHub2x4) {
|
||||
cliObj.stem.reset(new Acroname::BrainStem::Module(aUSBHUB2X4_MODULE, true, aMODULE_TYPE_USBHub2x4));
|
||||
}
|
||||
else if (cliObj.spec->model == aMODULE_TYPE_USBHub3c) {
|
||||
cliObj.stem.reset(new Acroname::BrainStem::Module(aUSBHUB3C_MODULE, true, aMODULE_TYPE_USBHub3c));
|
||||
}
|
||||
else {
|
||||
std::cerr << "Error: device object not created" << std::endl;
|
||||
return -5;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static aErr
|
||||
_process_reset(CLIObject_t& cliObj) {
|
||||
std::cout << "Resetting device" << std::endl;
|
||||
if(cliObj.stem->isConnected()) {
|
||||
Acroname::BrainStem::SystemClass system;
|
||||
system.init(cliObj.stem.get(), 0);
|
||||
system.reset();
|
||||
return aErrNone;
|
||||
}
|
||||
else { return aErrConnection; }
|
||||
}
|
||||
|
||||
|
||||
static aErr
|
||||
_process_ports(CLIObject_t& cliObj) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
//Loop through provided ports.
|
||||
for (const auto& port : cliObj.ports) {
|
||||
switch(cliObj.portsAction) {
|
||||
case kPORT_ACTIONS_ENABLE:
|
||||
err = _portAction_enable(cliObj, port);
|
||||
break;
|
||||
|
||||
case kPORT_ACTIONS_TOGGLE:
|
||||
err = _portAction_toggle(cliObj, port);
|
||||
break;
|
||||
|
||||
case kPORT_ACTIONS_DATA:
|
||||
if(aErrNone != err) { break; }
|
||||
if(cliObj.result.count("voltage")) {
|
||||
err = _portAction_voltage(cliObj, port);
|
||||
}
|
||||
|
||||
if(aErrNone != err) { break; }
|
||||
if(cliObj.result.count("current")) {
|
||||
err = _portAction_current(cliObj, port);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
//Given the current logic we shouldn't get here.
|
||||
cliObj.portsAction = kPORT_ACTIONS_UNKNOWN;
|
||||
std::cout << "Unknown Action" << std::endl;
|
||||
return aErrUnknown;
|
||||
}
|
||||
|
||||
if(aErrNone != err) { break; }
|
||||
} // for (const auto& port : ports)
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _translate_UpstreamPort(uint8_t model, int providedPort) {
|
||||
|
||||
switch(model) {
|
||||
case aMODULE_TYPE_USBHub3p:
|
||||
if(providedPort == 0) {
|
||||
return aUSBHub3p::PORT_ID_t::kPORT_ID_UP0;
|
||||
}
|
||||
else if(providedPort == 1) {
|
||||
return aUSBHub3p::PORT_ID_t::kPORT_ID_UP1;
|
||||
}
|
||||
case aMODULE_TYPE_USBHub2x4:
|
||||
if(providedPort == 0) {
|
||||
return aUSBHub2x4::PORT_ID_t::kPORT_ID_UP0;
|
||||
}
|
||||
else if(providedPort == 1) {
|
||||
return aUSBHub2x4::PORT_ID_t::kPORT_ID_UP1;
|
||||
}
|
||||
// case aMODULE_TYPE_USBHub3c: //Nothing to translate
|
||||
}
|
||||
|
||||
return providedPort;
|
||||
}
|
||||
|
||||
static aErr
|
||||
_process_upstream(CLIObject_t& cliObj) {
|
||||
if(! _checkVersion(cliObj.stem)) { return aErrVersion; }
|
||||
|
||||
Acroname::BrainStem::USBSystemClass usbSystem;
|
||||
usbSystem.init(cliObj.stem.get(), 0);
|
||||
|
||||
aErr err = aErrNone;
|
||||
if (cliObj.result.count("auto")) {
|
||||
err = usbSystem.setDataRoleBehavior(usbsystemDataBehavior_PortPriority);
|
||||
if (aErrTimeout == err) { err = _kickConnection(cliObj); }
|
||||
|
||||
if(aErrNone != err) {
|
||||
std::cerr << "Error (" << err << ") " << "changing the data role to auto (Port Priority)." << std::endl;
|
||||
return err;
|
||||
}
|
||||
|
||||
std::cout << "Automatic upstream selection configured successfully." << std::endl;
|
||||
}
|
||||
else if (cliObj.result.count("upstream")) {
|
||||
err = usbSystem.setDataRoleBehavior(usbsystemDataBehavior_HardCoded);
|
||||
if (aErrTimeout == err) { err = _kickConnection(cliObj); }
|
||||
|
||||
if(aErrNone != err) {
|
||||
std::cerr << "Error (" << err << ") " << "changing the data role to fixed (Hard Coded)." << std::endl;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = usbSystem.setUpstream(_translate_UpstreamPort(cliObj.spec->model, cliObj.upstream));
|
||||
if (aErrTimeout == err) { err = _kickConnection(cliObj); }
|
||||
|
||||
if(aErrNone != err) {
|
||||
std::cerr << "There was an error (" << err << ") " << "changing the upstream port." << std::endl;
|
||||
std::cerr << "If you changed the upstream connection away from this machine and you have no control port connection then this is expected." << std::endl;
|
||||
return err;
|
||||
}
|
||||
|
||||
std::cout << "Upstream successfully set to port: " << cliObj.upstream << std::endl;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static aErr
|
||||
_process_verbose(CLIObject_t& cliObj) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
if(cliObj.result.count("verbose")) {
|
||||
if(! _checkVersion(cliObj.stem)) { return aErrVersion; }
|
||||
|
||||
Acroname::BrainStem::USBSystemClass usbSystem;
|
||||
usbSystem.init(cliObj.stem.get(), 0);
|
||||
|
||||
uint8_t upstreamPort = 0;
|
||||
err = usbSystem.getUpstream(&upstreamPort);
|
||||
if(aErrNone != err) {
|
||||
std::cerr << "Error (" << err << ") " << "getting the upstream port." << std::endl;
|
||||
return err;
|
||||
}
|
||||
|
||||
std::cout << "Active Upstream: " << _verbose_upstreamPortNumber(cliObj.spec->model, upstreamPort) << std::endl;
|
||||
|
||||
|
||||
//Iterate up to a large value of ports to support all products.
|
||||
//We will break out when we get aErrIndexRange as an error code
|
||||
for(int port = 0; port < 20; port++) {
|
||||
Acroname::BrainStem::PortClass portClass;
|
||||
portClass.init(cliObj.stem.get(), port);
|
||||
|
||||
uint32_t mode = 0;
|
||||
err = portClass.getMode(&mode);
|
||||
|
||||
//Once we hit an invalid index bail.
|
||||
if(aErrIndexRange == err) {
|
||||
return aErrNone; //Overwrite the error since we expect this case.
|
||||
}
|
||||
else if(aErrUnimplemented == err) {
|
||||
//Some ports do not support this API.
|
||||
//For instance: Ports: Up0, Up1, DownA and Control on the USBHub3p.
|
||||
continue;
|
||||
}
|
||||
else if(aErrNone != err) {
|
||||
std::cerr << "Error (" << err << ") " << "getting the mode." << std::endl;
|
||||
return err;
|
||||
}
|
||||
|
||||
bool printHeader = (0 == port);
|
||||
|
||||
switch (cliObj.spec->model) {
|
||||
case aMODULE_TYPE_USBHub3c:
|
||||
_verbose_printMode_USBHub3c(mode, port, printHeader);
|
||||
break;
|
||||
|
||||
case aMODULE_TYPE_USBHub3p:
|
||||
_verbose_printMode_USBHub3p(mode, port, printHeader);
|
||||
break;
|
||||
|
||||
case aMODULE_TYPE_USBHub2x4:
|
||||
_verbose_printMode_USBHub2x4(mode, port, printHeader);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}//end switch
|
||||
}//end for loop (ports)
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static aErr
|
||||
_portAction_toggle(CLIObject_t& cliObj, const int& port) {
|
||||
|
||||
if(! _checkVersion(cliObj.stem)) { return aErrVersion; }
|
||||
|
||||
Acroname::BrainStem::PortClass portClass;
|
||||
portClass.init(cliObj.stem.get(), port);
|
||||
|
||||
aErr err = aErrNone;
|
||||
uint8_t vbusState = 0;
|
||||
uint8_t dataState = 0;
|
||||
|
||||
err = portClass.getDataEnabled(&dataState);
|
||||
if(aErrNone != err) {
|
||||
std::cerr << "Error (" << err << ") getting port: " << int(port) << " data state" << std::endl;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = portClass.getPowerEnabled(&vbusState);
|
||||
if(aErrNone != err) {
|
||||
std::cerr << "Error (" << err << ") getting port: " << int(port) << " power state" << std::endl;
|
||||
return err;
|
||||
}
|
||||
|
||||
//Apply Data Settings
|
||||
if (cliObj.data) {
|
||||
err = portClass.setDataEnabled(! dataState);
|
||||
if (aErrNone != err) {
|
||||
std::cerr << "Error (" << err << ") toggling port: " << int(port) << " data" << std::endl;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
//Apply Power Settings
|
||||
if (cliObj.power) {
|
||||
err = portClass.setPowerEnabled(! vbusState);
|
||||
if (aErrNone != err) {
|
||||
std::cerr << "Error (" << err << ") toggling port: " << int(port) << " power" << std::endl;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Port: " << int(port) << " was sucessfully toggled" << std::endl;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static aErr
|
||||
_portAction_enable(CLIObject_t& cliObj, const int& port)
|
||||
{
|
||||
if(! _checkVersion(cliObj.stem)) { return aErrVersion; }
|
||||
|
||||
Acroname::BrainStem::PortClass portClass;
|
||||
portClass.init(cliObj.stem.get(), port);
|
||||
|
||||
aErr err = aErrNone;
|
||||
|
||||
if ((cliObj.power) &&
|
||||
(cliObj.data))
|
||||
{
|
||||
err = portClass.setEnabled(cliObj.enable);
|
||||
}
|
||||
else {
|
||||
if (cliObj.power) { err = portClass.setPowerEnabled(cliObj.enable); }
|
||||
if (cliObj.data) { err = portClass.setDataEnabled(cliObj.enable); }
|
||||
}
|
||||
|
||||
if (err != aErrNone) {
|
||||
std::cerr << "There was an error (" << err << ") " << (cliObj.enable ? "enabling" : "disabling") << " port " << int(port) << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "Port: " << int(port) << " was sucessfully " << (cliObj.enable ? "enabled" : "disabled") << std::endl;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static aErr
|
||||
_portAction_voltage(CLIObject_t& cliObj, const int& port) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
if(! _checkVersion(cliObj.stem)) { return aErrVersion; }
|
||||
|
||||
Acroname::BrainStem::PortClass p;
|
||||
p.init(cliObj.stem.get(), port);
|
||||
|
||||
int32_t voltage = 0;
|
||||
err = p.getVbusVoltage(&voltage);
|
||||
|
||||
std::cout << "Port: " << int(port) << " Voltage: " << double(voltage)/1000000.0 << " VDC" << std::endl;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static aErr
|
||||
_portAction_current(CLIObject_t& cliObj, const int& port) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
if(! _checkVersion(cliObj.stem)) { return aErrVersion; }
|
||||
|
||||
Acroname::BrainStem::PortClass p;
|
||||
p.init(cliObj.stem.get(), port);
|
||||
|
||||
int32_t current = 0;
|
||||
err = p.getVbusCurrent(¤t);
|
||||
|
||||
std::cout << "Port: " << int(port) << " Current: " << double(current)/1000000.0 << " A" << std::endl;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
_checkVersion(std::shared_ptr<Acroname::BrainStem::Module> stem) {
|
||||
|
||||
//Cached variables in order to reduce calls to getVersion
|
||||
static std::weak_ptr<Acroname::BrainStem::Module> _stem;
|
||||
static uint8_t major = 0;
|
||||
static uint8_t minor = 0;
|
||||
static uint8_t patch = 0;
|
||||
|
||||
auto s = _stem.lock();
|
||||
if((nullptr == s) ||
|
||||
(s.get() != stem.get()))
|
||||
{
|
||||
Acroname::BrainStem::SystemClass sys;
|
||||
sys.init(stem.get(), 0);
|
||||
uint32_t build = 0;
|
||||
aErr err = sys.getVersion(&build);
|
||||
if(aErrNone == err) {
|
||||
major = aVersion_ParseMajor(build);
|
||||
minor = aVersion_ParseMinor(build);
|
||||
patch = aVersion_ParsePatch(build);
|
||||
_stem = stem;
|
||||
}
|
||||
}
|
||||
|
||||
if(aVersion_IsAtLeastCompare(major, minor, patch, 2, 10, 0)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
std::cout << "Current firmware version: "
|
||||
<< int(major) << "." << int(minor) << "." << int(patch) << std::endl;
|
||||
std::cout << "Minimum firmware version required: "
|
||||
<< int(MIN_MAJOR) << "." << int(MIN_MINOR) << "." << int(MIN_PATCH) << std::endl;
|
||||
std::cout << "Please upgrade you firmware via HubTool or Updater" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static aErr
|
||||
_kickConnection(CLIObject_t& cliObj) {
|
||||
cliObj.stem->disconnect();
|
||||
cliObj.stem->reconnect();
|
||||
return (cliObj.stem->isConnected()) ? (aErrNone) : (aErrConnection);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_verbose_printMode_USBHub3c(const uint32_t& mode, const int& port, const bool& showHeader) {
|
||||
int power = (mode & (1 << portPortMode_powerEnabled_Bit)) >> portPortMode_powerEnabled_Bit;
|
||||
int hs1 = (mode & (1 << portPortMode_HS1Enabled_Bit)) >> portPortMode_HS1Enabled_Bit;
|
||||
int hs2 = (mode & (1 << portPortMode_HS2Enabled_Bit)) >> portPortMode_HS2Enabled_Bit;
|
||||
int ss1 = (mode & (1 << portPortMode_SS1Enabled_Bit)) >> portPortMode_SS1Enabled_Bit;
|
||||
int ss2 = (mode & (1 << portPortMode_SS2Enabled_Bit)) >> portPortMode_SS2Enabled_Bit;
|
||||
int cc1 = (mode & (1 << portPortMode_CC1Enabled_Bit)) >> portPortMode_CC1Enabled_Bit;
|
||||
int cc2 = (mode & (1 << portPortMode_CC2Enabled_Bit)) >> portPortMode_CC2Enabled_Bit;
|
||||
int vconn1 = (mode & (1 << portPortMode_Vconn1Enabled_Bit)) >> portPortMode_Vconn1Enabled_Bit;
|
||||
int vconn2 = (mode & (1 << portPortMode_Vconn2Enabled_Bit)) >> portPortMode_Vconn2Enabled_Bit;
|
||||
int pwrMode = (mode & (portPortMode_portPowerMode_Mask << portPortMode_portPowerMode_Offset)) >> portPortMode_portPowerMode_Offset;
|
||||
|
||||
if(showHeader) {
|
||||
std::cout << "Port Power HS1 HS2 SS1 SS2 CC1 CC2 VConn1 VConn2 Power-Mode" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::setfill(' ') << std::setw(4) << port;
|
||||
std::cout << std::setfill(' ') << std::setw(6) << power;
|
||||
std::cout << std::setfill(' ') << std::setw(4) << hs1;
|
||||
std::cout << std::setfill(' ') << std::setw(4) << hs2;
|
||||
std::cout << std::setfill(' ') << std::setw(4) << ss1;
|
||||
std::cout << std::setfill(' ') << std::setw(4) << ss2;
|
||||
std::cout << std::setfill(' ') << std::setw(4) << cc1;
|
||||
std::cout << std::setfill(' ') << std::setw(4) << cc2;
|
||||
std::cout << std::setfill(' ') << std::setw(7) << vconn1;
|
||||
std::cout << std::setfill(' ') << std::setw(7) << vconn2;
|
||||
|
||||
std::cout << std::setfill(' ') << std::setw(11) << _verbose_printMode_decodeModeString(pwrMode);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_verbose_printMode_USBHub3p(const uint32_t& mode, const int& port, const bool& showHeader) {
|
||||
int power = (mode & (1 << portPortMode_powerEnabled_Bit)) >> portPortMode_powerEnabled_Bit;
|
||||
int hs = (mode & (1 << portPortMode_HS1Enabled_Bit)) >> portPortMode_HS1Enabled_Bit;
|
||||
int ss = (mode & (1 << portPortMode_SS1Enabled_Bit)) >> portPortMode_SS1Enabled_Bit;
|
||||
int pwrMode = (mode & (portPortMode_portPowerMode_Mask << portPortMode_portPowerMode_Offset)) >> portPortMode_portPowerMode_Offset;
|
||||
|
||||
if(showHeader) {
|
||||
std::cout << "Port Power HS SS Power-Mode" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::setfill(' ') << std::setw(4) << port;
|
||||
std::cout << std::setfill(' ') << std::setw(6) << power;
|
||||
std::cout << std::setfill(' ') << std::setw(3) << hs;
|
||||
std::cout << std::setfill(' ') << std::setw(3) << ss;
|
||||
|
||||
std::cout << std::setfill(' ') << std::setw(11) << _verbose_printMode_decodeModeString(pwrMode);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_verbose_printMode_USBHub2x4(const uint32_t& mode, const int& port, const bool& showHeader) {
|
||||
int power = (mode & (1 << portPortMode_powerEnabled_Bit)) >> portPortMode_powerEnabled_Bit;
|
||||
int hs = (mode & (1 << portPortMode_HS1Enabled_Bit)) >> portPortMode_HS1Enabled_Bit;
|
||||
int pwrMode = (mode & (portPortMode_portPowerMode_Mask << portPortMode_portPowerMode_Offset)) >> portPortMode_portPowerMode_Offset;
|
||||
|
||||
if(showHeader) {
|
||||
std::cout << "Port Power HS Power-Mode" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << std::setfill(' ') << std::setw(4) << port;
|
||||
std::cout << std::setfill(' ') << std::setw(6) << power;
|
||||
std::cout << std::setfill(' ') << std::setw(3) << hs;
|
||||
|
||||
std::cout << std::setfill(' ') << std::setw(11) << _verbose_printMode_decodeModeString(pwrMode);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
||||
static std::string
|
||||
_verbose_printMode_decodeModeString(const uint32_t& mode) {
|
||||
switch (mode) {
|
||||
case portPowerMode_none_Value: return "NONE";
|
||||
case portPowerMode_sdp_Value: return "SDP";
|
||||
case portPowerMode_cdp_dcp_Value: return "CDP/DCP";
|
||||
case portPowerMode_qc_Value: return "QC";
|
||||
case portPowerMode_pd_Value: return "PD";
|
||||
case portPowerMode_ps_Value: return "PS";
|
||||
case portPowerMode_usbc_Value: return "USBC";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static std::string
|
||||
_verbose_upstreamPortNumber(const uint32_t& model, const uint8_t& upstreamPort) {
|
||||
std::string s = "(Port: " + std::to_string(int(upstreamPort)) + ")";
|
||||
switch (model) {
|
||||
case aMODULE_TYPE_USBHub3c:
|
||||
return std::to_string(int(upstreamPort));
|
||||
|
||||
case aMODULE_TYPE_USBHub3p:
|
||||
if (9 == upstreamPort) { return "Up0 " + s; }
|
||||
else if(10 == upstreamPort) { return "Up1 " + s; }
|
||||
else { return "USBHub3p: Invalid upstream port number"; }
|
||||
|
||||
case aMODULE_TYPE_USBHub2x4:
|
||||
if (4 == upstreamPort) { return "0 " + s; }
|
||||
else if(5 == upstreamPort) { return "1 " + s; }
|
||||
else { return "USBHub2x4: Invalid upstream port number"; }
|
||||
|
||||
default:
|
||||
return "Unsupported model: " + std::to_string(int(model));
|
||||
}//end switch
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
===============================================================================
|
||||
USBHub CMD Line Example
|
||||
===============================================================================
|
||||
|
||||
This is a basic CMD line example that was designed for the USBHub2x4, USBHub3p
|
||||
and USBHub3c but could easily be adapted to our other products. It depends on
|
||||
an external header implementation "cxxopts.h". The source for this file can be
|
||||
found at: https://github.com/jarro2783/cxxopts.
|
||||
|
||||
Example execution:
|
||||
-h //Prints the help information.
|
||||
-p 0 -e 0 //Disables port 0
|
||||
-p 0 -e 1 //Enables port 0
|
||||
-p 0 -e 0 -b //Disables just the data lines of port 0
|
||||
-p 0 -e 0 -a //Disables just the power lines of port 0
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The makefile is setup with 3x different configurations.
|
||||
- Debug - Linked to the libBrainStem2.so
|
||||
* make debug
|
||||
- Release - Linked to the libBrainStem2.so
|
||||
* make release
|
||||
- Static - Linked to libBrainStem2.a for easy deployment.
|
||||
* make static
|
||||
|
||||
# For Debug and Release configurations the shared object is copied into the
|
||||
output folder. The shared object must be next to the executable or install
|
||||
into the local system.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
CPPFLAGS = -std=c++11
|
||||
ROOT = .
|
||||
TARGET = AcronameHubCLI
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
STC_DST := $(OUT)/Static
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2 -ludev
|
||||
STATICLIBS := lib/libBrainStem2.a -lpthread
|
||||
INCLUDES := -Ilib
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all :
|
||||
make app
|
||||
|
||||
app : debug release static
|
||||
|
||||
.PHONY : debug
|
||||
debug:
|
||||
mkdir -p $(DBG_DST)
|
||||
$(CPP) $(CPPFLAGS) $(CFLAGS) $(TARGET)/main.cpp $(LIBRARIES) -o $(DBG_DST)/$(TARGET)
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release:
|
||||
mkdir -p $(REL_DST)
|
||||
$(CPP) $(CPPFLAGS) $(CFLAGS) -DNDEBUG $(TARGET)/main.cpp $(LIBRARIES) -o $(REL_DST)/$(TARGET)
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : static
|
||||
static:
|
||||
mkdir -p $(STC_DST)
|
||||
$(CPP) $(CPPFLAGS) $(CFLAGS) -DNDEBUG $(TARGET)/main.cpp $(STATICLIBS) -ludev -o $(STC_DST)/$(TARGET)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
std::cout << "Creating a USBhub2x4 module" << std::endl;
|
||||
|
||||
// Create an instance of the USBHub2x4
|
||||
aUSBHub2x4 hub;
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Connect to the hardware.
|
||||
// The only difference for TCP/IP modules is to change 'USB' to 'TCP';
|
||||
// err = stem.discoverAndConnect(USB, 0x40F5849A); // for a known serial number
|
||||
err = hub.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered connecting to BrainStem module" << std::endl;
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
std::cout << "Connected to BrainStem module." << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::cout << "Disabling ports:" << std::endl;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// Disable all ports, then renable them.
|
||||
err = hub.usb.setPortDisable(i);
|
||||
std::cout << " port: " << i << " Error: " << err << std::endl;
|
||||
// We wait 400ms only to show the disable and renable process more clearly.
|
||||
// for the example.
|
||||
aTime_MSSleep(400);
|
||||
|
||||
}
|
||||
|
||||
std::cout << "Enabling ports:" << std::endl;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
// Disable all ports, then renable them.
|
||||
err = hub.usb.setPortEnable(i);
|
||||
std::cout << " port: " << i << " Error: " << err << std::endl;
|
||||
// We wait 400ms only to show the disable and renable process more clearly.
|
||||
// for the example.
|
||||
aTime_MSSleep(400);
|
||||
|
||||
}
|
||||
|
||||
// Disconnect
|
||||
err = hub.disconnect();
|
||||
if (err == aErrNone) {
|
||||
std::cout << "Disconnected from BrainStem module." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
USBHub2x4 C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the USBHub2x4. When executed, this example disables,
|
||||
and then re-enables each of the downstream device ports on the hub. Plug a device
|
||||
or two in to see the results.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2023 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
using namespace Acroname::BrainStem::Utilities;
|
||||
|
||||
//Constants
|
||||
static const int LOOPS = 25;
|
||||
static const int SLEEP_TIME_MS = 250;
|
||||
|
||||
//Function prototypes.
|
||||
static void printBS_PD_Packet(BS_PD_Packet_t& packet);
|
||||
static void processPacketsOneAtATime(std::shared_ptr<PDChannelLogger> logger);
|
||||
static void processMultiplePacketsAtATime(std::shared_ptr<PDChannelLogger> logger);
|
||||
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
// Create an instance of the USBHub3p
|
||||
aUSBHub3c chub;
|
||||
aErr err = aErrNone;
|
||||
|
||||
err = chub.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
printf("Failed to connect to device. Error: %d Exiting\n", err);
|
||||
return 1;
|
||||
}
|
||||
else { printf("Connected to BrainStem module.\n"); }
|
||||
|
||||
|
||||
std::vector<std::shared_ptr<PDChannelLogger>> loggers;
|
||||
|
||||
//Create a PDChannelLogger for each port and start them up.
|
||||
for (int port = 0; port <= aUSBHub3c::PORT_ID_t::kPORT_ID_POWER_C; port++) {
|
||||
std::shared_ptr<PDChannelLogger> logger = std::make_shared<PDChannelLogger>(&chub, port);
|
||||
err = logger->setEnabled(true); //Enable PD logging
|
||||
if (aErrPermission == err) {
|
||||
printf("This USBHub3c does not have the PD Logger Feature T99-PD-LOG\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
loggers.push_back(std::move(logger)); //The logger object is not copyable. You must move it.
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
//Single Packet Test:
|
||||
///////////////////////////////////////
|
||||
//Attempt to trigger PD communication on every port.
|
||||
//Note: No traffic will occur if the devices does not support PD.
|
||||
for (int port = 0; port <= aUSBHub3c::PORT_ID_t::kPORT_ID_POWER_C; port++) {
|
||||
err = chub.pd[port].request(pdRequestRemoteSourceExtendedCapabilities);
|
||||
}
|
||||
aTime_MSSleep(2000); //Wait for messages to come in.
|
||||
for (auto & l : loggers) {
|
||||
printf("\n\nPort: %d\n", l->getIndex());
|
||||
processPacketsOneAtATime(l);
|
||||
}
|
||||
///////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
//Multiple Packet Test:
|
||||
///////////////////////////////////////
|
||||
//Attempt to trigger PD communication on every port.
|
||||
//Note: No traffic will occur if the devices does not support PD.
|
||||
for (int port = 0; port <= aUSBHub3c::PORT_ID_t::kPORT_ID_POWER_C; port++) {
|
||||
err = chub.pd[port].request(pdRequestRemoteSourceExtendedCapabilities);
|
||||
}
|
||||
aTime_MSSleep(2000); //Wait for messages to come in.
|
||||
for (auto & l : loggers) {
|
||||
printf("\n\nPort: %d\n", l->getIndex());
|
||||
processMultiplePacketsAtATime(l);
|
||||
l->setEnabled(false); //Disable PD Logging
|
||||
}
|
||||
///////////////////////////////////////
|
||||
|
||||
|
||||
loggers.clear();
|
||||
|
||||
err = chub.disconnect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//Generic packet print formatter.
|
||||
void printBS_PD_Packet(BS_PD_Packet_t& packet) {
|
||||
printf(" - Channel: %d, Seconds: %d, uSeconds: %d, Direction: %d SOP: %d \nData: ",
|
||||
packet.channel, packet.seconds, packet.uSeconds, packet.direction, packet.sop);
|
||||
for(const auto& p : packet.payload) {
|
||||
printf("0x%02X ", p);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
//Get one packet at a time.
|
||||
void processPacketsOneAtATime(std::shared_ptr<PDChannelLogger> logger) {
|
||||
printf("Getting packets one at a time.\n");
|
||||
BS_PD_Packet_t packet;
|
||||
while(aErrNone == logger->getPacket(packet)) {
|
||||
printBS_PD_Packet(packet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Get all available packets in single call.
|
||||
//Note: Packet count is limited up to the default parameter buffer_length
|
||||
void processMultiplePacketsAtATime(std::shared_ptr<PDChannelLogger> logger) {
|
||||
printf("Getting all Packets at once\n");
|
||||
//Get available packets.
|
||||
std::vector<BS_PD_Packet_t> packets;
|
||||
if(aErrNone == logger->getPackets(packets)) {
|
||||
for (auto& p : packets) {
|
||||
printBS_PD_Packet(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
===============================================================================
|
||||
USBHub3c C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This example shows how to access Power Delivery packets from a USBHub3c.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
std::cout << "Creating a USBHub3c module" << std::endl;
|
||||
|
||||
// Create an instance of the USBHub3p
|
||||
aUSBHub3c chub;
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Connect to the hardware.
|
||||
// err = chub.discoverAndConnect(USB, 0x40F5849A); // for a known serial number
|
||||
err = chub.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered connecting to BrainStem module" << std::endl;
|
||||
return 1;
|
||||
|
||||
}
|
||||
else { std::cout << "Connected to BrainStem module." << std::endl; }
|
||||
|
||||
uint8_t upstreamPort = aUSBHUB3C_NUM_USB_PORTS;
|
||||
err = chub.hub.getUpstream(&upstreamPort);
|
||||
if(err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
printf("The current upstream port is: %d\n", upstreamPort);
|
||||
}
|
||||
|
||||
if(err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Disabling all downstream ports." << std::endl;
|
||||
|
||||
for (int port = 0; port < aUSBHUB3C_NUM_USB_PORTS; port++) {
|
||||
|
||||
if(port == upstreamPort) {
|
||||
std::cout << "Skipping upstream Port." << std::endl;
|
||||
}
|
||||
else if(port == aUSBHub3c::kPORT_ID_CONTROL) {
|
||||
std::cout << "The Control port is always enabled" << std::endl;
|
||||
}
|
||||
else if(port == aUSBHub3c::kPORT_ID_POWER_C) {
|
||||
std::cout << "The Power-C port is always enabled" << std::endl;
|
||||
}
|
||||
else {
|
||||
err = chub.hub.port[port].setEnabled(false);
|
||||
std::cout << "Disabling Port " << port << " Error: " << err << std::endl;
|
||||
}
|
||||
|
||||
aTime_MSSleep(400); //Delay so the user can see it.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Enabling all downstream ports." << std::endl;
|
||||
|
||||
for (int port = 0; port < aUSBHUB3C_NUM_USB_PORTS; port++) {
|
||||
|
||||
if(port == upstreamPort) {
|
||||
std::cout << "Skipping upstream Port: " << std::endl;
|
||||
}
|
||||
else if(port == aUSBHub3c::kPORT_ID_CONTROL) {
|
||||
std::cout << "The Control port is always enabled" << std::endl;
|
||||
}
|
||||
else if(port == aUSBHub3c::kPORT_ID_POWER_C) {
|
||||
std::cout << "The Power-C port is always enabled" << std::endl;
|
||||
}
|
||||
else {
|
||||
err = chub.hub.port[port].setEnabled(true);
|
||||
std::cout << "Enabling Port " << port << " Error: " << err << std::endl;
|
||||
}
|
||||
|
||||
aTime_MSSleep(400); //Delay so the user can see it.
|
||||
}
|
||||
}
|
||||
|
||||
//Voltage and Current
|
||||
if(err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Getting VBus and VConn Voltage and Current" << std::endl;
|
||||
std::cout << "Note: When in PD Mode voltage is only present after successful ";
|
||||
std::cout << " negotiation with a device." << std::endl;
|
||||
|
||||
for (int port = 0; port < aUSBHUB3C_NUM_USB_PORTS; port++) {
|
||||
int32_t vBusVoltage = 0;
|
||||
int32_t vBusCurrent = 0;
|
||||
int32_t vConnVoltage = 0;
|
||||
int32_t vConnCurrent = 0;
|
||||
|
||||
std::cout << std::endl;
|
||||
printf("Port: %d\n", port);
|
||||
|
||||
err = chub.hub.port[port].getVbusVoltage(&vBusVoltage);
|
||||
printf("Vbus Voltage: %.2f, Error: %d\n", vBusVoltage/1000000.0, err);
|
||||
|
||||
err = chub.hub.port[port].getVbusCurrent(&vBusCurrent);
|
||||
printf("Vbus Current: %.2f, Error: %d\n", vBusCurrent/1000000.0, err);
|
||||
|
||||
if(port != aUSBHub3c::kPORT_ID_POWER_C) {
|
||||
err = chub.hub.port[port].getVconnVoltage(&vConnVoltage);
|
||||
printf("VConn Voltage: %.2f, Error: %d\n", vConnVoltage/1000000.0, err);
|
||||
|
||||
err = chub.hub.port[port].getVconnCurrent(&vConnCurrent);
|
||||
printf("VConn Current: %.2f, Error: %d\n", vConnCurrent/1000000.0, err);
|
||||
}
|
||||
else { std::cout << "The Power-C port does not have VConn measurements." << std::endl; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Disconnect
|
||||
err = chub.disconnect();
|
||||
if (err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Disconnected from USBHub3c." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
===============================================================================
|
||||
USBHub3c C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the USBHub3c. When executed, this example disables,
|
||||
and then re-enables each of the downstream device ports on the hub. This example
|
||||
also reads the VBus and VConn voltage and current of each port. Plug a device
|
||||
or two in to see the results.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2023 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
std::cout << "Creating a USBHub3c module" << std::endl;
|
||||
|
||||
// Create an instance of the USBHub3p
|
||||
aUSBHub3c chub;
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Connect to the hardware.
|
||||
// err = chub.discoverAndConnect(USB, 0x40F5849A); // for a known serial number
|
||||
err = chub.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered connecting to BrainStem module" << std::endl;
|
||||
return 1;
|
||||
|
||||
}
|
||||
else { std::cout << "Connected to BrainStem module." << std::endl; }
|
||||
|
||||
// VDM Commands are a minimum of 8 bytes chunked into 4 byte blocks
|
||||
// First 4 bytes are SOP
|
||||
// 0 = SOP
|
||||
// 1 = SOP'
|
||||
// 2 = SOP''
|
||||
// 3 = SOP' Debug
|
||||
// 4 = SOP'' Debug
|
||||
// Second 4 bytes are the VDM header according to the USB PD Standard
|
||||
// Any subsequent sets of 4 bytes are the attached VDO's
|
||||
// Example:
|
||||
// SOP 0x00000000
|
||||
// VDM Header 0xFF00A001
|
||||
// No VDOs
|
||||
|
||||
// Discover Identity Command
|
||||
uint32_t buffer[] = {0x00000000, 0xFF00A001};
|
||||
|
||||
err = chub.pd[1].setUEIBytes(powerdeliveryVDM, (uint8_t*)buffer, 8);
|
||||
printf("Sent Discover Identity VDM to Port 1, Err: %d\n", err);
|
||||
|
||||
// Disconnect
|
||||
err = chub.disconnect();
|
||||
if (err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Disconnected from USBHub3c." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
USBHub3c C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the USBHub3c. When executed, this example sends
|
||||
a USB Power Delivery Structured Vendor Defined Message on Port 1. This requeires
|
||||
the PD Logging Software Feature to be unlocked on the USBHub3c.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
std::cout << "Creating a USBHub3c module" << std::endl;
|
||||
|
||||
// Create an instance of the USBHub3p
|
||||
aUSBHub3c chub;
|
||||
aErr err = aErrNone;
|
||||
|
||||
|
||||
|
||||
// Connect to a USBHub3c with Serial Number 0x341F6970 through
|
||||
// serial port '/dev/tty.usbserial-1110' at 115200 baudrate.
|
||||
// Port can be substituted with 'COM3' as an example as well
|
||||
linkSpec spec;
|
||||
const char* serial_port = "/dev/tty.usbserial-1110";
|
||||
spec.type = SERIAL;
|
||||
spec.serial_num = 0x341F6970;
|
||||
spec.t.serial.baudrate = 115200;
|
||||
memset(spec.t.serial.port, 0, sizeof(spec.t.serial.port));
|
||||
memcpy(spec.t.serial.port, serial_port, strlen(serial_port));
|
||||
|
||||
// The following line replaces discoverAndConnect() from most examples, when using
|
||||
// a serial port connection, the linkSpec has to be defined very explicitly
|
||||
// so there is not discovery that's needed.
|
||||
err = chub.connectFromSpec(spec);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered connecting to BrainStem module" << std::endl;
|
||||
return 1;
|
||||
|
||||
}
|
||||
else { std::cout << "Connected to BrainStem module." << std::endl; }
|
||||
|
||||
uint8_t upstreamPort = aUSBHUB3C_NUM_USB_PORTS;
|
||||
err = chub.hub.getUpstream(&upstreamPort);
|
||||
if(err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
printf("The current upstream port is: %d\n", upstreamPort);
|
||||
}
|
||||
|
||||
if(err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Disabling all downstream ports." << std::endl;
|
||||
|
||||
for (int port = 0; port < aUSBHUB3C_NUM_USB_PORTS; port++) {
|
||||
|
||||
if(port == upstreamPort) {
|
||||
std::cout << "Skipping upstream Port." << std::endl;
|
||||
}
|
||||
else if(port == aUSBHub3c::kPORT_ID_CONTROL) {
|
||||
std::cout << "The Control port is always enabled" << std::endl;
|
||||
}
|
||||
else if(port == aUSBHub3c::kPORT_ID_POWER_C) {
|
||||
std::cout << "The Power-C port is always enabled" << std::endl;
|
||||
}
|
||||
else {
|
||||
err = chub.hub.port[port].setEnabled(false);
|
||||
std::cout << "Disabling Port " << port << " Error: " << err << std::endl;
|
||||
}
|
||||
|
||||
aTime_MSSleep(400); //Delay so the user can see it.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Enabling all downstream ports." << std::endl;
|
||||
|
||||
for (int port = 0; port < aUSBHUB3C_NUM_USB_PORTS; port++) {
|
||||
|
||||
if(port == upstreamPort) {
|
||||
std::cout << "Skipping upstream Port: " << std::endl;
|
||||
}
|
||||
else if(port == aUSBHub3c::kPORT_ID_CONTROL) {
|
||||
std::cout << "The Control port is always enabled" << std::endl;
|
||||
}
|
||||
else if(port == aUSBHub3c::kPORT_ID_POWER_C) {
|
||||
std::cout << "The Power-C port is always enabled" << std::endl;
|
||||
}
|
||||
else {
|
||||
err = chub.hub.port[port].setEnabled(true);
|
||||
std::cout << "Enabling Port " << port << " Error: " << err << std::endl;
|
||||
}
|
||||
|
||||
aTime_MSSleep(400); //Delay so the user can see it.
|
||||
}
|
||||
}
|
||||
|
||||
//Voltage and Current
|
||||
if(err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Getting VBus and VConn Voltage and Current" << std::endl;
|
||||
std::cout << "Note: When in PD Mode voltage is only present after successful ";
|
||||
std::cout << " negotiation with a device." << std::endl;
|
||||
|
||||
for (int port = 0; port < aUSBHUB3C_NUM_USB_PORTS; port++) {
|
||||
int32_t vBusVoltage = 0;
|
||||
int32_t vBusCurrent = 0;
|
||||
int32_t vConnVoltage = 0;
|
||||
int32_t vConnCurrent = 0;
|
||||
|
||||
std::cout << std::endl;
|
||||
printf("Port: %d\n", port);
|
||||
|
||||
err = chub.hub.port[port].getVbusVoltage(&vBusVoltage);
|
||||
printf("Vbus Voltage: %.2f, Error: %d\n", vBusVoltage/1000000.0, err);
|
||||
|
||||
err = chub.hub.port[port].getVbusCurrent(&vBusCurrent);
|
||||
printf("Vbus Current: %.2f, Error: %d\n", vBusCurrent/1000000.0, err);
|
||||
|
||||
if(port != aUSBHub3c::kPORT_ID_POWER_C) {
|
||||
err = chub.hub.port[port].getVconnVoltage(&vConnVoltage);
|
||||
printf("VConn Voltage: %.2f, Error: %d\n", vConnVoltage/1000000.0, err);
|
||||
|
||||
err = chub.hub.port[port].getVconnCurrent(&vConnCurrent);
|
||||
printf("VConn Current: %.2f, Error: %d\n", vConnCurrent/1000000.0, err);
|
||||
}
|
||||
else { std::cout << "The Power-C port does not have VConn measurements." << std::endl; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Disconnect
|
||||
err = chub.disconnect();
|
||||
if (err == aErrNone) {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Disconnected from USBHub3c." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
===============================================================================
|
||||
USBHub3c Serial C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the USBHub3c over serial communication.
|
||||
When executed, this example disables, and then re-enables each of the downstream
|
||||
device ports on the hub. This example also reads the VBus and VConn voltage and
|
||||
current of each port. Plug a device or two in to see the results.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# The hub must have the baudrate set to 115200 and serial coms set to BrainStem
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,554 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2022 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
// Created by Acroname Inc. on 1/16/22.
|
||||
// Copyright (c) 2015 Acroname Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h> // standard input / output functions
|
||||
#include <stdlib.h>
|
||||
#include <chrono>
|
||||
|
||||
//Simple Format class.
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
static const uint32_t MAX_STREAM_STATUS_BUFFER = 500;
|
||||
|
||||
using namespace std::chrono;
|
||||
using namespace Acroname::BrainStem;
|
||||
|
||||
|
||||
//Formatting class to help with 64bit values across different architectures.
|
||||
template <class T>
|
||||
class SimpleFormat {
|
||||
public:
|
||||
static std::string formatValueDecimal(const T& numberValue, uint8_t padding) {
|
||||
std::stringstream ss;
|
||||
ss << std::setfill('0') << std::setw(padding) << numberValue;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string formatValueHex(const T& numberValue, uint8_t padding) {
|
||||
std::stringstream ss;
|
||||
ss << "0x" << std::uppercase << std::setfill('0') << std::setw(padding) << std::hex << numberValue;
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//Function Prototypes: Examples
|
||||
void Example_StreamingSpeedComparison(aUSBHub3c& cHub);
|
||||
void Example_StreamingStatus(aUSBHub3c& cHub);
|
||||
void Example_StreamingAsyc(aUSBHub3c& cHub);
|
||||
void Example_StreamingAsycWithUserRef(aUSBHub3c& cHub);
|
||||
void Example_StreamingAsycWildcards(aUSBHub3c& cHub);
|
||||
void Example_StreamingEnableAll(aUSBHub3c& cHub);
|
||||
|
||||
//Function Prototypes: Asyc callbacks.
|
||||
aErr _callback_PortVoltage(const aPacket* packet, void* pRef);
|
||||
aErr _callback_PortVoltageQueue(const aPacket* packet, void* pRef);
|
||||
|
||||
|
||||
//BrainStem streaming comes in 2x flavors.
|
||||
//1. Synchronous: Simply enable the entity you are interested in and start
|
||||
// executing API calls just like you always have. The BrainStem library will
|
||||
// automatically buffer these values and provide you with the most recent value
|
||||
// when requested through an API call.
|
||||
//2. Asynchronous: The user provides a callback and an optional reference to
|
||||
// the BrainStem library. When an update is available the users callback
|
||||
// will be executed.
|
||||
|
||||
//Note 1: Not all API's are capable of streaming.
|
||||
//Note 2: The Asynchronous option provides a dedicated worker thread for all
|
||||
// user callbacks. In other words if you block or take too much time in
|
||||
// the callback the BrainStem library will not be affected, but all user
|
||||
// callbacks will be.
|
||||
//Note 3: Subindex's are typically only used in the PowerDeliveryClass. This class
|
||||
// provides helper functions to decode these.
|
||||
// PowerDeliveryClass::packDataObjectAttributes
|
||||
// PowerDeliveryClass::unpackDataObjectAttributes
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
|
||||
//Connect
|
||||
////////////////////////////////////////////////////////////////
|
||||
aErr err = aErrNone;
|
||||
aUSBHub3c cHub;
|
||||
err = cHub.discoverAndConnect(USB);
|
||||
|
||||
if (err != aErrNone) {
|
||||
printf("Failed to connect to USBHub3c. Error: %d", err);
|
||||
return 1;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
//Examples - Enable one at a time to observe the different
|
||||
//streaming behaviors.
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Example_StreamingSpeedComparison(cHub);
|
||||
|
||||
// Example_StreamingStatus(cHub);
|
||||
|
||||
// Example_StreamingAsyc(cHub);
|
||||
|
||||
// Example_StreamingAsycWithUserRef(cHub);
|
||||
|
||||
// Example_StreamingAsycWildcards(cHub);
|
||||
|
||||
// Example_StreamingEnableAll(cHub);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
cHub.disconnect();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//Examples
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//This example highlights the differences in speed between streaming and non-streaming
|
||||
//Below we will enable streaming on 2 of the USBHub3c ports while leaving the
|
||||
//remaining 6 ports non-streaming (default). We will then fetch the VBus voltage
|
||||
//as quickly as possible displaying their value and the amount of time it
|
||||
//took to execute.
|
||||
//Note: Once streaming is enabled the hardware will transmit values as fast
|
||||
//as they become available. Once a value is read it is flagged as stale
|
||||
//Subsequent calls will provide the stale value, but aErrStreamingStale
|
||||
//will be returned until a new value is received.
|
||||
void
|
||||
Example_StreamingSpeedComparison(aUSBHub3c& cHub) {
|
||||
|
||||
aErr err = aErrNone;
|
||||
|
||||
//Enables streaming for ALL API's that support streaming within port[0].
|
||||
err = cHub.hub.port[0].setStreamEnabled(true);
|
||||
if (err != aErrNone) { printf("Could not enable streaming: %d;\n", err); }
|
||||
|
||||
//Enables streaming for ALL API's that support streaming within port[1].
|
||||
err = cHub.hub.port[1].setStreamEnabled(true);
|
||||
if (err != aErrNone) { printf("Could not enable streaming: %d;\n", err); }
|
||||
|
||||
aTime_MSSleep(1000); //Allow streaming to start coming in.
|
||||
|
||||
int count = 0;
|
||||
auto start = high_resolution_clock::now();
|
||||
auto stop = high_resolution_clock::now();
|
||||
auto duration = duration_cast<microseconds>(stop - start);
|
||||
|
||||
while (count++ < 10) {
|
||||
printf("Loop: %d\n", count);
|
||||
|
||||
for (int x = 0; x < aUSBHUB3C_NUM_USB_PORTS; x++) {
|
||||
|
||||
int32_t voltage = 0;
|
||||
|
||||
start = high_resolution_clock::now();
|
||||
err = cHub.hub.port[x].getVbusVoltage(&voltage); //Execute API's like normal.
|
||||
stop = high_resolution_clock::now();
|
||||
duration = duration_cast<microseconds>(stop - start);
|
||||
|
||||
//aErrStreamStale is expected when a value is requested before
|
||||
//a new value has been received. The old value is returned, but flagged as stale.
|
||||
std::string errString = std::to_string(err);
|
||||
std::string s = (err == aErrStreamStale) ?
|
||||
(errString + " (aErrStreamStale - Expected)") :
|
||||
(errString);
|
||||
|
||||
printf("Port: %d, Voltage: %8d(uV) - Duration: %s(uS) - Err: %s\n",
|
||||
x,
|
||||
voltage,
|
||||
SimpleFormat<long long int>::formatValueDecimal(duration.count(), 5).c_str(),
|
||||
s.c_str());
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}//End while
|
||||
|
||||
err = cHub.hub.port[0].setStreamEnabled(false);
|
||||
if (err != aErrNone) { printf("Could not disable streaming: %d;\n", err); }
|
||||
|
||||
err = cHub.hub.port[1].setStreamEnabled(false);
|
||||
if (err != aErrNone) { printf("Could not disable streaming: %d;\n", err); }
|
||||
}
|
||||
|
||||
|
||||
//In this example we will enable streaming for all the ports. Enabling
|
||||
//Through the Entity layer enables all options and subindex. Option
|
||||
//codes can be found in aProtocoldefs.h.
|
||||
//Once enabled we will then request the status of all streaming value
|
||||
//from both the Entity and Link layers.
|
||||
void
|
||||
Example_StreamingStatus(aUSBHub3c& cHub) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
//Enable streaming for all ports.
|
||||
printf("\n");
|
||||
for (int x = 0; x < aUSBHUB3C_NUM_USB_PORTS; x++) {
|
||||
err = cHub.hub.port[x].setStreamEnabled(true);
|
||||
if (err != aErrNone) { printf("Could not enable streaming on port: %d, err: %d;\n", x, err); }
|
||||
}
|
||||
|
||||
//Wait while stuff happens.
|
||||
aTime_MSSleep(1000);
|
||||
|
||||
//Entity Layer: Get Status - Fetched based on port[x]
|
||||
Acroname::BrainStem::Link::StreamStatusEntry_t status[MAX_STREAM_STATUS_BUFFER];
|
||||
memset(status, 0, sizeof(Acroname::BrainStem::Link::StreamStatusEntry_t) * MAX_STREAM_STATUS_BUFFER);
|
||||
|
||||
printf("\n");
|
||||
printf("EntityClass::getStreamStatus - Raw\n");
|
||||
printf("-------------------------------------------------------\n");
|
||||
for (int x = 0; x < aUSBHUB3C_NUM_USB_PORTS; x++) {
|
||||
size_t unloadedLength = 0;
|
||||
err = cHub.hub.port[x].getStreamStatus(status, MAX_STREAM_STATUS_BUFFER, &unloadedLength);
|
||||
|
||||
//Print status in raw form.
|
||||
for(size_t y = 0; y < unloadedLength; y++) {
|
||||
printf("Port: %d, Stream Key: %s, Value: %d\n",
|
||||
x,
|
||||
SimpleFormat<uint64_t>::formatValueHex(status[y].key, 16).c_str(),
|
||||
status[y].value);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
printf("EntityClass::getStreamStatus - Decoded\n");
|
||||
printf("-------------------------------------------------------\n");
|
||||
for (int x = 0; x < aUSBHUB3C_NUM_USB_PORTS; x++) {
|
||||
size_t unloadedLength = 0;
|
||||
err = cHub.hub.port[x].getStreamStatus(status, MAX_STREAM_STATUS_BUFFER, &unloadedLength);
|
||||
|
||||
//Print status in extracted form.
|
||||
for (size_t y = 0; y < unloadedLength; y++) {
|
||||
printf("Port Entity: Port: %d, subindex: %d, option: %d, Value: %d\n",
|
||||
x,
|
||||
Link::getStreamKeyElement(status[y].key, Link::STREAM_KEY_SUBINDEX),
|
||||
Link::getStreamKeyElement(status[y].key, Link::STREAM_KEY_OPTION),
|
||||
status[y].value);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
//Link Layer: Get Streaming Status
|
||||
printf("\n");
|
||||
if (Link* link = cHub.getLink()) {
|
||||
|
||||
//Get ALL status by using the wildcards (Link::STREAM_WILDCARD)
|
||||
Acroname::BrainStem::Link::StreamStatusEntry_t allStatus[MAX_STREAM_STATUS_BUFFER];
|
||||
memset(allStatus, 0, sizeof(Acroname::BrainStem::Link::StreamStatusEntry_t) * MAX_STREAM_STATUS_BUFFER);
|
||||
size_t unloadedLength = 0;
|
||||
err = link->getStreamStatus(cHub.getModuleAddress(),
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
allStatus,
|
||||
MAX_STREAM_STATUS_BUFFER,
|
||||
&unloadedLength);
|
||||
|
||||
if(err == aErrNone) {
|
||||
//Print status in raw form.
|
||||
printf("LinkClass::getStreamStatus - Raw\n");
|
||||
printf("-------------------------------------------------------\n");
|
||||
for(size_t x = 0; x < unloadedLength; x++) {
|
||||
printf("Stream Key: %s, Value: %d\n",
|
||||
SimpleFormat<uint64_t>::formatValueHex(allStatus[x].key, 16).c_str(),
|
||||
allStatus[x].value);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
//Print status in extracted form.
|
||||
printf("LinkClass::getStreamStatus - Decoded\n");
|
||||
printf("-------------------------------------------------------\n");
|
||||
for (size_t x = 0; x < unloadedLength; x++) {
|
||||
printf("module: %d, cmd: %2d, option: %2d, index: %d, subindex: %3d, value %d\n",
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_MODULE_ADDRESS),
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_CMD),
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_OPTION),
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_INDEX),
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_SUBINDEX),
|
||||
allStatus[x].value);
|
||||
}
|
||||
}
|
||||
else { printf("Error: %d, getting status.", err); }
|
||||
}
|
||||
|
||||
//Disable Streaming for all ports.
|
||||
//Note: Once streaming is disable, get status calls are no longer available.
|
||||
printf("\n");
|
||||
for (int x = 0; x < aUSBHUB3C_NUM_USB_PORTS; x++) {
|
||||
err = cHub.hub.port[x].setStreamEnabled(false);
|
||||
if (err != aErrNone) { printf("Could not disable streaming on port: %d, err: %d;\n", x, err); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//In this example we show how the streaming functionality can be used asynchronously
|
||||
//by providing a function callback.
|
||||
void
|
||||
Example_StreamingAsyc(aUSBHub3c& cHub) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
//Register callback.
|
||||
err = cHub.hub.port[0].registerOptionCallback(portVbusVoltage, //Option code for cmdPORT
|
||||
true, //Enable callback
|
||||
_callback_PortVoltage, //Callback function
|
||||
NULL); //No ref
|
||||
if (err != aErrNone) { printf("Could not register callback: %d;\n", err); }
|
||||
|
||||
//Wait while stuff happens.
|
||||
aTime_MSSleep(1000);
|
||||
|
||||
//Unregister callback
|
||||
err = cHub.hub.port[0].registerOptionCallback(portVbusVoltage, //Option code
|
||||
false, //Disable streaming
|
||||
NULL, //No callback
|
||||
NULL); //No ref
|
||||
if (err != aErrNone) { printf("Could not unregister callback: %d;\n", err); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
//This example is exactly the same as the previous one except we provide
|
||||
//reference parameter. This is helpful for gathering information to be handled
|
||||
//later.
|
||||
void
|
||||
Example_StreamingAsycWithUserRef(aUSBHub3c& cHub) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
//Thread-safe queue when used by a single producer (thread A - BrainStem Worker Thread)
|
||||
//and single consumer (thread B - Main Thread (this))
|
||||
Acroname::LocklessQueue_SPSC<int32_t> queue;
|
||||
|
||||
//Register callback.
|
||||
err = cHub.hub.port[0].registerOptionCallback(portVbusVoltage, //Option code
|
||||
true, //Enable
|
||||
_callback_PortVoltageQueue, //Callback
|
||||
(void*)&queue); //user ref
|
||||
if (err != aErrNone) { printf("Could not register callback: %d;\n", err); }
|
||||
|
||||
int count = 0;
|
||||
while (count++ < 10) {
|
||||
printf("Loop: %d\n", count);
|
||||
|
||||
//Wait while stuff happens.
|
||||
aTime_MSSleep(200);
|
||||
|
||||
//Process/consume queue.
|
||||
bool success = true;
|
||||
while (success) {
|
||||
int32_t voltage = 0;
|
||||
success = queue.pop(&voltage);
|
||||
if (success) {
|
||||
printf("Voltage: %.6f\n", double(voltage) / 1000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Unregister callback
|
||||
err = cHub.hub.port[0].registerOptionCallback(portVbusVoltage, //Option code
|
||||
false, //Disable
|
||||
NULL, //No callback
|
||||
NULL); //No ref
|
||||
if (err != aErrNone) { printf("Could not unregister callback: %d;\n", err); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Here we show how you can use the link later for even more customization.
|
||||
//The benefit of this option is that you can use wildcards to preform a mass
|
||||
//registration. In this case we will register a callback for portVbusVoltage
|
||||
//and for ALL ports. This means we will need to interrogate the packet for which
|
||||
//port index the packet refers too.
|
||||
void
|
||||
Example_StreamingAsycWildcards(aUSBHub3c& cHub) {
|
||||
|
||||
//Bulk registration - Specific cmd and option, but all indexes (Link::STREAM_WILDCARD)
|
||||
if (Link* link = cHub.getLink()) {
|
||||
link->registerStreamCallback(cHub.getModuleAddress(), //address
|
||||
cmdPORT, //cmd
|
||||
portVbusVoltage, //option
|
||||
Link::STREAM_WILDCARD, //index (ie ALL)
|
||||
true, //Enable
|
||||
_callback_PortVoltage, //Callback
|
||||
NULL); //No ref.
|
||||
}
|
||||
|
||||
//Wait while stuff happens.
|
||||
aTime_MSSleep(1000);
|
||||
|
||||
//Bulk un-registration callbacks.
|
||||
if (Link* link = cHub.getLink()) {
|
||||
|
||||
//In the future this will also call enable/disable.
|
||||
link->registerStreamCallback(cHub.getModuleAddress(), //address
|
||||
cmdPORT, //cmd
|
||||
portVbusVoltage, //option
|
||||
Link::STREAM_WILDCARD, //index (ie ALL)
|
||||
false, //disable
|
||||
NULL, //Callback
|
||||
NULL); //Callback ref.
|
||||
}
|
||||
|
||||
aTime_MSSleep(10); //Allow callbacks to finish up.
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Last but not least is the enable all command. Once executed
|
||||
//the device will begin streaming all values it is capable of streaming.
|
||||
//These values can be accessed through any normal API call or through
|
||||
//the bulk getStatus command as shown in this example.
|
||||
//Note: Not all commands are capable of streaming.
|
||||
void
|
||||
Example_StreamingEnableAll(aUSBHub3c& cHub) {
|
||||
aErr err = aErrNone;
|
||||
|
||||
//Enable All
|
||||
if (Link* link = cHub.getLink()) {
|
||||
link->enableStream(cHub.getModuleAddress(),
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
true);
|
||||
|
||||
//Wait for data to come in.
|
||||
aTime_MSSleep(1000);
|
||||
|
||||
//Get ALL status.
|
||||
Acroname::BrainStem::Link::StreamStatusEntry_t allStatus[MAX_STREAM_STATUS_BUFFER];
|
||||
size_t unloadedLength = 0;
|
||||
err = link->getStreamStatus(cHub.getModuleAddress(),
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
allStatus,
|
||||
MAX_STREAM_STATUS_BUFFER,
|
||||
&unloadedLength);
|
||||
|
||||
if(err == aErrNone) {
|
||||
for(size_t x = 0; x < unloadedLength; x++) {
|
||||
printf("module: %d, cmd: %2d, option: %2d, index: %d, subindex: %3d, value %d\n",
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_MODULE_ADDRESS),
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_CMD),
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_OPTION),
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_INDEX),
|
||||
Link::getStreamKeyElement(allStatus[x].key, Link::STREAM_KEY_SUBINDEX),
|
||||
allStatus[x].value);
|
||||
}
|
||||
}
|
||||
else { printf("Error: %d, getting status.", err); }
|
||||
|
||||
//Disable All
|
||||
link->enableStream(cHub.getModuleAddress(),
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
Link::STREAM_WILDCARD,
|
||||
false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//End Examples
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//Callback functions
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//Basic Asynchronous callback that simpley prints out the data it receives.
|
||||
aErr
|
||||
_callback_PortVoltage(const aPacket* packet, void* pRef) {
|
||||
uint64_t timestamp = 0;
|
||||
uint32_t seconds = 0;
|
||||
uint32_t uSeconds = 0;
|
||||
int32_t voltage = 0;
|
||||
|
||||
aErr err = Link::getStreamSample(packet, ×tamp, (uint32_t*)&voltage);
|
||||
|
||||
//The timestamp can be further decoded with helper functions. (variables not used)
|
||||
Link::getTimestampParts(timestamp, &seconds, &uSeconds);
|
||||
|
||||
if (err == aErrNone) {
|
||||
uint8_t index = 0;
|
||||
err = aPacket_GetIndex(packet, &index);
|
||||
if (err == aErrNone) {
|
||||
printf("Port: %d, TS: %d:%06d (s:uS), Voltage: %d\n", index, seconds, uSeconds, voltage);
|
||||
}
|
||||
else { printf("Error %d, in _callback_PortVoltage::aPacket_GetIndex", err); }
|
||||
}
|
||||
else { printf("Error %d, in _callback_PortVoltage::getStreamSample", err); }
|
||||
|
||||
return aErrNone;
|
||||
}
|
||||
|
||||
|
||||
//Advanced Asynchronous callback that decodes a user provide reference
|
||||
//and stores the data within it.
|
||||
aErr
|
||||
_callback_PortVoltageQueue(const aPacket* packet, void* pRef) {
|
||||
|
||||
//Fetch user reference. User MUST know the type that was passed in! You have been warned!
|
||||
Acroname::LocklessQueue_SPSC<int32_t>* queue = (Acroname::LocklessQueue_SPSC<int32_t>*) pRef;
|
||||
|
||||
//Fetch sample
|
||||
uint64_t timestamp = 0;
|
||||
int32_t voltage = 0;
|
||||
|
||||
aErr err = Link::getStreamSample(packet, ×tamp, (uint32_t*)&voltage);
|
||||
|
||||
//If successful, store the sample
|
||||
if (err == aErrNone) {
|
||||
queue->push(voltage); //Store sample
|
||||
}
|
||||
else { printf("Error %d, in _callback_PortVoltageQueue::getStreamSample", err); }
|
||||
|
||||
return aErrNone;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//End Callback functions
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
===============================================================================
|
||||
USBHub3c C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example that demonstates the streaming capability of the
|
||||
USBHub3c.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// main.cpp
|
||||
// BrainStem2Example
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Copyright (c) 2018 Acroname Inc. - All Rights Reserved //
|
||||
// //
|
||||
// This file is part of the BrainStem release. See the license.txt //
|
||||
// file included with this package or go to //
|
||||
// https://acroname.com/software/brainstem-development-kit //
|
||||
// for full license details. //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include "BrainStem2/BrainStem-all.h"
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
std::cout << "Creating a USBHub3+ module" << std::endl;
|
||||
|
||||
// Create an instance of the USBHub3p
|
||||
aUSBHub3p hub;
|
||||
aErr err = aErrNone;
|
||||
|
||||
// Connect to the hardware.
|
||||
// The only difference for TCP/IP modules is to change 'USB' to 'TCP';
|
||||
// err = stem.discoverAndConnect(USB, 0x40F5849A); // for a known serial number
|
||||
err = hub.discoverAndConnect(USB);
|
||||
if (err != aErrNone) {
|
||||
std::cout << "Error "<< err <<" encountered connecting to BrainStem module" << std::endl;
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
std::cout << "Connected to BrainStem module." << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::cout << "Disabling ports:" << std::endl;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
// Disable all ports
|
||||
err = hub.usb.setPortDisable(i);
|
||||
std::cout << " port: " << i << " Error: " << err << std::endl;
|
||||
// We wait 400ms only to show the disable process more clearly.
|
||||
aTime_MSSleep(400);
|
||||
|
||||
}
|
||||
|
||||
std::cout << "Enabling ports:" << std::endl;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
// Renable all ports.
|
||||
err = hub.usb.setPortEnable(i);
|
||||
std::cout << " port: " << i << " Error: " << err << std::endl;
|
||||
// We wait 400ms only to show the renable process more clearly.
|
||||
aTime_MSSleep(400);
|
||||
|
||||
}
|
||||
|
||||
// Disconnect
|
||||
err = hub.disconnect();
|
||||
if (err == aErrNone) {
|
||||
std::cout << "Disconnected from BrainStem module." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
===============================================================================
|
||||
USBHub3p C++ Example Readme
|
||||
===============================================================================
|
||||
|
||||
This is a basic C++ example for the USBHub3p. When executed, this example disables,
|
||||
and then re-enables each of the downstream device ports on the hub. Plug a device
|
||||
or two in to see the results.
|
||||
|
||||
Notes:
|
||||
===============================================================================
|
||||
|
||||
# To build, copy the lib directory into this directory. The lib directory contains
|
||||
the required header files, and the Brainstem2 shared object file.
|
||||
|
||||
# The output directory is linux_BrainStem2Example/Debug.
|
||||
|
||||
# A build step has been added to the project that copies the shared object into
|
||||
the build output directory. In addition the runpath is updated to search in
|
||||
the same directory as the executable.
|
||||
|
||||
If you have questions, please see the reference, or check out our guides
|
||||
at www.acroname.com.
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
# Brainstem2Example C
|
||||
|
||||
CPP = g++
|
||||
ROOT = .
|
||||
TARGET = BrainStem2Example
|
||||
OUT := linux_$(TARGET)
|
||||
DBG_DST := $(OUT)/Debug
|
||||
REL_DST := $(OUT)/Release
|
||||
|
||||
# We are looking for the BrainStem2 library in
|
||||
# a lib folder sibling to this makefile. Change
|
||||
# these defines to point somewhere else if this
|
||||
# is not the case.
|
||||
LIBRARIES := -L$(ROOT)/lib -lBrainStem2
|
||||
INCLUDES := -Ilib/
|
||||
|
||||
# We add the current directory to the rpath expecting
|
||||
# that libBrainStem2.so will be copied into the build
|
||||
# folder. If this is not the case adjust the rpath
|
||||
# do match your needs.
|
||||
CFLAGS = -std=c++11 -Wall -Werror -Wl,-rpath,. $(INCLUDES)
|
||||
|
||||
all : dirs
|
||||
make app
|
||||
|
||||
app : debug release
|
||||
|
||||
.PHONY : debug
|
||||
debug: dirs
|
||||
$(CPP) $(CFLAGS) BrainStem2Example/main.cpp $(LIBRARIES) -o $(DBG_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(DBG_DST)
|
||||
|
||||
.PHONY : release
|
||||
release: dirs
|
||||
$(CPP) $(CFLAGS) -DNDEBUG BrainStem2Example/main.cpp $(LIBRARIES) -o $(REL_DST)/BrainStem2Example
|
||||
cp lib/libBrainStem2.so $(REL_DST)
|
||||
|
||||
.PHONY : dirs
|
||||
dirs:
|
||||
mkdir -p $(DBG_DST)
|
||||
mkdir -p $(REL_DST)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUT)
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
brainstem2_signal.py
|
||||
=========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This examples creates a signal loopback using a MTMUSBStem. It creates a square wave using the Digital pins and the Signal interface, which is the interface which allows those pins to produce square waves. The characteristics of the square wave are defined by setting T3 and T2 times on the Signal interface. That square wave is output from one Digital pin and then read in by another Digital pin. Lastly, the Duty Cycle of the square wave produced is calculated using the T3 and T2 times read from the input Signal interface.
|
||||
|
||||
It should be noted that while there are presets for the pins, the interfaces, the T3 time, and the T2 time, they are configurable by the user.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
# Copyright (c) 2019 Acroname Inc. - All Rights Reserved
|
||||
#
|
||||
# This file is part of the BrainStem release. See the license.txt
|
||||
# file included with this package or go to
|
||||
# https://acroname.com/software/brainstem-development-kit
|
||||
# for full license details.
|
||||
|
||||
"""
|
||||
This Example shows creating a signal loopback with the MTMUSBStem. Since this is a
|
||||
signal loopback, this example assumes you have a jumper cable connection between Digital pins
|
||||
6 and 4. Please see the product datasheet and the reference material at: http://acroname.com/reference
|
||||
1. Create a MTMUSBStem object and connect.
|
||||
2. Configure the MTMUSBStem to output a square wave via digital pin 6.
|
||||
3. Set the T3 Time for signal entity 2 to 100000000.
|
||||
4. Get and display the T3 Time for signal 2.
|
||||
5. Set the T2 Time for signal entity 2 to 50000000.
|
||||
6. Get and display the T2 Time for signal entity 2.
|
||||
7. Enable the signal output on signal entity 2.
|
||||
8. Configure the MTMUSBStem to receive a square wave via digital pin 4.
|
||||
9. Enable the signal input on signal entity 0.
|
||||
10. Get and display the T3 Time for signal entity 0.
|
||||
11. Get and display the T2 Time for signal entity 0.
|
||||
12. Calculate the Duty Cycle with the read T3 and T2 values.
|
||||
13. Disable signal entity 2.
|
||||
14. Disable signal entity 0.
|
||||
15. Disconnect from the MTMUSBStem object.
|
||||
"""
|
||||
|
||||
import brainstem
|
||||
|
||||
from brainstem.result import Result
|
||||
from brainstem.stem import Digital
|
||||
from time import sleep
|
||||
|
||||
print("Creating a signal loopback, between digital pins 6 and 4 with a MTMUSBStem module\n")
|
||||
|
||||
# Lookup Table for Signal to Digital Mapping
|
||||
# The indicies refer to the signal [0-4], while the values
|
||||
# held in those indicies refer to the digital pins they
|
||||
# are associated with.
|
||||
# Note: This Lookup Table is for the MTMUSBStem only.
|
||||
# Digital Entity to Signal Entity mapping varies per
|
||||
# device. Please refer to the data sheet for the MTM
|
||||
# Device you are using to see its unique mapping.
|
||||
SIGNAL_TO_DIGITAL_MAPPING = [4, 5, 6, 7, 8]
|
||||
|
||||
# Preset T Times. Editable by user
|
||||
T3_TIME = 100000000
|
||||
T2_TIME = 50000000
|
||||
|
||||
# Signal Entity indexs to be used for input and output.
|
||||
SIGNAL_OUTPUT_IDX = 2;
|
||||
SIGNAL_INPUT_IDX = 0;
|
||||
|
||||
# Find the first BrainStem Module connected and store its Spec in spec
|
||||
spec = brainstem.discover.findFirstModule(brainstem.link.Spec.USB)
|
||||
|
||||
# If there is no spec...
|
||||
if spec is None:
|
||||
# ...there is no reason to continue
|
||||
print("Could not find any BrainStem Modules")
|
||||
# Else, let's continue
|
||||
else:
|
||||
# Create a MTMUSBStem object
|
||||
stem = brainstem.stem.MTMUSBStem()
|
||||
# Connect to this object using the serial number contained in spec.
|
||||
# This serial number should be the serial number of the MTMUSBStem
|
||||
# currently connected.
|
||||
err = stem.connect(spec.serial_number)
|
||||
# If there was a connection error...
|
||||
if err != Result.NO_ERROR:
|
||||
# ...there is no reason to continue
|
||||
print("Error %d encountered connecting to Brainstem Module" % err)
|
||||
# Else, let's continue
|
||||
else:
|
||||
# Output
|
||||
|
||||
# Initialize the boolean which denotes whether a fatal error has occurred
|
||||
fatal_error_occurred = False
|
||||
|
||||
# Configure the MTMUSBStem to output a square wave via digital pin 6
|
||||
err = stem.digital[SIGNAL_TO_DIGITAL_MAPPING[SIGNAL_OUTPUT_IDX]].setConfiguration(Digital.CONFIGURATION_SIGNAL_OUTPUT)
|
||||
# If there was an error...
|
||||
if err != Result.NO_ERROR:
|
||||
# ...the digital pin signal output was NOT configured successfully
|
||||
fatal_error_occurred = True
|
||||
print("Error %d encountered attempting to set the configuration for digital pin 6 on the MTM USB Stem" % err)
|
||||
|
||||
print("\n")
|
||||
|
||||
# Set the T3 Time for signal entity 2
|
||||
err = stem.signal[SIGNAL_OUTPUT_IDX].setT3Time(T3_TIME)
|
||||
# If there was an error...
|
||||
if err != Result.NO_ERROR:
|
||||
# ...T Time was NOT set successfully. There's no reason to try to get the T3 Time from signal entity 2
|
||||
fatal_error_occurred = True
|
||||
print("Error %d encountered attempting to set the T3 Time for signal entity 2 on the MTMUSBStem" % err)
|
||||
# Else, let's get the T3 Time from signal entity 2
|
||||
else:
|
||||
# Get the T3 Time from signal entity 2, and display it if it was retrieved with no error
|
||||
err_and_time = stem.signal[SIGNAL_OUTPUT_IDX].getT3Time()
|
||||
if err_and_time.error != Result.NO_ERROR:
|
||||
print("Error %d encountered attempting to get the T3 Time for signal entity 2 on the MTMUSBStem" % err_and_time.error)
|
||||
elif err_and_time.value == 0:
|
||||
fatal_error_occurred = True
|
||||
print("T3 Time cannot be 0!")
|
||||
else:
|
||||
read_t3_time_from_output_pin = err_and_time.value
|
||||
print("T3 Time from Output Pin: %d" % read_t3_time_from_output_pin)
|
||||
|
||||
# Set the T2 Time for signal entity 2
|
||||
err = stem.signal[SIGNAL_OUTPUT_IDX].setT2Time(T2_TIME)
|
||||
# If there was an error...
|
||||
if err != Result.NO_ERROR:
|
||||
# ...T Time was NOT set successfully. There's no reason to try to get the T2 Time from signal entity 2
|
||||
fatal_error_occurred = True
|
||||
print("Error %d encountered attempting to set the T2 Time for signal entity 2 on the MTMUSBStem" % err)
|
||||
# Else, let's get the T2 Time from signal entity 2
|
||||
else:
|
||||
# Get the T2 Time from signal entity 2, and display it if it was retrieved with no error
|
||||
err_and_time = stem.signal[SIGNAL_OUTPUT_IDX].getT2Time()
|
||||
if err_and_time.error != Result.NO_ERROR:
|
||||
print("Error %d encountered attempting to get the T2 Time for signal entity 2 on the MTMUSBStem" % err_and_time.error)
|
||||
else:
|
||||
read_t2_time_from_output_pin = err_and_time.value
|
||||
print("T2 Time from Output Pin: %d" % read_t2_time_from_output_pin)
|
||||
|
||||
print("\n")
|
||||
|
||||
# Enable the signal ouput on signal entity 2
|
||||
err = stem.signal[SIGNAL_OUTPUT_IDX].setEnable(True)
|
||||
# If there was an error...
|
||||
if err != Result.NO_ERROR:
|
||||
# ...signal output on signal entity 2 was NOT enabled
|
||||
fatal_error_occurred = True
|
||||
print("Error %d encountered attempting to set the signal enabled state of signal 2 to true on the MTMUSBStem" % err)
|
||||
print("\n")
|
||||
|
||||
# If digital pin 6 was not configured successfully, T Time was not set successfully, or signal output on signal entity 2 was not enabled successfully...
|
||||
if fatal_error_occurred:
|
||||
# ...there is no reason to continue
|
||||
print("A Fatal Error occurred in the Output phase. Aborting example!")
|
||||
# Else, let's continue
|
||||
else:
|
||||
# Input
|
||||
|
||||
# Configure the MTMUSBStem to take in a square wave via digital pin 4
|
||||
err = stem.digital[SIGNAL_TO_DIGITAL_MAPPING[SIGNAL_INPUT_IDX]].setConfiguration(Digital.CONFIGURATION_SIGNAL_INPUT)
|
||||
if err != Result.NO_ERROR:
|
||||
fatal_error_occurred = True
|
||||
print("Error %d encountered attempting to set the configuration for digital pin 4 on the MTMUSBStem" % err)
|
||||
print("\n")
|
||||
|
||||
# Enable the signal input on signal entity 0
|
||||
err = stem.signal[SIGNAL_INPUT_IDX].setEnable(True)
|
||||
if err != Result.NO_ERROR:
|
||||
fatal_error_occurred = True
|
||||
print("Error %d encountered attempting to set the signal enabled state of signal 0 to true on the MTMUSBStem" % err)
|
||||
print("\n")
|
||||
|
||||
# Sleep for 500ms so the ouput can stabilize and the input can have time to calculate the time high/low
|
||||
sleep(.5)
|
||||
|
||||
# Get the T3 Time from signal entity 0, and display it if it is not 0 and was retrieved with an error
|
||||
err_and_time = stem.signal[SIGNAL_INPUT_IDX].getT3Time()
|
||||
if err_and_time.error != Result.NO_ERROR:
|
||||
fatal_error_occurred = True
|
||||
print("Error %d encountered attempting to get the T3 Time for signal entity 0 on the MTMUSBStem" % err_and_time.error)
|
||||
elif err_and_time.value == 0:
|
||||
fatal_error_occurred = True
|
||||
print("T3 Time cannot be 0!")
|
||||
else:
|
||||
read_t3_time_from_input_pin = err_and_time.value
|
||||
print("T3 Time from Input Pin: %d" % read_t3_time_from_input_pin)
|
||||
|
||||
# Get the T2 Time from signal entity 0, and display it if it was retrieved with no error
|
||||
err_and_time = stem.signal[SIGNAL_INPUT_IDX].getT2Time()
|
||||
if err_and_time.error != Result.NO_ERROR:
|
||||
fatal_error_occurred = True
|
||||
print("Error %d encountered attempting to get the T3 Time for signal entity 0 on the MTMUSBStem" % err_and_time.error)
|
||||
else:
|
||||
read_t2_time_from_input_pin = err_and_time.value
|
||||
print("T2 Time from Input Pin: %d" % read_t2_time_from_input_pin)
|
||||
|
||||
print("\n")
|
||||
|
||||
# If digital pin 4 was not configured correctly, signal input on signal entity 0 was not enabled, or T Time was not read correctly
|
||||
if fatal_error_occurred:
|
||||
# ...there is no reason to continue
|
||||
print("A Fatal Error occurred in the Input phase. Aborting example!")
|
||||
# Else, let's continue
|
||||
else:
|
||||
# Compute the Duty Cycle and display it
|
||||
duty_cycle = (float(read_t2_time_from_input_pin) / float(read_t3_time_from_input_pin)) * 100.0
|
||||
|
||||
print("Duty Cycle: %f" % duty_cycle)
|
||||
|
||||
# Disable the signal output on signal entity 2
|
||||
err = stem.signal[SIGNAL_OUTPUT_IDX].setEnable(False)
|
||||
if err != Result.NO_ERROR:
|
||||
print("Error %d encountered attempting to set the signal enabled state of signal entity 2 to false on the MTMUSBStem" % err)
|
||||
|
||||
# Disable the signal input on signal entity 0
|
||||
err = stem.signal[SIGNAL_INPUT_IDX].setEnable(False)
|
||||
if err != Result.NO_ERROR:
|
||||
print("Error %d encountered attempting to set the signal enabled state of signal entity 0 to false on the MTMUSBStem" % err)
|
||||
|
||||
# Disconnect from the MTMUSBStem
|
||||
stem.disconnect()
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
brainstem_bulk_capture.py
|
||||
=========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This script captures 8,000 analog voltage samples at a sample rate of 200,000 samples per second (Hertz) on Analog channel 0, using an MTMUSBStem. Since the bulk capture channel, number of samples, and sample rate are user configurable, the script prints out these values before performing the bulk capture. After the bulk capture has occurred the script prints out a list of all the samples. Each sample has its own line, and displays the sample number, the voltage calculated from each sample's two bytes of data, and the raw data from each sample's two bytes of data.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
# Copyright (c) 2018 Acroname Inc. - All Rights Reserved
|
||||
#
|
||||
# This file is part of the BrainStem development package.
|
||||
# See file LICENSE or go to https://acroname.com/software/brainstem-development-kit for full license details.
|
||||
import time
|
||||
import brainstem
|
||||
# for easy access to error constants
|
||||
from brainstem.result import Result
|
||||
|
||||
# Constants
|
||||
BULK_CAPTURE_CHANNEL = 0
|
||||
NUM_SAMPLES = 8000
|
||||
SAMPLE_RATE = 200000
|
||||
|
||||
print ("\nCreating MTMUSBStem Object.")
|
||||
# Create MTMUSBStem object
|
||||
stem = brainstem.stem.MTMUSBStem()
|
||||
|
||||
# Locate and connect to the first object you find on USB
|
||||
# Easy way: 1=USB, 2=TCPIP
|
||||
print("Attempting to connect.")
|
||||
err = stem.discoverAndConnect(brainstem.link.Spec.USB)
|
||||
if(err == Result.NO_ERROR):
|
||||
print("Connected")
|
||||
else:
|
||||
print("Error connecting to device. Exiting.")
|
||||
exit(1)
|
||||
|
||||
print("")
|
||||
print("Configuring Bulk capture")
|
||||
print("Analog Channel: %d" % BULK_CAPTURE_CHANNEL)
|
||||
print("Number of Samples: %d" % NUM_SAMPLES)
|
||||
print("Sample Rate: %d" % SAMPLE_RATE)
|
||||
# Setup Analog Entity for Bulk capture configuration
|
||||
stem.analog[BULK_CAPTURE_CHANNEL].setBulkCaptureNumberOfSamples(NUM_SAMPLES)
|
||||
stem.analog[BULK_CAPTURE_CHANNEL].setBulkCaptureSampleRate(SAMPLE_RATE)
|
||||
|
||||
print("")
|
||||
print("Starting bulk capture")
|
||||
captureState = 0
|
||||
stem.analog[BULK_CAPTURE_CHANNEL].initiateBulkCapture()
|
||||
# Wait for Bulk Capture to finish.
|
||||
# You can go do other stuff if you would like... Including other BrainStem functions.
|
||||
# but you will need to check that it is finished before unloading the data
|
||||
while(captureState != brainstem.stem.Analog.BULK_CAPTURE_FINISHED):
|
||||
if(captureState == brainstem.stem.Analog.BULK_CAPTURE_ERROR):
|
||||
print("There was an Error with Bulk Capture")
|
||||
break
|
||||
captureState = stem.analog[BULK_CAPTURE_CHANNEL].getBulkCaptureState().value
|
||||
time.sleep(.1)
|
||||
|
||||
print("Unloading data from device")
|
||||
data = stem.store[brainstem.stem.Store.RAM_STORE].unloadSlot(0)
|
||||
values = bytearray(data.value)
|
||||
|
||||
# Process 8bit values 2 bytes at a time for a 16bit value (Little Endian)
|
||||
# i.e.
|
||||
# val[0] = XXXXXXXX = LSB's
|
||||
# val[1] = YYYYYYYY = MSB's
|
||||
# combinedVal = YYYYYYYY XXXXXXXX for a 16 bit value
|
||||
# Repeat until all the data has been processed
|
||||
# Note: ",2" increments loop counter "i" by 2
|
||||
print("")
|
||||
for i in range(0, len(values)-1, 2):
|
||||
combinedValue = ((values[i]) + (values[i+1] << 8))
|
||||
print ("Sample: %d \tVoltage: %.3f \tRaw: %d" % (i/2, (combinedValue/65535.0)*3.3, combinedValue))
|
||||
|
||||
print("Disconnecting from Device")
|
||||
stem.disconnect()
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
brainstem_client_example.py
|
||||
========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This example is intended to highlight the multi-process and
|
||||
network capabilities of BrainStem modules. This application
|
||||
is intended to be used in conjunction with a "client" example (Any API)
|
||||
however, it will work with any application or even HubTool
|
||||
if configured properly.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
# Copyright (c) 2023 Acroname Inc. - All Rights Reserved
|
||||
#
|
||||
# This file is part of the BrainStem development package.
|
||||
# See file LICENSE or go to https://acroname.com/software/brainstem-development-kit for full license details.
|
||||
import brainstem
|
||||
from brainstem.result import Result
|
||||
from brainstem.link import aEtherConfig
|
||||
from brainstem import _BS_C #BrainStem lib handle, for aProtocolDefs.h values only!
|
||||
|
||||
import sys
|
||||
|
||||
#This example is intended to highlight the multi-process and
|
||||
#is intended to be used in conjunction with a "client" example (Any API)
|
||||
#network capabilities of BrainStem modules. This application
|
||||
#however, it will work with any application or even HubTool
|
||||
#if configured properly.
|
||||
|
||||
#Note 1:
|
||||
# The actual server is created by the first process to connect to the device.
|
||||
# This means you could run the "Client" or even HubTool first in
|
||||
# which it would create/own the server and this application would be
|
||||
# a client. This is intended to smooth over the user experience
|
||||
# but is important to remember when closing applications. If
|
||||
# The "Server" application is closed it will result in the "Clients"
|
||||
# losing access to the device.
|
||||
|
||||
#Note 2:
|
||||
# This application was created with the aUSBHub3p object. If
|
||||
# your devices differs (say a USBCSwitch) you will need to change
|
||||
# all instances of aUSBHub3p to aUSBCSwitch in order to connect to
|
||||
# the device. This is a result of discoveryAndConnect as it will
|
||||
# only connect to a device that matches the object type. It is
|
||||
# possible to use the generic "Module" object; however, this was avoided
|
||||
# in order to present a simplified example. For more connection types
|
||||
# see the "Discovery-and-Connection" example
|
||||
|
||||
#Note 3:
|
||||
# If you intended to connect to a device that is not connected
|
||||
# to your local machine or on your local intranet (local network)
|
||||
# you will need to define a linkSpec with the intended ip and port
|
||||
# number of the device and then use "connectFromSpec".
|
||||
# Discovery works through broadcast and multicast packets;
|
||||
# neither of which work for the internet (global network).
|
||||
# For more connection types see the "Discovery-and-Connection"
|
||||
|
||||
#Note 4:
|
||||
# Additional network details are described in _configure_aEther().#
|
||||
|
||||
|
||||
#Global stem object
|
||||
stem = brainstem.stem.USBHub3p()
|
||||
#If your module is different, replace it with the appropriate module
|
||||
#Such as a USBCSwitch as shown below.
|
||||
#stem = brainstem.stem.USBCSwitch()
|
||||
|
||||
|
||||
def printProgramInfo():
|
||||
print("The aUSBHub3p server has been started.");
|
||||
print("You can now access this device from another process.");
|
||||
print("Build and run the \"client\" example to see it in action.");
|
||||
print("Additionally you can still issue commands to this process.");
|
||||
|
||||
|
||||
def printFailedConnection():
|
||||
print("Failed to discover Module");
|
||||
print(" - Confirm device is connected to your machine");
|
||||
print(" - Confirm object type. This examples default is \"aUSBHub3p\"");
|
||||
|
||||
|
||||
def print_aEtherConfig():
|
||||
print(stem.getConfig().value)
|
||||
|
||||
|
||||
def configure_aEther():
|
||||
#NOTE: Network configuration MUST be done before connecting.
|
||||
res = stem.getConfig()
|
||||
config = res.value
|
||||
|
||||
#Controls the exposure of the device. By default,
|
||||
#the device is only exposed on the localhost.
|
||||
#True = localhost(default); False = Public;
|
||||
#config.localOnly = false; //uncomment to test non-default values
|
||||
|
||||
#Controls how strictly we honor the linkType (USB, NETWORK).
|
||||
#Fallback allows for a smoother user experience when getting
|
||||
#familiar with the device; however, it might be helpful to disable
|
||||
#this so that you can control who is the server and who is the client.
|
||||
#For instance if stem.discoverAndConnect(USB) fails it will automatically
|
||||
#try stem.discoverAndConnect(Network) and vise-versa.
|
||||
#True = fallback (default); False = NO fallback
|
||||
#config.fallback = false; //uncomment to test non-default values
|
||||
|
||||
#Controls if the Client-Server model is used. If you prefer to restrict
|
||||
#the device to a single process you can disable this capability.
|
||||
#By default the stem is enabled for multi-process use.
|
||||
#True = Client-Server (default); False = Direct connection (not multi-process)
|
||||
#config.enabled = false; //uncomment to test non-default values
|
||||
|
||||
#Allows the user to select what network interface the stem will be exposed to.
|
||||
#Default = LOCALHOST_IP_ADDRESS; (0 is also accepted for LOCALHOST_IP_ADDRESS);
|
||||
#Available interfaces can be found with brainstem.discover.getIPv4Interfaces()
|
||||
#NOTE: If config.localOnly == true; This value is ignored.
|
||||
# If config.localOnly == false; The stem will automatically pick
|
||||
# the highest priority network interface and will ignore 0 and
|
||||
# LOCALHOST_IP_ADDRESS values. However, you may override this value.
|
||||
#config.networkInterface = _BS_C.LOCALHOST_IP_ADDRESS;
|
||||
|
||||
e = stem.setConfig(config)
|
||||
if e is not Result.NO_ERROR:
|
||||
print("setConfig Error: ", e)
|
||||
|
||||
|
||||
def main(argv):
|
||||
configure_aEther()
|
||||
e = stem.discoverAndConnect(brainstem.link.Spec.USB)
|
||||
if e == Result.NO_ERROR:
|
||||
printProgramInfo()
|
||||
print("")
|
||||
print_aEtherConfig()
|
||||
|
||||
#Loop for a long time so that we can see the interactions
|
||||
#of the client and server.
|
||||
NUM_LOOPS = 10000
|
||||
for x in range(0, NUM_LOOPS):
|
||||
if x % 20 == 0:
|
||||
print("Loop: ", x)
|
||||
|
||||
result = stem.system.getInputVoltage()
|
||||
print("System Input Voltage: %0.3f VDC - error: %d" %
|
||||
(result.value/1000000, result.error))
|
||||
|
||||
stem.disconnect()
|
||||
else:
|
||||
printFailedConnection()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
brainstem_example.py
|
||||
=========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This simple example connects to the first USBStem found, displays its Serial Number, and then blinks its LED for 5 seconds. The script contains commented out lines of code which allow you to configure this script to connect to a USBHub2x4 or MTMUSBStem, and which allow you to connect to a Module with a specific Serial Number instead of the first one found.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# Copyright (c) 2018 Acroname Inc. - All Rights Reserved
|
||||
#
|
||||
# This file is part of the BrainStem development package.
|
||||
# See file LICENSE or go to https://acroname.com/software/brainstem-development-kit for full license details.
|
||||
import brainstem
|
||||
import time
|
||||
|
||||
#for easy access to error constants
|
||||
from brainstem.result import Result
|
||||
|
||||
# Create USBStem object
|
||||
print ('\nCreating USBHub3p and connecting to first module found')
|
||||
stem = brainstem.stem.USBHub3p()
|
||||
#Other Options/Examples:
|
||||
#stem = brainstem.stem.USBHub2x4()
|
||||
#stem = brainstem.stem.MTMUSBStem()
|
||||
|
||||
#Locate and connect to the first object you find on USB
|
||||
#Easy way: 1=USB, 2=TCPIP
|
||||
result = stem.discoverAndConnect(brainstem.link.Spec.USB)
|
||||
#Locate and connect to a specific module (replace "0x66F4859B" with your Serial Number (hex))
|
||||
#result = stem.discoverAndConnect(brainstem.link.Spec.USB, 0x66F4859B)
|
||||
|
||||
#Check error
|
||||
if result == (Result.NO_ERROR):
|
||||
result = stem.system.getSerialNumber()
|
||||
print ("Connected to USBHub3p with serial number: 0x%08X" % result.value)
|
||||
|
||||
#Flash the LED
|
||||
print ('Flashing the user LED\n')
|
||||
for i in range(1, 11):
|
||||
stem.system.setLED(i % 2)
|
||||
time.sleep(0.5)
|
||||
|
||||
else:
|
||||
print ("Could not connect to device\n")
|
||||
|
||||
#Disconnect from device.
|
||||
stem.disconnect()
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
brainstem_port_mapping.py
|
||||
========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This example demonstrates how to map downstream devices to specific ports of Acroname hub products.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Copyright (c) 2023 Acroname Inc. - All Rights Reserved
|
||||
#
|
||||
# This file is part of the BrainStem development package.
|
||||
# See file LICENSE or go to https://acroname.com/software/brainstem-development-kit for full license details.
|
||||
import brainstem
|
||||
from brainstem.result import Result
|
||||
|
||||
devices = brainstem.discover.getDownstreamDevices()
|
||||
|
||||
if devices.error == Result.NO_ERROR and len(devices.value):
|
||||
print("The following downstream devices were found:")
|
||||
print(devices.value)
|
||||
else:
|
||||
print("No downstream devices were found")
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
brainstem_server_example.py
|
||||
========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This example is intended to highlight the multi-process and
|
||||
network capabilities of BrainStem modules. This application
|
||||
is intended to be used in conjunction with a "client" example (Any API)
|
||||
however, it will work with any application or even HubTool
|
||||
if configured properly.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
#
|
||||
# This file is part of the BrainStem development package.
|
||||
# See file LICENSE or go to https://acroname.com/software/brainstem-development-kit for full license details.
|
||||
import brainstem
|
||||
from brainstem.result import Result
|
||||
from brainstem.link import aEtherConfig
|
||||
from brainstem import _BS_C #BrainStem lib handle, for aProtocolDefs.h values only!
|
||||
|
||||
import sys
|
||||
|
||||
#This example is intended to highlight the multi-process and
|
||||
#network capabilities of BrainStem modules. This application
|
||||
#is intended to be used in conjunction with a "client" example (Any API)
|
||||
#however, it will work with any application or even HubTool
|
||||
#if configured properly.
|
||||
|
||||
#Note 1:
|
||||
# Although this is labeled as the "Server" application this
|
||||
# is a bit misleading. The actual server is created by the
|
||||
# first process to connect to the device.
|
||||
# This means you could run the "Client" or even HubTool first in
|
||||
# which it would create/own the server and this application would be
|
||||
# a client. This is intended to smooth over the user experience
|
||||
# but is important to remember when closing applications. If
|
||||
# The "Server" application is closed it will result in the "Clients"
|
||||
# losing access to the device.
|
||||
|
||||
#Note 2:
|
||||
# This application was created with the aUSBHub3p object. If
|
||||
# your devices differs (say a USBCSwitch) you will need to change
|
||||
# all instances of aUSBHub3p to aUSBCSwitch in order to connect to
|
||||
# the device. This is a result of discoveryAndConnect as it will
|
||||
# only connect to a device that matches the object type. It is
|
||||
# possible to use the generic "Module" object; however, this was avoided
|
||||
# in order to present a simplified example. For more connection types
|
||||
# see the "Discovery-and-Connection" example
|
||||
|
||||
#Note 3:
|
||||
# If you intended to connect to a device that is not connected
|
||||
# to your local machine or on your local intranet (local network)
|
||||
# you will need to define a linkSpec with the intended ip and port
|
||||
# number of the device and then use "connectFromSpec".
|
||||
# Discovery works through broadcast and multicast packets;
|
||||
# neither of which work for the internet (global network).
|
||||
# For more connection types see the "Discovery-and-Connection"
|
||||
|
||||
#Note 4:
|
||||
# Additional network details are described in _configure_aEther().#
|
||||
|
||||
|
||||
#Global stem object
|
||||
stem = brainstem.stem.USBHub3p()
|
||||
#If your module is different, replace it with the appropriate module
|
||||
#Such as a USBCSwitch as shown below.
|
||||
#stem = brainstem.stem.USBCSwitch()
|
||||
|
||||
|
||||
def printCLIOutput():
|
||||
print("Commands: ");
|
||||
print("\t exit - Exits this application");
|
||||
print("\t voltage - Gets the system input voltage");
|
||||
print("\t led - Gets the current led value");
|
||||
print("\t led <value> - Sets the led to the defined value (0/1)");
|
||||
|
||||
|
||||
def printProgramInfo():
|
||||
print("The aUSBHub3p server has been started.");
|
||||
print("You can now access this device from another process.");
|
||||
print("Build and run the \"client\" example to see it in action.");
|
||||
print("Additionally you can still issue commands to this process.");
|
||||
|
||||
|
||||
def printFailedConnection():
|
||||
print("Failed to discover Module");
|
||||
print(" - Confirm device is connected to your machine");
|
||||
print(" - Confirm object type. This examples default is \"aUSBHub3p\"");
|
||||
|
||||
|
||||
def print_aEtherConfig():
|
||||
print(stem.getConfig().value)
|
||||
|
||||
|
||||
def handleCLI():
|
||||
while True:
|
||||
s = input("cmd: ")
|
||||
|
||||
args = s.split()
|
||||
|
||||
if len(args) == 1:
|
||||
if args[0] == "exit":
|
||||
break;
|
||||
elif args[0] == "led":
|
||||
result = stem.system.getLED()
|
||||
print("Get LED value %d - error: %d" % (result.value, result.error))
|
||||
elif args[0] == "voltage":
|
||||
result = stem.system.getInputVoltage()
|
||||
print("System Input Voltage: %0.3f - error: %d" % (result.value/1000000, result.error))
|
||||
|
||||
elif len(args) == 2:
|
||||
if args[0] == "led":
|
||||
e = stem.system.setLED(int(args[1]))
|
||||
print("Set LED value: %d - error: %d" % (int(args[1]), e))
|
||||
|
||||
else:
|
||||
printCLIOutput()
|
||||
|
||||
|
||||
def configure_aEther():
|
||||
#NOTE: Network configuration MUST be done before connecting.
|
||||
res = stem.getConfig()
|
||||
config = res.value
|
||||
|
||||
#Controls the exposure of the device. By default,
|
||||
#the device is only exposed on the localhost.
|
||||
#True = localhost(default); False = Public;
|
||||
#config.localOnly = false; //uncomment to test non-default values
|
||||
|
||||
#Controls how strictly we honor the linkType (USB, NETWORK).
|
||||
#Fallback allows for a smoother user experience when getting
|
||||
#familiar with the device; however, it might be helpful to disable
|
||||
#this so that you can control who is the server and who is the client.
|
||||
#For instance if stem.discoverAndConnect(USB) fails it will automatically
|
||||
#try stem.discoverAndConnect(Network) and vise-versa.
|
||||
#True = fallback (default); False = NO fallback
|
||||
#config.fallback = false; //uncomment to test non-default values
|
||||
|
||||
#Controls if the Client-Server model is used. If you prefer to restrict
|
||||
#the device to a single process you can disable this capability.
|
||||
#By default the stem is enabled for multi-process use.
|
||||
#True = Client-Server (default); False = Direct connection (not multi-process)
|
||||
#config.enabled = false; //uncomment to test non-default values
|
||||
|
||||
#Allows the user to select what network interface the stem will be exposed to.
|
||||
#Default = LOCALHOST_IP_ADDRESS; (0 is also accepted for LOCALHOST_IP_ADDRESS);
|
||||
#Available interfaces can be found with brainstem.discover.getIPv4Interfaces()
|
||||
#NOTE: If config.localOnly == true; This value is ignored.
|
||||
# If config.localOnly == false; The stem will automatically pick
|
||||
# the highest priority network interface and will ignore 0 and
|
||||
# LOCALHOST_IP_ADDRESS values. However, you may override this value.
|
||||
#config.networkInterface = _BS_C.LOCALHOST_IP_ADDRESS;
|
||||
|
||||
e = stem.setConfig(config)
|
||||
if e is not Result.NO_ERROR:
|
||||
print("setConfig Error: ", e)
|
||||
|
||||
|
||||
def main(argv):
|
||||
configure_aEther()
|
||||
e = stem.discoverAndConnect(brainstem.link.Spec.USB)
|
||||
if e == Result.NO_ERROR:
|
||||
printProgramInfo()
|
||||
print("")
|
||||
print_aEtherConfig()
|
||||
print("")
|
||||
printCLIOutput()
|
||||
|
||||
handleCLI() #This function will block until "exit" is issued.
|
||||
|
||||
stem.disconnect()
|
||||
else:
|
||||
printFailedConnection()
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
import argparse
|
||||
import sys
|
||||
|
||||
|
||||
|
||||
class CustomArgumentParser(argparse.ArgumentParser):
|
||||
|
||||
CLI_ACTION_DISCOVER = "discover"
|
||||
CLI_ACTION_SEND = "send"
|
||||
|
||||
def __init__(self, argv=None, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.argv = argv if argv is not None else sys.argv[1:]
|
||||
|
||||
subparsers = self.add_subparsers(dest='cli_action', help="Available actions")
|
||||
subparsers._parser_class = self.create_subparser # Use a factory method for subparsers
|
||||
|
||||
parser_discover = subparsers.add_parser(self.CLI_ACTION_DISCOVER, help="Discover Apple VDM's based on the given arguments")
|
||||
parser_discover.add_argument("-d", "--device", help="Acroname Device Serial Number", type=self.auto_int, metavar='', default=0)
|
||||
parser_discover.add_argument("-p", "--port", help="Port to execute VDM on.", required=True, type=int, metavar='')
|
||||
parser_discover.add_argument("-a", "--action", help="The Action to be included in the VDM", type=self.auto_int, metavar='', default=None)
|
||||
parser_discover.add_argument("-s", "--sop", help="SOP Selection: SOP`Debug(3), SOP``Debug(4)", required=False, type=int, metavar='', choices={3,4}, default=4) #SOP'Debug
|
||||
|
||||
parser_send = subparsers.add_parser(self.CLI_ACTION_SEND, help="Sends the resulting Apple DFU VDM")
|
||||
parser_send.add_argument("-d", "--device", help="Acroname Device Serial Number", type=self.auto_int, metavar='', default=0)
|
||||
parser_send.add_argument("-p", "--port", help="Port to execute VDM on.", required=True, type=int, metavar='')
|
||||
parser_send.add_argument("-a", "--action", help="The Action to be included in the VDM", required=True, type=self.auto_int, metavar='')
|
||||
parser_send.add_argument("-r", "--action_argument", help="The Action to be included in the VDM", required=True, type=self.auto_int, metavar='')
|
||||
parser_send.add_argument("-s", "--sop", help="SOP Selection: SOP`Debug(3), SOP``Debug(4)", required=False, type=int, metavar='', choices={3,4}, default=4) #SOP'Debug
|
||||
parser_send.add_argument("-x", "--send", help="Actually send the vdm", action='store_true')
|
||||
|
||||
self.parsed_args = self.parse_args(self.argv[1:])
|
||||
|
||||
#Ensure the user provided a subparser argument (discovered, send)
|
||||
self.cli_action = self.parsed_args.cli_action
|
||||
if self.cli_action is None:
|
||||
self.print_help()
|
||||
sys.exit(255)
|
||||
|
||||
self.action = self.parsed_args.action
|
||||
self.port = self.parsed_args.port
|
||||
self.sn = self.parsed_args.device
|
||||
self.sop = self.parsed_args.sop
|
||||
|
||||
if self.CLI_ACTION_SEND == self.cli_action:
|
||||
self.action_argument= self.parsed_args.action_argument
|
||||
self.send = self.parsed_args.send
|
||||
|
||||
def create_subparser(self, **kwargs):
|
||||
return argparse.ArgumentParser(**kwargs)
|
||||
|
||||
def print_example_usage(self):
|
||||
|
||||
EXAMPLE_USAGE = [ \
|
||||
(""), \
|
||||
("Example Usage:"), \
|
||||
(" \"%s discover -p 5\" - Discovers all Actions and Action Arguments" % (self.argv[0])), \
|
||||
(" \"%s discover -p 5 -d 0xBEEFFEED\" - Discovers all Actions and Action Arguments for the specified device" % (self.argv[0])), \
|
||||
(" \"%s discover -p 5 -a 0x106\" - Discovers Action Arguments for the provided action" % (self.argv[0])), \
|
||||
(""), \
|
||||
(" Note: Action (-a) and Action Arguments (-r) are not verified before sending."), \
|
||||
(" \"%s send -p 5 -a 0x0106 -r 0x8001\" - Constructs an Apple DFU VDM, but does not send it." % (self.argv[0])), \
|
||||
(" \"%s send -p 5 -a 0x0106 -r 0x8001 -x\" - Constructs an Apple DFU VDM and Sends it" % (self.argv[0])), \
|
||||
]
|
||||
|
||||
for usage in EXAMPLE_USAGE:
|
||||
print(usage)
|
||||
|
||||
def print_help(self):
|
||||
super().print_help()
|
||||
self.print_example_usage()
|
||||
|
||||
@staticmethod
|
||||
def auto_int(x):
|
||||
# Automatically detect the base (hex if prefixed with '0x', decimal otherwise)
|
||||
return int(x, 0)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,445 @@
|
|||
#!/usr/bin/env python3
|
||||
#System
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
|
||||
#BrainStem
|
||||
import brainstem
|
||||
from brainstem import _BS_C #Gives access to aProtocolDef.h constants.
|
||||
from brainstem.pd_channel_logger import PDChannelLogger
|
||||
from brainstem.result import Result
|
||||
|
||||
#Local files
|
||||
from argument_parser import *
|
||||
|
||||
#Power Delivery Utilities
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_dir = os.path.abspath(os.path.join(script_dir, "../utilities/PowerDelivery"))
|
||||
sys.path.insert(0, parent_dir)
|
||||
from bs_pd_packet_filtering import *
|
||||
|
||||
#Generic Utilities
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_dir = os.path.abspath(os.path.join(script_dir, "../utilities"))
|
||||
sys.path.insert(0, parent_dir)
|
||||
from brainstem_helpers import *
|
||||
|
||||
BAIL_COUNTER = 40
|
||||
|
||||
#Note: Apple DFU related information was acquired from here:
|
||||
#https://github.com/AsahiLinux/docs/wiki/HW:USB-PD
|
||||
#Users should keep in mind that this information was NOT publicly distributed
|
||||
#by Apple and no guarantee of accuracy can be made.
|
||||
#Users should use this code at their own risk and Acroname accepts
|
||||
#no responsibility for any damage caused by this code.
|
||||
CMD_GET_ACTION = 0x10
|
||||
CMD_GET_ACTION_INFO = 0x11
|
||||
CMD_PREFORM_ACTION = 0x12
|
||||
|
||||
#Apple Vendor ID
|
||||
APPLE_VID = 0x05AC
|
||||
|
||||
#Apple DFU command number to string.
|
||||
COMMAND_LOOKUP = {
|
||||
0x0103: "PD Reset",
|
||||
0x0105: "Reboot",
|
||||
0x0106: "DFU / Hold Mode",
|
||||
0x0306: "Debug UART",
|
||||
0x0606: "DFU USB",
|
||||
0x4606: "Debug USB",
|
||||
0x0803: "I2C Bus (1)",
|
||||
0x0809: "I2C Bus (2)",
|
||||
}
|
||||
|
||||
|
||||
def is_pd_established(stem, port_index):
|
||||
pd = brainstem.entity.PowerDelivery(stem, port_index)
|
||||
|
||||
#Local RDO - This will be set if the port is SINKING power.
|
||||
rdo_local = pd.getRequestDataObject(_BS_C.powerdeliveryPartnerLocal)
|
||||
if not basic_error_handling(stem, rdo_local) and rdo_local.value != 0:
|
||||
return True
|
||||
|
||||
#Remote RDO - This will be set if the port is SOURCING power.
|
||||
rdo_remote = pd.getRequestDataObject(_BS_C.powerdeliveryPartnerRemote)
|
||||
if not basic_error_handling(stem, rdo_remote) and rdo_remote.value != 0:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
#Turn the indicated port off and confirm that the voltage bleeds off.
|
||||
def turn_port_off_and_confirm_voltage(stem, port_index, max_voltage=200000): #0.2VDC
|
||||
port = brainstem.entity.Port(stem, port_index)
|
||||
error = port.setEnabled(False)
|
||||
s = "Exiting: Failed to disable port: %d - Error: %d" % (port_index, error)
|
||||
basic_error_handling(stem, error, s, exit=True, exit_code=9)
|
||||
|
||||
bail_count = 0
|
||||
while True:
|
||||
result = port.getVbusVoltage()
|
||||
if not basic_error_handling(stem, result) and result.value < max_voltage:
|
||||
break;
|
||||
|
||||
bail_count += 1
|
||||
if bail_count > BAIL_COUNTER:
|
||||
print("Exiting Failed to turn off port: %d - Result: %s - Bail Count: %d" % (port_index, result, bail_count))
|
||||
sys.exit(5)
|
||||
|
||||
time.sleep(.2)
|
||||
|
||||
|
||||
#Turn the indicated port off and confirm power delivery negotiations are completed (defined RDO)
|
||||
def turn_port_on_and_confirm_power_delivery(stem, port_index):
|
||||
port = brainstem.entity.Port(stem, port_index)
|
||||
error = port.setEnabled(True)
|
||||
s = "Exiting: Failed to enable port: %d - Error: %d" % (port_index, error)
|
||||
basic_error_handling(stem, error, s, exit=True, exit_code=9)
|
||||
|
||||
bail_count = 0
|
||||
while not is_pd_established(stem, port_index):
|
||||
bail_count += 1
|
||||
if bail_count > BAIL_COUNTER:
|
||||
print("Exiting Failed to find a pd connection on port: %d - Bail Count: %d" % (port_index, bail_count))
|
||||
sys.exit(5)
|
||||
|
||||
time.sleep(.2)
|
||||
|
||||
|
||||
#Convenience function for combining the off confirm with the on confirm functions
|
||||
def toggle_and_wait_for_device(stem, port_index):
|
||||
turn_port_off_and_confirm_voltage(stem, port_index)
|
||||
turn_port_on_and_confirm_power_delivery(stem, port_index)
|
||||
|
||||
|
||||
import struct
|
||||
#Helper function for constructing basic apple dfu related vdm's
|
||||
def construct_apple_dfu_vdm(sop, command, action=None, action_arg=None):
|
||||
if CMD_GET_ACTION == command:
|
||||
return struct.pack('<LBBHL', sop, command, 0x80, APPLE_VID, 0)
|
||||
|
||||
elif CMD_GET_ACTION_INFO == command:
|
||||
if action == None:
|
||||
raise RuntimeError("Missing action parameter for this command type")
|
||||
return struct.pack('<LBBHL', sop, command, 0x80, APPLE_VID, action)
|
||||
|
||||
elif CMD_PREFORM_ACTION == command:
|
||||
if action == None or action_arg == None:
|
||||
raise RuntimeError("Missing action or action_arg parameter for this command type.")
|
||||
return struct.pack('<LBBHLHH', sop, command, 0x80, APPLE_VID, action, 0x00, action_arg)
|
||||
|
||||
else:
|
||||
raise RuntimeError("Unsupported vdm command: %d" % (command))
|
||||
|
||||
|
||||
#Convenience function for sending VDM's
|
||||
def send_vdm(stem, port_index, buffer):
|
||||
pd = brainstem.entity.PowerDelivery(stem, port_index)
|
||||
error = pd.set_UEIBytes(_BS_C.powerdeliveryVDM, buffer)
|
||||
basic_error_handling(stem, error)
|
||||
|
||||
|
||||
#Simple send/receive with retry for a VDM sending.
|
||||
def handle_send_receive_apple_dfu_vdm(stem, port_index, sop, vdm, logger, max_time_seconds=5):
|
||||
start_time = time.time()
|
||||
while True:
|
||||
current_time = time.time()
|
||||
elapsed_time = current_time - start_time
|
||||
|
||||
#Some DFU supporting devices will only respond to one command per connection.
|
||||
#This function will toggle the port off in the hopes we can request again.
|
||||
toggle_and_wait_for_device(stem, port_index)
|
||||
|
||||
#Some devices are chatty when they come online (especially Apple devices).
|
||||
#Let them finish before we start asking questions.
|
||||
wait_for_silence(logger, silence_time_seconds=1)
|
||||
|
||||
send_vdm(stem, port_index, vdm)
|
||||
result_packet = pd_packet_filter(logger, sop, filter_tx_apple_dfu_vdm, filter_rx_apple_dfu_vdm)
|
||||
|
||||
if result_packet:
|
||||
return result_packet
|
||||
|
||||
if elapsed_time >= max_time_seconds:
|
||||
print("Exiting: Failed to send/receive apple dfu vdm's")
|
||||
sys.exit(5)
|
||||
|
||||
time.sleep(.1)
|
||||
|
||||
#Toggle the port one more time to ensure it is in a working state.
|
||||
toggle_and_wait_for_device(stem, port_index)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
#Discovers the actions a device supports
|
||||
def discover_actions(stem, port_index, sop, logger):
|
||||
supported_actions = []
|
||||
req = construct_apple_dfu_vdm(sop, CMD_GET_ACTION)
|
||||
result_packet = handle_send_receive_apple_dfu_vdm(stem, port_index, sop, req, logger)
|
||||
if result_packet and result_packet.error == Result.NO_ERROR:
|
||||
supported_actions = get_two_byte_list_from_buffer(result_packet.value.payload, start_offset=6)
|
||||
print("Discovered Actions: ", format_list_as_hex_string_list(supported_actions, width=4))
|
||||
for action in supported_actions:
|
||||
print("Action: 0x%04X - %s" % (action, COMMAND_LOOKUP.get(action, "Unknown")))
|
||||
print("----------------------------------------------------------")
|
||||
|
||||
return supported_actions
|
||||
|
||||
|
||||
#Discovers the actions arguments that a device action supports.
|
||||
def discover_action_arguments(stem, port_index, sop, action, logger):
|
||||
supported_args = []
|
||||
print("Discovering Arguments for Action: 0x%04X - %s" % (action, COMMAND_LOOKUP.get(action, "Unknown")))
|
||||
req = construct_apple_dfu_vdm(sop, CMD_GET_ACTION_INFO, action)
|
||||
result_packet = handle_send_receive_apple_dfu_vdm(stem, port_index, sop, req, logger)
|
||||
if result_packet and result_packet.error == Result.NO_ERROR:
|
||||
supported_args = get_two_byte_list_from_buffer(result_packet.value.payload, start_offset=6)
|
||||
print("Discovered Arguments: ", format_list_as_hex_string_list(supported_args, width=4))
|
||||
print("----------------------------------------------------------")
|
||||
|
||||
return supported_args
|
||||
|
||||
|
||||
#Checks to see if the device can execute the required commands for the defined port.
|
||||
#This also includes some functionality from software features.
|
||||
def check_device_capability(stem, port_index):
|
||||
#Note: We don't check cmdSYSTEM because all Acroname devices support this Entity.
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#cmdPORT Checks
|
||||
#---------------------------------------------------------------------------------
|
||||
#Check how many Port Entities this devices has.
|
||||
result = stem.classQuantity(_BS_C.cmdPORT)
|
||||
s = "Exiting: Could not acquire class quantity for cmdPORT - %s" % (result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that the supplied port does not exceed the amount of Port entities this devices has.
|
||||
if port_index > result.value:
|
||||
print("The provided port is out of range of supported ports for this device (cmdPORT). - %s" % (result))
|
||||
sys.exit(2)
|
||||
|
||||
#Check that we can enable/disable a port
|
||||
result = stem.hasUEI(_BS_C.cmdPORT, _BS_C.portPortEnabled, port_index, (_BS_C.ueiOPTION_SET))
|
||||
s = "Exiting: There is an error with this devices ability to enable port: %d - %s" % (port_index, result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that we can get vbus voltage
|
||||
result = stem.hasUEI(_BS_C.cmdPORT, _BS_C.portVbusVoltage, port_index, (_BS_C.ueiOPTION_GET))
|
||||
s = "Exiting: There is an error with this devices ability to get vbus voltage on port: %d - %s" % (port_index, result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#cmdUSBSYSTEM Checks
|
||||
#---------------------------------------------------------------------------------
|
||||
#Check how many USBSystem Entities this devices has.
|
||||
result = stem.classQuantity(_BS_C.cmdUSBSYSTEM)
|
||||
s = "Exiting: Could not acquire class quantity for cmdUSBSYSTEM - %s" % (result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
|
||||
#Check that the supplied port does not exceed the amount of PowerDelivery entities this devices has.
|
||||
if result.value < 1:
|
||||
print("Exiting The USBSystem index is out of range for this device (cmdUSBSYSTEM). - %s" % (result))
|
||||
sys.exit(2)
|
||||
|
||||
#Check that we can get the upstream port
|
||||
result = stem.hasUEI(_BS_C.cmdUSBSYSTEM, _BS_C.usbsystemUpstreamPort, 0, (_BS_C.ueiOPTION_GET))
|
||||
s = "Exiting: There is an error with this devices ability to enable port: %d - %s" % (port_index, result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
#cmdPOWERDELIVERY Checks
|
||||
#---------------------------------------------------------------------------------
|
||||
#Check how many PowerDelivery Entities this devices has.
|
||||
result = stem.classQuantity(_BS_C.cmdPOWERDELIVERY)
|
||||
s = "Exiting: Could not acquire class quantity for cmdPOWERDELIVERY - %s" % (result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that the supplied port does not exceed the amount of PowerDelivery entities this devices has.
|
||||
if port_index > result.value:
|
||||
print("Exiting The provided port is out of range of supported ports for this device (cmdPOWERDELIVERY). - %s" % (result))
|
||||
sys.exit(2)
|
||||
|
||||
#Check that we can send VDM's
|
||||
result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryVDM, port_index, (_BS_C.ueiOPTION_SET))
|
||||
#TODO: indicate in the error message that this might require a software features update.
|
||||
s = "Exiting: There is an error with this devices ability to send VDM messages on port: %d - %s" % (port_index, result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that we can get RDO's
|
||||
result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryRequestDataObject, port_index, (_BS_C.ueiOPTION_GET))
|
||||
|
||||
s = "Exiting: There is an error with this devices ability to get RDOs on port: %d - %s" % (port_index, result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that we can send PD Requests
|
||||
result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryRequestCommand, port_index, (_BS_C.ueiOPTION_SET))
|
||||
s = "Exiting: There is an error with this devices ability to send PD requests on port: %d - %s" % (port_index, result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that we can send PD VDMs
|
||||
result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryVDM, port_index, (_BS_C.ueiOPTION_SET))
|
||||
s = "Exiting: There is an error with this devices ability to send PD VDM messages on port: %d - %s" % (port_index, result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that we can enable PD Logging
|
||||
result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryLogEnable, port_index, (_BS_C.ueiOPTION_SET))
|
||||
s = "Exiting: There is an error with this devices ability to send Power Delivery Logging Enable requests on port: %d - %s" % (port_index, result)
|
||||
s += "\nDoes this devices have the PD Logging software feature?"
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#TODO: This check doesn't exist in firmware yet.
|
||||
# #Check that we can register for PD Logging events
|
||||
# result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryLogEvent, port_index, (_BS_C.ueiOPTION_SET))
|
||||
# s = "Exiting: There is an error with this devices ability to register for Power Delivery Events on port: %d - %s" % (port_index, result)
|
||||
# s += "\nDoes this devices have the PD Logging software feature?"
|
||||
# basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#Ensure the software library is >=2.11.x
|
||||
def check_software_version_capability():
|
||||
if not brainstem.version.isAtLeast(2, 11, 2).value:
|
||||
print("Exiting: This application requires BrainStem >= 2.11.2")
|
||||
sys.exit(14)
|
||||
|
||||
|
||||
#Context manager that handles cleanup of the stem and logger.
|
||||
#It also attempts to return the power mode.
|
||||
class CLI_Manager:
|
||||
def __init__(self):
|
||||
self.stem = None #brainstem.module.Module objects
|
||||
self.logger = None #PDChannelLogger objects
|
||||
self.power_role = None #values acquired by getPowerRole()
|
||||
self.port = None #port number associated with the value above.
|
||||
|
||||
def __enter__(self): #You must have this function for the context manager to work correctly
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if self.logger:
|
||||
self.logger.setEnabled(False)
|
||||
self.logger = None
|
||||
|
||||
if self.stem:
|
||||
#Attempts to restore the devices original power mode if it was changed.
|
||||
pd = brainstem.entity.PowerDelivery(self.stem, self.port) #We only support one stem
|
||||
result = pd.setPowerRole(self.power_role)
|
||||
basic_error_handling(self.stem, result, "Error Applying user's original power role.")
|
||||
|
||||
self.stem.disconnect()
|
||||
self.stem = None
|
||||
|
||||
return False # Ensure exception propagates
|
||||
|
||||
|
||||
#Acquire the current power role of the device so that it can be restored and
|
||||
#set the needed power role based on the sop.
|
||||
def handle_power_role(stem, port, sop):
|
||||
pd = brainstem.entity.PowerDelivery(stem, port)
|
||||
pr_result = pd.getPowerRole()
|
||||
basic_error_handling(stem, pr_result, "pd.getPowerRole()", exit=True, exit_code=10)
|
||||
|
||||
set_power_role = 0
|
||||
if 4 == sop:
|
||||
set_power_role = _BS_C.powerdeliveryPowerRoleSource
|
||||
elif 3 == sop:
|
||||
set_power_role = _BS_C.powerdeliveryPowerRoleSink
|
||||
else: #Arg parser should be handling this.
|
||||
print("Unsupported SOP")
|
||||
sys.exit(76)
|
||||
error = pd.setPowerRole(set_power_role)
|
||||
basic_error_handling(stem, error, ("pd.setPowerRole(%d)" % (set_power_role)), exit=True, exit_code=11)
|
||||
|
||||
#Power should be on; however, if the power role changed then we should wait for PD to be established.
|
||||
turn_port_on_and_confirm_power_delivery(stem, port)
|
||||
|
||||
return pr_result.value #return the original value
|
||||
|
||||
|
||||
#Check that the requested port is not our upstream port. We don't want to cut our head off.
|
||||
def check_upstream_port(stem, port):
|
||||
usb_system = brainstem.entity.USBSystem(stem, 0)
|
||||
upstream_result = usb_system.getUpstream()
|
||||
if not basic_error_handling(stem, upstream_result, "usb_system.getUpstream()", exit=True, exit_code=77):
|
||||
if upstream_result.value == port:
|
||||
print("Unable to Discover DFU capabilities on the upstream port. Select a different port")
|
||||
sys.exit(78)
|
||||
|
||||
|
||||
def main(argv):
|
||||
try:
|
||||
print("Provided Arguments:")
|
||||
print(argv)
|
||||
arg_parser = CustomArgumentParser(argv)
|
||||
|
||||
with CLI_Manager() as cli:
|
||||
|
||||
cli.port = arg_parser.port
|
||||
|
||||
#Setup
|
||||
#/////////////////////////////////////////////////////////////////////
|
||||
#Only connect if we need to.
|
||||
if (arg_parser.CLI_ACTION_DISCOVER == arg_parser.cli_action) or \
|
||||
(arg_parser.CLI_ACTION_SEND == arg_parser.cli_action and arg_parser.send):
|
||||
#---------------------------------------------------------------------
|
||||
#Note: This code doesn't use the typical BrainStem object, but instead uses a Module object.
|
||||
#The Module class is the base class for all BrainStem Objects like the USBHub3c, USBHub3p, USBCSwitch etc.
|
||||
#This allows our code to be more generic; however, we don't really know what we are or what
|
||||
#we are capable of and that is why we do a handful of capability checks here.
|
||||
cli.stem = create_and_connect_stem(arg_parser.sn)
|
||||
check_device_capability(cli.stem, arg_parser.port)
|
||||
check_software_version_capability()
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
check_upstream_port(cli.stem, arg_parser.port)
|
||||
|
||||
cli.power_role = handle_power_role(cli.stem, cli.port, arg_parser.sop)
|
||||
|
||||
cli.logger = create_logger(cli.stem, cli.port) #Create Logger object for given port
|
||||
#/////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#Work
|
||||
#/////////////////////////////////////////////////////////////////////
|
||||
if arg_parser.CLI_ACTION_DISCOVER == arg_parser.cli_action:
|
||||
if arg_parser.action != None:
|
||||
discover_action_arguments(cli.stem, cli.port, arg_parser.sop, arg_parser.action, logger)
|
||||
else:
|
||||
supported_actions = discover_actions(cli.stem, cli.port, arg_parser.sop, cli.logger)
|
||||
for action in supported_actions:
|
||||
discover_action_arguments(cli.stem, cli.port, arg_parser.sop, action, cli.logger)
|
||||
|
||||
elif arg_parser.CLI_ACTION_SEND == arg_parser.cli_action:
|
||||
vdm = construct_apple_dfu_vdm(arg_parser.sop, CMD_PREFORM_ACTION, arg_parser.action, arg_parser.action_argument)
|
||||
print("Provided Action: 0x%04X" % (arg_parser.action))
|
||||
print("Provided Action Argument: 0x%04X" % (arg_parser.action_argument))
|
||||
print("Requested VDM as integer list: ", vdm)
|
||||
print("Requested VDM as hex string list: ", format_list_as_hex_string_list(vdm, width=2))
|
||||
if arg_parser.send:
|
||||
handle_send_receive_apple_dfu_vdm(cli.stem, cli.port, arg_parser.sop, vdm, cli.logger)
|
||||
else:
|
||||
print("Provide the '-x' argument to send this VDM")
|
||||
|
||||
else: #Arg parser should be handling this.
|
||||
print("Unsupported Action")
|
||||
sys.exit(79)
|
||||
#/////////////////////////////////////////////////////////////////////
|
||||
|
||||
except SystemExit as e:
|
||||
return e
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
discovery_and_connect.py
|
||||
========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This example demonstrates the various ways to discover and connect to BrainStem devices. This example can be easily configured by the user to work with the BrainStem devices they currently posess or have access to.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
#
|
||||
# main.py
|
||||
# BrainStem2Example
|
||||
#
|
||||
###################################################################
|
||||
# #
|
||||
# Copyright (c) 2019 Acroname Inc. - All Rights Reserved #
|
||||
# #
|
||||
# This file is part of the BrainStem release. See the license.txt #
|
||||
# file included with this package or go to #
|
||||
# https:#acroname.com/software/brainstem-development-kit #
|
||||
# for full license details. #
|
||||
###################################################################
|
||||
|
||||
|
||||
##########################################################################
|
||||
# This example shows the various ways to discover and connect to BrainStem
|
||||
# modules/devices.
|
||||
# NOTE: Not all functions will be successful. Many of the examples will
|
||||
# require slight modification in order to work with your device.
|
||||
# Please refer to the individual notes/comments in and around
|
||||
# each function.
|
||||
##########################################################################
|
||||
|
||||
import brainstem
|
||||
# for easy access to error constants
|
||||
from brainstem.result import Result
|
||||
|
||||
|
||||
# discoverAndConnect_Example:
|
||||
#############################################################################
|
||||
# This is the most common form of connection. The discovery and connection
|
||||
# process is enveloped into a single function.
|
||||
#
|
||||
# PITFALL: This function requires that the object type matches the device
|
||||
# you are attempting to connect too and will likely require modification
|
||||
# in order to work properly.
|
||||
###############################################################################
|
||||
def discoverAndConnect_Example():
|
||||
|
||||
# TODO
|
||||
# Uncomment the object that matches your device.
|
||||
|
||||
# stem = brainstem.stem.USBStem()
|
||||
# stem = brainstem.stem.EtherStem()
|
||||
# stem = brainstem.stem.MTMEtherStem()
|
||||
# stem = brainstem.stem.MTMIOSerial()
|
||||
# stem = brainstem.stem.MTMUSBStem()
|
||||
# stem = brainstem.stem.MTMPM1()
|
||||
# stem = brainstem.stem.MTMRelay()
|
||||
# stem = brainstem.stem.USBHub2x4()
|
||||
stem = brainstem.stem.USBHub3p()
|
||||
#stem = brainstem.stem.USBHub3c()
|
||||
# stem = brainstem.stem.USBCSwitch()
|
||||
# stem = brainstem.stem.MTMDAQ1()
|
||||
# stem = barinstem.stem.MTMDAQ2()
|
||||
|
||||
# When no serial number is provided discoverAndConnect will attempt to
|
||||
# connect to the first module it finds. If multiple BrainStem devices
|
||||
# are connected to your machine it is unknown which device will be
|
||||
# discovered first.
|
||||
# Under the hood this function uses findFirstModule()
|
||||
|
||||
print("\nStarting DiscoverAndConnect(USB) example.")
|
||||
|
||||
err = stem.discoverAndConnect(brainstem.link.Spec.USB)
|
||||
if err != Result.NO_ERROR:
|
||||
print("Unable to find BrainStem module. Error: %s.\n" % err)
|
||||
print("Are you using the correct module/object type?")
|
||||
else:
|
||||
print("Found and connected to a BrainStem module. \n")
|
||||
serial_number = stem.system.getSerialNumber()
|
||||
stem.disconnect()
|
||||
|
||||
# discoverAndConnect has an overload which accepts a Serial Number.
|
||||
# The example immediately above will attempt to fetch the serial number
|
||||
# and use it in this example. Feel free to drop in the
|
||||
# serial number of your device.
|
||||
# Under the hood this function uses a combination of findAllModules() and
|
||||
# connectFromSpec().
|
||||
|
||||
# TODO
|
||||
# Put the SN of your device here.
|
||||
user_serial_number = serial_number.value
|
||||
|
||||
print("Starting DiscoverAndConnect(USB, serial_number) example. ")
|
||||
err = stem.discoverAndConnect(brainstem.link.Spec.USB, user_serial_number)
|
||||
if err != Result.NO_ERROR:
|
||||
print("Unable to find BrainStem module. Error: %s.\n" % err)
|
||||
print("Are you using the correct module/object type?")
|
||||
else:
|
||||
print("Found and connected to a BrainStem module. \n")
|
||||
stem.disconnect()
|
||||
print("Finished with DiscoverAndConnect example.\n"
|
||||
"------------------------------------------- \n")
|
||||
# end of Discover and Connect example
|
||||
##########################################################################
|
||||
|
||||
# findAllModules_Example:
|
||||
##########################################################################
|
||||
# Highlights how to discover and integrate multiple BrainStem devices
|
||||
# without connecting to them.
|
||||
# This is especially helpful for device agnostic applications.'
|
||||
###########################################################################
|
||||
def findAllModules_Example():
|
||||
|
||||
print("Starting findAllModules(USB) example.\n")
|
||||
specList = brainstem.discover.findAllModules(brainstem.link.Spec.USB)
|
||||
if not specList:
|
||||
print("No devices discovered over USB.")
|
||||
else:
|
||||
for spec in specList:
|
||||
print("Model: ", spec.model)
|
||||
print("Module: ", spec.module)
|
||||
print("Serial Number: ", spec.serial_number)
|
||||
print("Transport: ", spec.transport)
|
||||
print("")
|
||||
|
||||
print("Starting findAllModules(TCPIP) example")
|
||||
specList = brainstem.discover.findAllModules(brainstem.link.Spec.TCPIP)
|
||||
if not specList:
|
||||
print("No devices discovered over TCPIP.\n")
|
||||
else:
|
||||
for spec in specList:
|
||||
print("Model: ", spec.model)
|
||||
print("Module: ", spec.module)
|
||||
print("Serial Number: ", spec.serial_number)
|
||||
print("Transport: ", spec.transport)
|
||||
print("")
|
||||
|
||||
print("End of findAllModules example. \n"
|
||||
"------------------------------------------- \n")
|
||||
##########################################################################
|
||||
|
||||
# findFirstModule_Example:
|
||||
##########################################################################
|
||||
# This example will return the linkSpec object of the first device it
|
||||
# finds. The linkSpec object can then be used to connect to a device via
|
||||
# the connectFromSpec function.
|
||||
##########################################################################
|
||||
def findFisrtModule_Example():
|
||||
|
||||
print("Starting findFirstModule(USB) example.")
|
||||
spec = brainstem.discover.findFirstModule(brainstem.link.Spec.USB)
|
||||
if not spec:
|
||||
print("No devices found over USB.\n")
|
||||
else:
|
||||
print("Discovered and connected to BrainStem device.\n")
|
||||
print("Model: ", spec.model)
|
||||
print("Module: ", spec.module)
|
||||
print("Serial Number: ", spec.serial_number)
|
||||
print("Transport: ", spec.transport)
|
||||
|
||||
print("\nStarting findFirstModule(TCPIP) example.")
|
||||
spec = brainstem.discover.findFirstModule(brainstem.link.Spec.TCPIP)
|
||||
if not spec:
|
||||
print("No devices found over TCPIP.")
|
||||
else:
|
||||
print("Discovered and connected to BrainStem device.")
|
||||
print("Model: ", spec.model)
|
||||
print("Module: ", spec.module)
|
||||
print("Serial Number: ", spec.serial_number)
|
||||
print("Transport: ", spec.transport)
|
||||
print("\nEnd of findFirstModule example. \n"
|
||||
"------------------------------------------- \n")
|
||||
##########################################################################
|
||||
|
||||
# findModule_Example:
|
||||
##########################################################################
|
||||
# This example will connect to any BrainStem device given its serial
|
||||
# number. It will not connect without a SN.
|
||||
##########################################################################
|
||||
def findModule_Example():
|
||||
|
||||
print("Starting findModule(USB, SN) example.\n")
|
||||
|
||||
# TODO:
|
||||
# Add the serial number of your device here.
|
||||
serial_number = 0xB971001E
|
||||
|
||||
spec = brainstem.discover.findModule(brainstem.link.Spec.USB, serial_number)
|
||||
if not spec:
|
||||
print("No devices found over USB.\n")
|
||||
else:
|
||||
print("Discovered and connected to BrainStem device.")
|
||||
print("Model: ", spec.model)
|
||||
print("Module: ", spec.module)
|
||||
print("Serial Number: ", spec.serial_number)
|
||||
print("Transport: ", spec.transport)
|
||||
|
||||
print("\nStarting findModule(TCPIP, SN) example.")
|
||||
spec = brainstem.discover.findModule(brainstem.link.Spec.TCPIP, serial_number)
|
||||
if not spec:
|
||||
print("No devices found over TCPIP.\n")
|
||||
else:
|
||||
print("Discovered and connected to BrainStem device.")
|
||||
print("Model: ", spec.model)
|
||||
print("Module: ", spec.module)
|
||||
print("Serial Number: ", spec.serial_number)
|
||||
print("Transport: ", spec.transport)
|
||||
|
||||
print("\nEnd of findModule example. \n"
|
||||
"------------------------------------------- \n")
|
||||
##########################################################################
|
||||
|
||||
# connectFromSpec_Example:
|
||||
##########################################################################
|
||||
# Many of the discovery functions will return a linkSpec object.
|
||||
# This function shows how to use that object to connect to a BrainStem
|
||||
# device.
|
||||
# The benefit of this connection method is that it does not care
|
||||
# about which BrainStem object you use.
|
||||
# i.e. you can connect to a USBHub3p from a USBStem object. However,
|
||||
# the USBStem object does not possess a USB Entity and therefor will not be
|
||||
# able to control the USBHub3p correctly. This is typically not
|
||||
# recommended.
|
||||
###########################################################################
|
||||
def connectFromSpec_Example():
|
||||
|
||||
print("Starting connectFromSpec(Spec) example.")
|
||||
|
||||
stem = brainstem.stem.USBHub3p()
|
||||
spec = brainstem.discover.findFirstModule(brainstem.link.Spec.USB)
|
||||
if not spec:
|
||||
print("No devices found.")
|
||||
else:
|
||||
err = stem.connectFromSpec(spec)
|
||||
if err != Result.NO_ERROR:
|
||||
print("Unable to connect to module. Error: ", err)
|
||||
else:
|
||||
print("Successfully connected to BrainStem module.")
|
||||
stem.disconnect()
|
||||
|
||||
print("\nEnd of connectFromSpec example. \n"
|
||||
"------------------------------------------- \n")
|
||||
##########################################################################
|
||||
|
||||
|
||||
|
||||
# connectThroughLinkModule_Example:
|
||||
##########################################################################
|
||||
# This function allows a device to share the connection of another device.
|
||||
# This feature is only available for Acroname's MTM and 40pin devices.
|
||||
#
|
||||
# In this example we have a MTMUSBStem and a MTMDAQ2 connected to a BrainStem
|
||||
# development board. The board is powered and ONLY the MTMUSBStem is connected
|
||||
# to the computer via USB cable. The MTMDAQ2 will connect to the PC through the
|
||||
# MTMUSBStem via the BrainStem Network (I2C) which is wired through the
|
||||
# development board.
|
||||
###########################################################################
|
||||
def connectThroughLinkModule_Example():
|
||||
|
||||
print("Starting connectThroughLinkModule example.")
|
||||
|
||||
# Create the devices required for this example
|
||||
mtmstem = brainstem.stem.MTMUSBStem()
|
||||
mtmdaq2 = brainstem.stem.MTMDAQ2()
|
||||
|
||||
err = mtmstem.discoverAndConnect(brainstem.link.Spec.USB)
|
||||
if err != Result.NO_ERROR:
|
||||
print("Unable to find BrainStem module. Error: %s.\n" % err)
|
||||
print("Are you using the correct module/object type?")
|
||||
else:
|
||||
print("Found and connected to a MTMUSBStem. \n")
|
||||
|
||||
# Each module has a "router" address. This address defines the I2C network.
|
||||
# By default this value is set to the devices module address. In order
|
||||
# for devices to communicate on the BrainStem Network all devices must have
|
||||
# the router address of the link stem. In this example the MTMUSBStem is the
|
||||
# the link stem. When the routeToMe function is called the device will broadcast
|
||||
# to all devices on the network. 0 = default configuration, 1 = Instructs all modules
|
||||
# to change their router address to that of the broadcaster.
|
||||
err = mtmstem.system.routeToMe(1)
|
||||
if err == Result.NO_ERROR:
|
||||
# Now that the MTMUSBStem connection is up and running we can
|
||||
# use its connection to connect to the MTMDAQ2.
|
||||
err = mtmdaq2.connectThroughLinkModule(mtmstem)
|
||||
if err != Result.NO_ERROR:
|
||||
print("Unable to connect to MTMDAQ2 through the MTMUSBStem: %s.\n" % err)
|
||||
else:
|
||||
print("Connected to MTMDAQ2 through the MTMUSBStem\n")
|
||||
# Once connected you can use the device normally.
|
||||
LED_result = mtmstem.system.getLED()
|
||||
if LED_result.error == Result.NO_ERROR:
|
||||
string_val = "Off" if LED_result.value == 0 else "On"
|
||||
print("MTMUSBStem's User LED: %s\n" % string_val)
|
||||
LED_result = mtmdaq2.system.getLED()
|
||||
if LED_result.error == Result.NO_ERROR:
|
||||
string_val = "Off" if LED_result.value == 0 else "On"
|
||||
print("MTMDAQ2's User LED: %s\n" % string_val)
|
||||
|
||||
# You should disconnect in the reverse order in which you connected.
|
||||
mtmdaq2.disconnect()
|
||||
|
||||
# Reset all network routers back to their default configurations.
|
||||
mtmstem.system.routeToMe(0)
|
||||
mtmstem.disconnect()
|
||||
print("\nEnd of connectThroughLinkModule example. \n"
|
||||
"------------------------------------------- \n")
|
||||
##########################################################################
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
discoverAndConnect_Example()
|
||||
findAllModules_Example()
|
||||
findFisrtModule_Example()
|
||||
findModule_Example()
|
||||
connectFromSpec_Example()
|
||||
connectThroughLinkModule_Example()
|
||||
print("FINISHED WITH ALL EXAMPLES!")
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
mtm_io_serial_uart.py
|
||||
========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This example is a basic demonstration of the MTMIOSerial's communication capabilities. In this example a line of communication is open between the user's computer and the MTMIOSerial. This line of communication is a loopback such that the MTMIOSerial receives bytes from the computer and then immediately sends them back to the computer. At the end of this example a read out of the number of bytes sent from the computer and a read out of the data read in by the computer is presented to the user.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
# Copyright (c) 2018 Acroname Inc. - All Rights Reserved
|
||||
#
|
||||
# This file is part of the BrainStem development package.
|
||||
# See file LICENSE or go to https://acroname.com/software/brainstem-development-kit for full license details.
|
||||
import brainstem
|
||||
# Requires pySerial
|
||||
import serial
|
||||
import serial.tools.list_ports
|
||||
|
||||
#for easy access to error constants
|
||||
from brainstem.result import Result
|
||||
|
||||
|
||||
# HARDWARE SETUP:
|
||||
# This example assumes that you have a loop back cable from UART 0 TO UART 1 on
|
||||
# the MTMIOSerial device. (Remember to swap those TX/RX lines)
|
||||
|
||||
# Constants
|
||||
RAIL_1_VOLTAGE = 5000000 #5VDC
|
||||
|
||||
# Example of Mac/Linux ports. Windows would be "COM#" with "#" being replaced
|
||||
# by the port number. i.e. COM5, or COM9 etc.
|
||||
BRAINSTEM_OUTPUT_PORT = 0
|
||||
BRAINSTEM_INPUT_PORT = 1
|
||||
SERIAL_BAUDRATE = 115200
|
||||
SERIAL_TIMEOUT = .5
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Creating MTMIOSerial Object")
|
||||
stem = brainstem.stem.MTMIOSerial()
|
||||
|
||||
|
||||
print ("Attempting to connect to device")
|
||||
#Locate and connect to the first object you find on USB
|
||||
#Easy way: 1=USB, 2=TCPIP
|
||||
err = stem.discoverAndConnect(brainstem.link.Spec.USB)
|
||||
#Locate and connect to a specific module (replace "0x66F4859B" with your Serial Number (hex))
|
||||
#result = stem.discoverAndConnect(brainstem.link.Spec.USB, 0x66F4859B)
|
||||
if err == Result.NO_ERROR: print ("Connected")
|
||||
else: print ("Failed to connect to device")
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Configuring MTMIOSerial device")
|
||||
err = stem.rail[1].setVoltageSetpoint(RAIL_1_VOLTAGE)
|
||||
print ("Rail 1 Voltage was set to %d VDC, Error: %d" % (RAIL_1_VOLTAGE, err))
|
||||
err = stem.rail[1].setEnable(True)
|
||||
print ("Enabling Rail 1: Error %d" % err)
|
||||
|
||||
|
||||
# Output for this example
|
||||
err = stem.uart[BRAINSTEM_OUTPUT_PORT].setEnable(1)
|
||||
print ("Enabling Channel 0's Data lines: Error %d" % err)
|
||||
# Input for this example
|
||||
err = stem.uart[BRAINSTEM_INPUT_PORT].setEnable(1)
|
||||
print ("Enabling Channel 1's Data lines: Error %d" % err)
|
||||
|
||||
|
||||
# Communication port setup: pySerial
|
||||
# //////////////////////////////////////////////////////////////////////////////
|
||||
print ("")
|
||||
print ("Setting up output port")
|
||||
found_ports = serial.tools.list_ports.grep("MTMIOSerial - UART%s" % BRAINSTEM_OUTPUT_PORT)
|
||||
serialOutput = serial.Serial()
|
||||
serialOutput.baudrate = SERIAL_BAUDRATE
|
||||
serialOutput.port = next(found_ports).device
|
||||
serialOutput.timeout = SERIAL_TIMEOUT
|
||||
print ("Port Configuration")
|
||||
print (serialOutput)
|
||||
serialOutput.open()
|
||||
print ("The port: \"%s\" is open: %s" % (serialOutput.port, serialOutput.is_open))
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Setting up input port")
|
||||
found_ports = serial.tools.list_ports.grep("MTMIOSerial - UART%s" % BRAINSTEM_INPUT_PORT)
|
||||
serialInput = serial.Serial()
|
||||
serialInput.baudrate = SERIAL_BAUDRATE
|
||||
serialInput.port = next(found_ports).device
|
||||
serialInput.timeout = SERIAL_TIMEOUT
|
||||
print ("Port Configuration:")
|
||||
print (serialInput)
|
||||
serialInput.open()
|
||||
print ("The port: \"%s\" is open: %s" % (serialInput.port, serialOutput.is_open))
|
||||
# //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
for x in range(0, 10):
|
||||
|
||||
# This if/else is to show that the enable and disable do infact work
|
||||
# Note: The host machine does not know that the ports are being enabled/disabled
|
||||
# and will still send the data out (host computer), but the MTMIOSerial will
|
||||
# not output the data. You will notice that the read it tied to
|
||||
# "numBytesWritten". This will cause the read to "timeout" (.5 seconds)
|
||||
# becauese the host computer is under the impression that the data was written.
|
||||
if(x % 2):
|
||||
# Note: This only disables the TX lines. The RX lines are not affected
|
||||
# by the enable and disable. In other words you might think you can use
|
||||
# stem.uart[0].setChannelDisable(BRAINSTEM_INPUT_PORT) to disable the read,
|
||||
# but this will have no affect
|
||||
err = stem.uart[BRAINSTEM_OUTPUT_PORT].setEnable(0)
|
||||
else:
|
||||
err = stem.uart[BRAINSTEM_OUTPUT_PORT].setEnable(1)
|
||||
# Enabling and disabling the UART will cause "noise" in the read buffer
|
||||
# It is best to reset the buffer before starting again.
|
||||
serialInput.reset_input_buffer()
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Writting to port:")
|
||||
numBytesWritten = serialOutput.write(b'Testing...')
|
||||
print ("%d Bytes were written to serial port: \"%s\"" % (numBytesWritten, serialOutput.port))
|
||||
|
||||
|
||||
print ("Reading from port:")
|
||||
print ("The following was read from port: \"%s\": \"%s\"" % (serialInput.port, serialInput.read(numBytesWritten)))
|
||||
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Closing port: \"%s\"" % serialOutput.port)
|
||||
serialOutput.close()
|
||||
print ("Closing port: \"%s\"" % serialInput.port)
|
||||
serialInput.close()
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Returning MTMIOSerial to its previous configuration")
|
||||
err = stem.rail[1].setEnable(False)
|
||||
print ("Disabling Rail 1 Error %d" % err)
|
||||
err = stem.uart[BRAINSTEM_OUTPUT_PORT].setEnable(0)
|
||||
print ("Disabling Channel 0's Data lines: Error %d" % err)
|
||||
err = stem.uart[BRAINSTEM_INPUT_PORT].setEnable(0)
|
||||
print ("Disabling Channel 1's Data lines: Error %d" % err)
|
||||
|
||||
|
||||
print ("Disconnecting from device")
|
||||
stem.disconnect()
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
brainstem>=2.9.0
|
||||
pyserial>=3.4
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
mtm_io_serial_uart.py
|
||||
========================
|
||||
|
||||
General Overview:
|
||||
-----------------
|
||||
This example is a basic demonstration of the MTM-Load-1's Constant Current ability. In this example the Rail 0 entity is being initialized, setup for constant current linear operation with a current setpoint of 100mA. After which, there is modification of the max voltage limit to 5V and enabling of the rail. While the rail is enabled, the measured voltage and current is gathered, then the rail is diabled.
|
||||
|
||||
How to Run:
|
||||
-----------
|
||||
To run this example follow the instructions enumerated in the BrainStem python documentation.
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# Copyright (c) 2019 Acroname Inc. - All Rights Reserved
|
||||
#
|
||||
# This file is part of the BrainStem development package.
|
||||
# See file LICENSE or go to https://acroname.com/software/brainstem-development-kit for full license details.
|
||||
import brainstem
|
||||
# for easy access to error constants
|
||||
from brainstem.result import Result
|
||||
import time
|
||||
|
||||
# Note: This example assumes you have a device connected to the rail 0 and is
|
||||
# capable of allowing 5VDC @ 100mA.
|
||||
|
||||
print('\nCreating MTM-Load-1 stem and connecting to first module found')
|
||||
stem = brainstem.stem.MTMLOAD1()
|
||||
|
||||
# Locate and connect to the first BrainStem device found (object type must match the device).
|
||||
# Easy way: USB=1, TCPIP=2
|
||||
result = stem.discoverAndConnect(brainstem.link.Spec.USB)
|
||||
# If you want to connect to a specific module you can supply the devics serial number.
|
||||
# result = stem.discoverAndConnect(brainstem.link.Spec.USB, 0x66F4859B)
|
||||
|
||||
# Check error
|
||||
if result == Result.NO_ERROR:
|
||||
result = stem.system.getSerialNumber()
|
||||
print("Connected to MTM-Load-1 with serial number: 0x%08X" % result.value)
|
||||
|
||||
# Operational modes are defined in aProtocoldefs.h (development/lib/BrainStem2/)
|
||||
# Device specific configurations/capabilities can be found in the product datasheet.
|
||||
# 0x01 = (railOperationalModeConstantCurrent(0x00) | railOperationalModeLinear(0x01))
|
||||
print('Setting load rail 0 to constant current mode\n')
|
||||
stem.rail[0].setOperationalMode(0x01) # this sets the operational mode to constant current and linear mode
|
||||
|
||||
print('Setting load rail 0 to draw 0.1A\n')
|
||||
stem.rail[0].setCurrentSetpoint(100000) # Current is in microamps
|
||||
|
||||
print('Setting load rail 0 max voltage to 5.0V\n')
|
||||
stem.rail[0].setVoltageMaxLimit(5000000)
|
||||
|
||||
print('Enabling load rail 0\n')
|
||||
stem.rail[0].setEnable(True)
|
||||
|
||||
print('Allowing time for the rail to stabilize\n')
|
||||
time.sleep(1)
|
||||
|
||||
voltage = stem.rail[0].getVoltage()
|
||||
print('Voltage: %d microvolts, Error: %d\n' % (voltage.value, voltage.error))
|
||||
|
||||
current = stem.rail[0].getCurrent()
|
||||
print('Current: %d microamps, Error: %d\n' % (current.value, current.error))
|
||||
|
||||
print('Disabling load rail 0\n')
|
||||
stem.rail[0].setEnable(False)
|
||||
|
||||
else:
|
||||
print('Could not find a module.\n')
|
||||
|
||||
# Disconnect from device.
|
||||
stem.disconnect()
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import argparse
|
||||
import sys
|
||||
|
||||
|
||||
class CustomArgumentParser(argparse.ArgumentParser):
|
||||
def __init__(self, argv=None, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.argv = argv if argv is not None else sys.argv[1:]
|
||||
|
||||
|
||||
self.add_argument("-d", "--device", help="Acroname Device Serial Number", type=self.auto_int, metavar='', default=0)
|
||||
self.add_argument("-p", "--port", help="Port to send the request on.", required=True, type=int, metavar='')
|
||||
self.add_argument("-r", "--request", help="The BrainStem Power Delivery request to send", required=True, type=int, metavar='')
|
||||
self.add_argument("-s", "--sop", help="SOP Selection: SOP`Debug(3), SOP``Debug(4)", required=False, type=int, metavar='', choices={0,1,2,3,4}, default=0)
|
||||
|
||||
self.parsed_args = self.parse_args(self.argv[1:])
|
||||
self.port = self.parsed_args.port
|
||||
self.request = self.parsed_args.request
|
||||
self.sn = self.parsed_args.device
|
||||
self.sop = self.parsed_args.sop
|
||||
|
||||
def print_example_usage(self):
|
||||
|
||||
EXAMPLE_USAGE = [ \
|
||||
(""), \
|
||||
("Example Usage:"), \
|
||||
(" \"%s -p 2 -r 14\" - Requests \"pdRequestBatteryCapabilities\" on the given port" % (self.argv[0])), \
|
||||
(" \"%s -p 3 -r 15\" - Requests \"pdRequestBatteryStatus\" on the given port" % (self.argv[0])), \
|
||||
(" \"%s -p 4 -r 16\" - Requests \"pdRequestManufacturerInfoSop\" on the given port" % (self.argv[0])), \
|
||||
]
|
||||
|
||||
for usage in EXAMPLE_USAGE:
|
||||
print(usage)
|
||||
|
||||
def print_help(self):
|
||||
super().print_help()
|
||||
self.print_example_usage()
|
||||
|
||||
@staticmethod
|
||||
def auto_int(x):
|
||||
# Automatically detect the base (hex if prefixed with '0x', decimal otherwise)
|
||||
return int(x, 0)
|
||||
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#System
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
|
||||
#BrainStem
|
||||
import brainstem
|
||||
from brainstem import _BS_C #Gives access to aProtocolDef.h constants.
|
||||
from brainstem.result import Result
|
||||
|
||||
#Local files
|
||||
from argument_parser import *
|
||||
|
||||
#Power Delivery Utilities
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_dir = os.path.abspath(os.path.join(script_dir, "../utilities/PowerDelivery"))
|
||||
sys.path.insert(0, parent_dir)
|
||||
from bs_pd_packet_filtering import *
|
||||
|
||||
#Generic Utilities
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_dir = os.path.abspath(os.path.join(script_dir, "../utilities"))
|
||||
sys.path.insert(0, parent_dir)
|
||||
from brainstem_helpers import *
|
||||
|
||||
|
||||
#Checks to see if the device can execute the required commands for a given port.
|
||||
#This also includes some functionality from software features.
|
||||
def check_device_capability(stem, port_index):
|
||||
#Note: I don't check System commands. All devices have a system class.
|
||||
|
||||
#Check how many PowerDelivery Entities this devices has.
|
||||
result = stem.classQuantity(_BS_C.cmdPOWERDELIVERY)
|
||||
s = "Exiting: Could not acquire class quantity for cmdPOWERDELIVERY - %s" % (result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that the supplied port does not exceed the amount of PowerDelivery entities this devices has.
|
||||
if port_index > result.value:
|
||||
print("Exiting The provided port is out of range of supported ports for this device (cmdPOWERDELIVERY). - %s" % (result))
|
||||
sys.exit(2)
|
||||
|
||||
#Check that we can send PD Requests
|
||||
result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryRequestCommand, port_index, (_BS_C.ueiOPTION_SET))
|
||||
s = "Exiting: There is an error with this devices ability to send PD requests on port: %d - %s" % (port_index, result)
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#Check that we can enable PD Logging
|
||||
result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryLogEnable, port_index, (_BS_C.ueiOPTION_SET))
|
||||
s = "Exiting: There is an error with this devices ability to send Power Delivery Logging Enable requests on port: %d - %s" % (port_index, result)
|
||||
s += "\nDoes this devices have the PD Logging software feature?"
|
||||
basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
#TODO: This check doesn't exist in firmware yet.
|
||||
# #Check that we can register for PD Logging events
|
||||
# result = stem.hasUEI(_BS_C.cmdPOWERDELIVERY, _BS_C.powerdeliveryLogEvent, port_index, (_BS_C.ueiOPTION_SET))
|
||||
# s = "Exiting: There is an error with this devices ability to register for Power Delivery Events on port: %d - %s" % (port_index, result)
|
||||
# s += "\nDoes this devices have the PD Logging software feature?"
|
||||
# basic_error_handling(stem, result, s, exit=True, exit_code=2)
|
||||
|
||||
|
||||
#Ensure the software library is >=2.11.x
|
||||
def check_software_version_capability():
|
||||
if not brainstem.version.isAtLeast(2, 11, 2).value:
|
||||
print("Exiting: This application requires BrainStem >= 2.11.2")
|
||||
sys.exit(14)
|
||||
|
||||
|
||||
def handle_request(stem, port_index, request, logger, sop):
|
||||
func_tx = None
|
||||
func_rx = None
|
||||
func_decode = None
|
||||
|
||||
requests_dict = get_request_dict()
|
||||
if requests_dict.get(request, None):
|
||||
func_tx = requests_dict[request][0]
|
||||
func_rx = requests_dict[request][1]
|
||||
func_decode = requests_dict[request][2]
|
||||
else:
|
||||
print("The following request is not currently supported: %d" %(request))
|
||||
return None
|
||||
|
||||
if func_tx and func_rx and func_decode:
|
||||
pd = brainstem.entity.PowerDelivery(stem, port_index)
|
||||
result = pd.request(request)
|
||||
basic_error_handling(stem, result, ("pd.sendRequest(%d)" % (request)))
|
||||
result = pd_packet_filter(logger, sop, func_tx, func_rx)
|
||||
if result and result.error == Result.NO_ERROR:
|
||||
return func_decode(result.value)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
#Context manager that handles cleanup of the stem and logger.
|
||||
class CLI_Manager:
|
||||
def __init__(self):
|
||||
self.stem = None #brainstem.module.Module objects
|
||||
self.logger = None #PDChannelLogger objects
|
||||
|
||||
def __enter__(self): #You must have this function for the context manager to work correctly
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if self.logger:
|
||||
self.logger.setEnabled(False)
|
||||
self.logger = None
|
||||
|
||||
if self.stem:
|
||||
self.stem.disconnect()
|
||||
self.stem = None
|
||||
|
||||
return False # Ensure exception propagates
|
||||
|
||||
|
||||
def main(argv):
|
||||
try:
|
||||
print("Provided Arguments:")
|
||||
print(argv)
|
||||
arg_parser = CustomArgumentParser(argv)
|
||||
|
||||
with CLI_Manager() as cli:
|
||||
|
||||
#Setup
|
||||
#/////////////////////////////////////////////////////////////////////
|
||||
#---------------------------------------------------------------------
|
||||
#Note: This code doesn't use the typical BrainStem object, but instead uses a Module object.
|
||||
#The Module class is the base class for all BrainStem Objects like the USBHub3c, USBHub3p, USBCSwitch etc.
|
||||
#This allows our code to be more generic; however, we don't really know what we are or what
|
||||
#we are capable of and that is why we do a handful of capability checks here.
|
||||
cli.stem = create_and_connect_stem(arg_parser.sn)
|
||||
check_device_capability(cli.stem, arg_parser.port)
|
||||
check_software_version_capability()
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
cli.logger = create_logger(cli.stem, arg_parser.port) #Create Logger object for given port
|
||||
#/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#Work
|
||||
#/////////////////////////////////////////////////////////////////////
|
||||
request_result = handle_request(cli.stem, arg_parser.port, arg_parser.request, cli.logger, arg_parser.sop)
|
||||
print(request_result)
|
||||
#/////////////////////////////////////////////////////////////////////
|
||||
|
||||
except SystemExit as e:
|
||||
return e
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
# RDO Test CLI
|
||||
|
||||
This example is designed to test Fixed PDOs of known USB PD power supplies.
|
||||
|
||||
The test validates:
|
||||
- PDO values reported by the connected power supply match expected values
|
||||
- RDO requests are accepted and result in the expected voltage levels
|
||||
|
||||
Load testing of the PDOs is left as an exercise to the reader.
|
||||
|
||||
## Supported Power Supplies
|
||||
|
||||
| Power Supply | Voltage Levels |
|
||||
|--------------|----------------|
|
||||
| Nekteck | 5V, 9V, 15V, 20V |
|
||||
| HKY100W | 5V, 9V, 12V, 15V, 20V |
|
||||
| Apple61W | 5V, 9V, 15V, 20V |
|
||||
| Apple96W | 5V, 9V, 15V, 20V |
|
||||
| Apple140W | 5V, 9V, 15V, 20V |
|
||||
| Samsung45W | 5V, 9V, 15V, 20V |
|
||||
| Samsung25W | 5V, 9V |
|
||||
| PD45W | 5V, 9V, 15V, 20V |
|
||||
|
||||
> **Note:** Additional power supplies can be added by modifying the `POWER_SUPPLY_CONFIGS` dictionary in `power_supply_configs.py`.
|
||||
|
||||
## Hardware Setup
|
||||
|
||||
> **Note:** Configuration assumes a device with its default settings. If your device has been significantly changed from the default it might be worthwhile doing a factory reset.
|
||||
|
||||
- **Upstream connection:** "Port 0" connected to host
|
||||
- **Power supply:** 100W USB-C power supply connected to "Power C" port or an Unregulated connection.
|
||||
- **Device under test:** PD power supply connected to the test port.
|
||||
|
||||
> **Note:** If the DUT power supply is >= the "Power Supply" then an unregulated connection will be required for best results.
|
||||
|
||||
## Software Setup
|
||||
|
||||
1. Create a virtual environment:
|
||||
```bash
|
||||
python -m venv venv
|
||||
```
|
||||
|
||||
2. Activate the virtual environment:
|
||||
```bash
|
||||
# macOS/Linux
|
||||
source venv/bin/activate
|
||||
|
||||
# Windows
|
||||
venv\Scripts\activate
|
||||
```
|
||||
|
||||
3. Install BrainStem:
|
||||
```bash
|
||||
pip install brainstem
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
**Detailed Help:**
|
||||
```bash
|
||||
python rdo_test_cli.py --help
|
||||
```
|
||||
|
||||
**Extended Help (from README):**
|
||||
```bash
|
||||
python rdo_test_cli.py --help_extended
|
||||
```
|
||||
|
||||
**Test HKY power supply on port 5:**
|
||||
```bash
|
||||
python rdo_test_cli.py --test_port 5 --dut HKY100W
|
||||
```
|
||||
|
||||
**Test Nekteck power supply on port 4:**
|
||||
```bash
|
||||
python rdo_test_cli.py --test_port 4 --dut Nekteck
|
||||
```
|
||||
|
||||
**Test PD45W power supply on port 3:**
|
||||
```bash
|
||||
python rdo_test_cli.py --test_port 3 --dut PD45W
|
||||
```
|
||||
|
||||
**Connect to a specific device by serial number:**
|
||||
```bash
|
||||
python rdo_test_cli.py --test_port 5 --dut HKY100W --sn 0x12345678
|
||||
```
|
||||
|
||||
## Exit Codes
|
||||
|
||||
| Code | Name | Description |
|
||||
|------|------|-------------|
|
||||
| 0 | SUCCESS | All tests passed |
|
||||
| 1 | CONNECTION_ERROR | Failed to connect to device |
|
||||
| 2 | CAPABILITY_CHECK_FAILED | Device does not support required capabilities |
|
||||
| 3 | PDO_TEST_FAILED | One or more PDO tests failed |
|
||||
| 4 | RDO_TEST_FAILED | One or more RDO tests failed |
|
||||
| 5 | PORT_DISABLE_FAILED | Failed to disable port |
|
||||
| 6 | PORT_ENABLE_FAILED | Failed to enable port |
|
||||
|
||||
## Adding New Power Supplies
|
||||
|
||||
To add support for a new power supply:
|
||||
|
||||
1. Connect the power supply and run the script with an existing DUT configuration
|
||||
2. Note the actual PDO values reported in the output
|
||||
3. Use HubTool to find:
|
||||
- `KEY_EXPECTED_HOST_PDOS_VOLTAGE`: Look at "Power Data Object: Remote Source" and convert voltage to microvolts (µV)
|
||||
- `KEY_EXPECTED_RDOS`: Select the "Object Position" for each index and copy the "Raw" value
|
||||
4. Add a new entry to `POWER_SUPPLY_CONFIGS` in `power_supply_configs.py`
|
||||
|
||||
> **Note:** RDOs can be created programmatically, but this requires a deep understanding of the PD protocol and is beyond the scope of this example.
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add utilities to path for readme_helper import
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
utilities_dir = os.path.abspath(os.path.join(script_dir, "../utilities"))
|
||||
sys.path.insert(0, utilities_dir)
|
||||
from readme_helper import read_readme_as_help
|
||||
from power_supply_configs import POWER_SUPPLY_CONFIGS, KEY_EXPECTED_HOST_PDOS, KEY_EXPECTED_HOST_PDOS_VOLTAGE, KEY_EXPECTED_RDOS
|
||||
|
||||
|
||||
class CustomArgumentParser:
|
||||
"""Command-line argument parser for the RDO Test CLI script."""
|
||||
|
||||
def __init__(self, argv):
|
||||
self._test_port = None
|
||||
self._dut = None
|
||||
self._sn = 0
|
||||
self._expected_host_pdos = None
|
||||
self._expected_host_pdos_voltage = None
|
||||
self._expected_rdos = None
|
||||
self._parse_arguments(argv)
|
||||
|
||||
@staticmethod
|
||||
def _parse_serial_number(value):
|
||||
try:
|
||||
return int(value, 0)
|
||||
except ValueError:
|
||||
try:
|
||||
return int(value, 16)
|
||||
except ValueError:
|
||||
raise argparse.ArgumentTypeError("'%s' - use decimal or hex (0x...)" % value)
|
||||
|
||||
def _parse_arguments(self, argv):
|
||||
"""Parse command-line arguments."""
|
||||
# Handle --help_extended early, before argparse validates required args
|
||||
if "--help_extended" in argv:
|
||||
print(read_readme_as_help(__file__))
|
||||
sys.exit(0)
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="RDO Test CLI - Tests USB Power Delivery RDO (Request Data Object) configurations on USB Hub ports.",
|
||||
epilog="Use --help_extended for detailed documentation from the README.",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-t", "--test_port",
|
||||
type=int,
|
||||
required=True,
|
||||
help="Port number under test"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-d", "--dut",
|
||||
choices=list(POWER_SUPPLY_CONFIGS.keys()),
|
||||
required=True,
|
||||
help="Power supply to test: %s" % ", ".join(POWER_SUPPLY_CONFIGS.keys())
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-s", "--sn",
|
||||
type=self._parse_serial_number,
|
||||
default=0,
|
||||
help="Serial number of the device to connect to (hex or decimal, default: 0 = first found)"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--help_extended",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Show extended help from the README file and exit."
|
||||
)
|
||||
|
||||
args = parser.parse_args(argv[1:])
|
||||
|
||||
self._test_port = args.test_port
|
||||
self._dut = args.dut
|
||||
self._sn = args.sn
|
||||
|
||||
# Load power supply configuration
|
||||
if self._dut not in POWER_SUPPLY_CONFIGS:
|
||||
parser.error("Unknown power supply: %s" % self._dut)
|
||||
|
||||
config = POWER_SUPPLY_CONFIGS[self._dut]
|
||||
self._expected_host_pdos = config[KEY_EXPECTED_HOST_PDOS]
|
||||
self._expected_host_pdos_voltage = config[KEY_EXPECTED_HOST_PDOS_VOLTAGE]
|
||||
self._expected_rdos = config[KEY_EXPECTED_RDOS]
|
||||
|
||||
print("Test Port: %d" % self._test_port)
|
||||
print("DUT: %s" % self._dut)
|
||||
if self._sn:
|
||||
print("Target serial number: 0x%08X" % self._sn)
|
||||
|
||||
@property
|
||||
def test_port(self):
|
||||
return self._test_port
|
||||
|
||||
@property
|
||||
def dut(self):
|
||||
return self._dut
|
||||
|
||||
@property
|
||||
def sn(self):
|
||||
return self._sn
|
||||
|
||||
@property
|
||||
def expected_host_pdos(self):
|
||||
return self._expected_host_pdos
|
||||
|
||||
@property
|
||||
def expected_host_pdos_voltage(self):
|
||||
return self._expected_host_pdos_voltage
|
||||
|
||||
@property
|
||||
def expected_rdos(self):
|
||||
return self._expected_rdos
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue