openpilot v0.7.9 release

Vehicle Researcher 2020-10-02 01:45:44 +00:00
parent 0aa4867be4
commit 49d82d6ac1
268 changed files with 5986 additions and 5106 deletions

View File

@ -18,7 +18,7 @@ You can test your changes on your machine by running `run_docker_tests.sh`. This
### Automated Testing
All PRs and commits are automatically checked by Github Actions. Check out `.github/workflows/` for what Github Actions runs. Any new tests sould be added to Github Actions.
All PRs and commits are automatically checked by Github Actions. Check out `.github/workflows/` for what Github Actions runs. Any new tests should be added to Github Actions.
### Code Style and Linting
@ -28,7 +28,7 @@ Code is automatically checked for style by Github Actions as part of the automat
We've released a [Model Port guide](https://medium.com/@comma_ai/openpilot-port-guide-for-toyota-models-e5467f4b5fe6) for porting to Toyota/Lexus models.
If you port openpilot to a substantially new car brand, see this more generic [Brand Port guide](https://medium.com/@comma_ai/how-to-write-a-car-port-for-openpilot-7ce0785eda84). You might also be eligible for a bounty. See our bounties at [comma.ai/bounties.html](https://comma.ai/bounties.html)
If you port openpilot to a substantially new car brand, see this more generic [Brand Port guide](https://medium.com/@comma_ai/how-to-write-a-car-port-for-openpilot-7ce0785eda84). You might also be eligible for a bounty.
## Pull Requests

10
Jenkinsfile vendored
View File

@ -70,7 +70,7 @@ pipeline {
stage('PC tests') {
agent {
dockerfile {
filename 'Dockerfile.openpilot'
filename 'Dockerfile.openpilotci'
args '--privileged --shm-size=1G --user=root'
}
}
@ -132,6 +132,7 @@ pipeline {
["build cereal", "SCONS_CACHE=1 scons -j4 cereal/"],
["test sounds", "nosetests -s selfdrive/test/test_sounds.py"],
["test boardd loopback", "nosetests -s selfdrive/boardd/tests/test_boardd_loopback.py"],
["test loggerd", "CI=1 python selfdrive/loggerd/tests/test_loggerd.py"],
//["test updater", "python installer/updater/test_updater.py"],
])
}
@ -140,6 +141,13 @@ pipeline {
}
}
}
post {
always {
cleanWs()
}
}
}
}

View File

@ -70,31 +70,30 @@ Supported Cars
| Honda | Accord Hybrid 2018-20 | All | Stock | 0mph | 3mph |
| Honda | Civic Hatchback 2017-19 | Honda Sensing | Stock | 0mph | 12mph |
| Honda | Civic Sedan/Coupe 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
| Honda | Civic Sedan/Coupe 2019-20 | Honda Sensing | Stock | 0mph | 2mph<sup>2</sup> |
| Honda | Civic Sedan/Coupe 2019-20 | All | Stock | 0mph | 2mph<sup>2</sup> |
| Honda | CR-V 2015-16 | Touring | openpilot | 25mph<sup>1</sup> | 12mph |
| Honda | CR-V 2017-20 | Honda Sensing | Stock | 0mph | 12mph |
| Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Stock | 0mph | 12mph |
| Honda | Fit 2018-19 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
| Honda | HR-V 2019 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
| Honda | Insight 2019-20 | Honda Sensing | Stock | 0mph | 3mph |
| Honda | Insight 2019-20 | All | Stock | 0mph | 3mph |
| Honda | Odyssey 2018-20 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 0mph |
| Honda | Passport 2019 | All | openpilot | 25mph<sup>1</sup> | 12mph |
| Honda | Pilot 2016-18 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
| Honda | Pilot 2019 | All | openpilot | 25mph<sup>1</sup> | 12mph |
| Honda | Pilot 2016-19 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
| Honda | Ridgeline 2017-20 | Honda Sensing | openpilot | 25mph<sup>1</sup> | 12mph |
| Hyundai | Palisade 2020 | All | Stock | 0mph | 0mph |
| Hyundai | Sonata 2020 | All | Stock | 0mph | 0mph |
| Lexus | CT Hybrid 2017-18 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Lexus | CT Hybrid 2017-18 | LSS | Stock<sup>3</sup>| 0mph | 0mph |
| Lexus | ES 2019 | All | openpilot | 0mph | 0mph |
| Lexus | ES Hybrid 2019 | All | openpilot | 0mph | 0mph |
| Lexus | IS 2017-2019 | All | Stock | 22mph | 0mph |
| Lexus | IS Hybrid 2017 | All | Stock | 0mph | 0mph |
| Lexus | NX Hybrid 2018 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Lexus | RX 2016-17 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Lexus | RX 2016-18 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Lexus | RX 2020 | All | openpilot | 0mph | 0mph |
| Lexus | RX Hybrid 2016-19 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Lexus | RX Hybrid 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Avalon 2016 | TSS-P | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
| Toyota | Avalon 2017-18 | All | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
| Toyota | Avalon 2016-18 | TSS-P | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
| Toyota | Camry 2018-20 | All | Stock | 0mph<sup>4</sup> | 0mph |
| Toyota | Camry Hybrid 2018-19 | All | Stock | 0mph<sup>4</sup> | 0mph |
| Toyota | C-HR 2017-19 | All | Stock | 0mph | 0mph |
@ -102,19 +101,16 @@ Supported Cars
| Toyota | Corolla 2017-19 | All | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
| Toyota | Corolla 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Corolla Hatchback 2019-20 | All | openpilot | 0mph | 0mph |
| Toyota | Corolla Hybrid 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Corolla Hybrid 2020-21 | All | openpilot | 0mph | 0mph |
| Toyota | Highlander 2017-19 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Highlander Hybrid 2017-19 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Highlander 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Highlander Hybrid 2017-19 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Highlander Hybrid 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Prius 2016 | TSS-P | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Prius 2017-20 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Prius 2016-20 | TSS-P | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Prius Prime 2017-20 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Rav4 2016 | TSS-P | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
| Toyota | Rav4 2017-18 | All | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
| Toyota | Rav4 2016-18 | TSS-P | Stock<sup>3</sup>| 20mph<sup>1</sup> | 0mph |
| Toyota | Rav4 2019-20 | All | openpilot | 0mph | 0mph |
| Toyota | Rav4 Hybrid 2016 | TSS-P | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Rav4 Hybrid 2017-18 | All | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Rav4 Hybrid 2016-18 | TSS-P | Stock<sup>3</sup>| 0mph | 0mph |
| Toyota | Rav4 Hybrid 2019-20 | All | openpilot | 0mph | 0mph |
| Toyota | Sienna 2018-20 | All | Stock<sup>3</sup>| 0mph | 0mph |
@ -143,24 +139,22 @@ Community Maintained Cars and Features
| Holden | Astra 2017<sup>1</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
| Hyundai | Elantra 2017-19 | SCC + LKAS | Stock | 19mph | 34mph |
| Hyundai | Genesis 2015-16 | SCC + LKAS | Stock | 19mph | 37mph |
| Hyundai | Ioniq Electric Premium SE 2020| SCC + LKAS | Stock | 0mph | 32mph |
| Hyundai | Ioniq Electric Limited 2019 | SCC + LKAS | Stock | 0mph | 32mph |
| Hyundai | Ioniq Electric 2019-20 | SCC + LKAS | Stock | 0mph | 32mph |
| Hyundai | Kona 2020 | SCC + LKAS | Stock | 0mph | 0mph |
| Hyundai | Kona EV 2019 | SCC + LKAS | Stock | 0mph | 0mph |
| Hyundai | Palisade 2020 | All | Stock | 0mph | 0mph |
| Hyundai | Santa Fe 2019 | All | Stock | 0mph | 0mph |
| Hyundai | Sonata 2019 | All | Stock | 0mph | 0mph |
| Hyundai | Veloster 2019 | SCC + LKAS | Stock | 5mph | 0mph |
| Jeep | Grand Cherokee 2016-18 | Adaptive Cruise | Stock | 0mph | 9mph |
| Jeep | Grand Cherokee 2019-20 | Adaptive Cruise | Stock | 0mph | 39mph |
| Kia | Forte 2018-19 | SCC + LKAS | Stock | 0mph | 0mph |
| Kia | Optima 2017 | SCC + LKAS/LDWS | Stock | 0mph | 32mph |
| Kia | Optima 2017 | SCC + LKAS | Stock | 0mph | 32mph |
| Kia | Optima 2019 | SCC + LKAS | Stock | 0mph | 0mph |
| Kia | Sorento 2018 | SCC + LKAS | Stock | 0mph | 0mph |
| Kia | Stinger 2018 | SCC + LKAS | Stock | 0mph | 0mph |
| Nissan | Leaf 2018-19 | Propilot | Stock | 0mph | 0mph |
| Nissan | Rogue 2019 | Propilot | Stock | 0mph | 0mph |
| Nissan | X-Trail 2017 | Propilot | Stock | 0mph | 0mph |
| Nissan | Leaf 2018-19 | ProPILOT | Stock | 0mph | 0mph |
| Nissan | Rogue 2019 | ProPILOT | Stock | 0mph | 0mph |
| Nissan | X-Trail 2017 | ProPILOT | Stock | 0mph | 0mph |
| Subaru | Ascent 2019 | EyeSight | Stock | 0mph | 0mph |
| Subaru | Crosstrek 2018-19 | EyeSight | Stock | 0mph | 0mph |
| Subaru | Forester 2019 | EyeSight | Stock | 0mph | 0mph |
@ -274,8 +268,23 @@ Safety and Testing
Testing on PC
------
For simplified development and experimentation, openpilot runs in the CARLA driving simulator, which allows you to develop openpilot without a car.
Steps:
1) Start the CARLA server on first terminal
```
bash -c "$(curl https://raw.githubusercontent.com/commaai/openpilot/master/tools/sim/start_carla.sh)"
```
2) Start openpilot on second terminal
```
bash -c "$(curl https://raw.githubusercontent.com/commaai/openpilot/master/tools/sim/start_openpilot_docker.sh)"
```
3) Press 1 to engage openpilot
See the full [README](tools/sim/README.md)
You should also take a look at the tools directory in master: lots of tools you can use to replay driving data, test, and develop openpilot from your PC.
Check out the tools directory in master: lots of tools you can use to replay driving data, test and develop openpilot from your pc.
Community and Contributing
------

View File

@ -1,3 +1,11 @@
Version 0.7.9 (2020-10-09)
========================
* Improved car battery power management
* Improved updater robustness
* Improved realtime performance
* Reduced UI and modeld lags
* Increased torque on 2020 Hyundai Sonata and Palisade
Version 0.7.8 (2020-08-19)
========================
* New driver monitoring model: improved face detection and better compatibility with sunglasses

View File

@ -6,6 +6,8 @@ import subprocess
import sys
import platform
TICI = os.path.isfile('/TICI')
AddOption('--test',
action='store_true',
help='build test files')
@ -18,10 +20,11 @@ AddOption('--asan',
cython_dependencies = [Value(v) for v in (sys.version, distutils.__version__, Cython.__version__)]
Export('cython_dependencies')
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
real_arch = arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
if platform.system() == "Darwin":
arch = "Darwin"
if arch == "aarch64" and not os.path.isdir("/system"):
if arch == "aarch64" and TICI:
arch = "larch64"
webcam = bool(ARGUMENTS.get("use_webcam", 0))
@ -44,7 +47,6 @@ if arch == "aarch64" or arch == "larch64":
libpath = [
"/usr/lib",
"/data/data/com.termux/files/usr/lib",
"/system/vendor/lib64",
"/system/comma/usr/lib",
"#phonelibs/nanovg",
@ -62,11 +64,12 @@ if arch == "aarch64" or arch == "larch64":
else:
libpath += [
"#phonelibs/snpe/aarch64",
"#phonelibs/libyuv/lib"
"#phonelibs/libyuv/lib",
"/system/vendor/lib64"
]
cflags = ["-DQCOM", "-mcpu=cortex-a57"]
cxxflags = ["-DQCOM", "-mcpu=cortex-a57"]
rpath = ["/system/vendor/lib64"]
rpath = []
if QCOM_REPLAY:
cflags += ["-DQCOM_REPLAY"]
@ -131,8 +134,11 @@ env = Environment(
"-O2",
"-Wunused",
"-Werror",
"-Wno-unknown-warning-option",
"-Wno-deprecated-register",
"-Wno-inconsistent-missing-override",
"-Wno-c99-designator",
"-Wno-reorder-init-list",
] + cflags + ccflags_asan,
CPPPATH=cpppath + [
@ -143,7 +149,6 @@ env = Environment(
"#phonelibs/openmax/include",
"#phonelibs/json11",
"#phonelibs/curl/include",
#"#phonelibs/opencv/include", # use opencv4 instead
"#phonelibs/libgralloc/include",
"#phonelibs/android_frameworks_native/include",
"#phonelibs/android_hardware_libhardware/include",
@ -156,6 +161,8 @@ env = Environment(
"#selfdrive/camerad/include",
"#selfdrive/loggerd/include",
"#selfdrive/modeld",
"#selfdrive/sensord",
"#selfdrive/ui",
"#cereal/messaging",
"#cereal",
"#opendbc/can",
@ -176,6 +183,44 @@ env = Environment(
]
)
qt_env = None
if arch in ["x86_64", "Darwin", "larch64"]:
qt_env = env.Clone()
if arch == "Darwin":
qt_env['QTDIR'] = "/usr/local/opt/qt"
QT_BASE = "/usr/local/opt/qt/"
qt_dirs = [
QT_BASE + "include/",
QT_BASE + "include/QtWidgets",
QT_BASE + "include/QtGui",
QT_BASE + "include/QtCore",
QT_BASE + "include/QtDBus",
QT_BASE + "include/QtMultimedia",
]
qt_env["LINKFLAGS"] += ["-F" + QT_BASE + "lib"]
else:
qt_dirs = [
f"/usr/include/{real_arch}-linux-gnu/qt5",
f"/usr/include/{real_arch}-linux-gnu/qt5/QtWidgets",
f"/usr/include/{real_arch}-linux-gnu/qt5/QtGui",
f"/usr/include/{real_arch}-linux-gnu/qt5/QtCore",
f"/usr/include/{real_arch}-linux-gnu/qt5/QtDBus",
f"/usr/include/{real_arch}-linux-gnu/qt5/QtMultimedia",
f"/usr/include/{real_arch}-linux-gnu/qt5/QtGui/5.5.1/QtGui",
]
qt_env.Tool('qt')
qt_env['CPPPATH'] += qt_dirs
qt_flags = [
"-D_REENTRANT",
"-DQT_NO_DEBUG",
"-DQT_WIDGETS_LIB",
"-DQT_GUI_LIB",
"-DQT_CORE_LIB"
]
qt_env['CXXFLAGS'] += qt_flags
if os.environ.get('SCONS_CACHE'):
cache_dir = '/tmp/scons_cache'
@ -214,7 +259,7 @@ def abspath(x):
# still needed for apks
zmq = 'zmq'
Export('env', 'arch', 'zmq', 'SHARED', 'webcam', 'QCOM_REPLAY')
Export('env', 'qt_env', 'arch', 'zmq', 'SHARED', 'webcam', 'QCOM_REPLAY')
# cereal and messaging are shared with the system
SConscript(['cereal/SConscript'])
@ -255,16 +300,18 @@ SConscript(['selfdrive/controls/lib/longitudinal_mpc_model/SConscript'])
SConscript(['selfdrive/boardd/SConscript'])
SConscript(['selfdrive/proclogd/SConscript'])
SConscript(['selfdrive/clocksd/SConscript'])
SConscript(['selfdrive/ui/SConscript'])
SConscript(['selfdrive/loggerd/SConscript'])
SConscript(['selfdrive/locationd/SConscript'])
SConscript(['selfdrive/locationd/models/SConscript'])
SConscript(['selfdrive/sensord/SConscript'])
SConscript(['selfdrive/ui/SConscript'])
if arch == "aarch64":
if arch != "Darwin":
SConscript(['selfdrive/logcatd/SConscript'])
SConscript(['selfdrive/sensord/SConscript'])
SConscript(['selfdrive/clocksd/SConscript'])
else:
if arch == "x86_64":
SConscript(['tools/lib/index_log/SConscript'])

View File

@ -38,7 +38,6 @@ struct CarEvent @0x9b1657f34caf3ad3 {
pedalPressed @13;
cruiseDisabled @14;
radarCanError @15;
dataNeededDEPRECATED @16;
speedTooLow @17;
outOfSpace @18;
overheat @19;
@ -49,29 +48,22 @@ struct CarEvent @0x9b1657f34caf3ad3 {
pcmDisable @24;
noTarget @25;
radarFault @26;
modelCommIssueDEPRECATED @27;
brakeHold @28;
parkBrake @29;
manualRestart @30;
lowSpeedLockout @31;
plannerError @32;
ipasOverrideDEPRECATED @33;
debugAlert @34;
steerTempUnavailableMute @35;
resumeRequired @36;
preDriverDistracted @37;
promptDriverDistracted @38;
driverDistracted @39;
geofenceDEPRECATED @40;
driverMonitorOnDEPRECATED @41;
driverMonitorOffDEPRECATED @42;
preDriverUnresponsive @43;
promptDriverUnresponsive @44;
driverUnresponsive @45;
belowSteerSpeed @46;
calibrationProgressDEPRECATED @47;
lowBattery @48;
invalidGiraffeHondaDEPRECATED @49;
vehicleModelInvalid @50;
controlsFailed @51;
sensorDataInvalid @52;
@ -104,8 +96,6 @@ struct CarEvent @0x9b1657f34caf3ad3 {
fcw @79;
steerSaturated @80;
whitePandaUnsupported @81;
startupWhitePanda @82;
canErrorPersistentDEPRECATED @83;
belowEngageSpeed @84;
noGps @85;
focusRecoverActive @86;
@ -113,6 +103,17 @@ struct CarEvent @0x9b1657f34caf3ad3 {
neosUpdateRequired @88;
modeldLagging @89;
deviceFalling @90;
dataNeededDEPRECATED @16;
modelCommIssueDEPRECATED @27;
ipasOverrideDEPRECATED @33;
geofenceDEPRECATED @40;
driverMonitorOnDEPRECATED @41;
driverMonitorOffDEPRECATED @42;
calibrationProgressDEPRECATED @47;
invalidGiraffeHondaDEPRECATED @49;
canErrorPersistentDEPRECATED @83;
startupWhitePandaDEPRECATED @82;
}
}

View File

@ -186,6 +186,7 @@ struct SensorEventData {
gyroUncalibrated @12 :SensorVec;
proximity @13: Float32;
light @14: Float32;
temperature @15: Float32;
}
source @8 :SensorSource;
@ -203,6 +204,8 @@ struct SensorEventData {
lsm6ds3 @5; # accelerometer (c2)
bmp280 @6; # barometer (c2)
mmc3416x @7; # magnetometer (c2)
bmx055 @8;
rpr0521 @9;
}
}
@ -267,14 +270,15 @@ struct CanData {
}
struct ThermalData {
cpu0 @0 :UInt16;
cpu1 @1 :UInt16;
cpu2 @2 :UInt16;
cpu3 @3 :UInt16;
mem @4 :UInt16;
gpu @5 :UInt16;
bat @6 :UInt32;
pa0 @21 :UInt16;
# Deprecated
cpu0DEPRECATED @0 :UInt16;
cpu1DEPRECATED @1 :UInt16;
cpu2DEPRECATED @2 :UInt16;
cpu3DEPRECATED @3 :UInt16;
memDEPRECATED @4 :UInt16;
gpuDEPRECATED @5 :UInt16;
batDEPRECATED @6 :UInt32;
pa0DEPRECATED @21 :UInt16;
# not thermal
freeSpace @7 :Float32;
@ -286,6 +290,7 @@ struct ThermalData {
networkType @22 :NetworkType;
offroadPowerUsage @23 :UInt32; # Power usage since going offroad in uWh
networkStrength @24 :NetworkStrength;
carBatteryCapacity @25 :UInt32; # Estimated remaining car battery capacity in uWh
fanSpeed @10 :UInt16;
started @11 :Bool;
@ -298,6 +303,12 @@ struct ThermalData {
memUsedPercent @19 :Int8;
cpuPerc @20 :Int8;
cpu @26 :List(Float32);
gpu @27 :List(Float32);
mem @28 :Float32;
bat @29 :Float32;
ambient @30 :Float32;
enum ThermalStatus {
green @0; # all processes run
yellow @1; # critical processes run (kill uploader), engage still allowed
@ -373,6 +384,8 @@ struct HealthData {
interruptRateTim3 @17;
registerDivergent @18;
interruptRateKlineInit @19;
interruptRateClockSource @20;
interruptRateTim9 @21;
# Update max fault type in boardd when adding faults
}
@ -602,7 +615,7 @@ struct ControlsState @0x97ff69c53601abf1 {
output @3 :Float32;
lqrOutput @4 :Float32;
saturated @5 :Bool;
}
}
}
struct LiveEventData {
@ -675,6 +688,52 @@ struct ModelData {
}
}
struct ModelDataV2 {
frameId @0 :UInt32;
frameAge @1 :UInt32;
frameDropPerc @2 :Float32;
timestampEof @3 :UInt64;
position @4 :XYZTData;
orientation @5 :XYZTData;
velocity @6 :XYZTData;
orientationRate @7 :XYZTData;
laneLines @8 :List(XYZTData);
laneLineProbs @9 :List(Float32);
roadEdges @10 :List(XYZTData);
leads @11 :List(LeadDataV2);
meta @12 :MetaData;
struct XYZTData {
x @0 :List(Float32);
y @1 :List(Float32);
z @2 :List(Float32);
t @3 :List(Float32);
xStd @4 :List(Float32);
yStd @5 :List(Float32);
zStd @6 :List(Float32);
}
struct LeadDataV2 {
prob @0 :Float32;
t @1 :Float32;
xyva @2 :List(Float32);
xyvaStd @3 :List(Float32);
}
struct MetaData {
engagedProb @0 :Float32;
desirePrediction @1 :List(Float32);
brakeDisengageProb @2 :Float32;
gasDisengageProb @3 :Float32;
steerOverrideProb @4 :Float32;
desireState @5 :List(Float32);
}
}
struct CalibrationFeatures {
frameId @0 :UInt32;
@ -1906,7 +1965,6 @@ struct DMonitoringState {
isDistracted @2 :Bool;
awarenessStatus @3 :Float32;
isRHD @4 :Bool;
rhdChecked @5 :Bool;
posePitchOffset @6 :Float32;
posePitchValidCount @7 :UInt32;
poseYawOffset @8 :Float32;
@ -1917,6 +1975,8 @@ struct DMonitoringState {
isLowStd @13 :Bool;
hiStdCount @14 :UInt32;
isPreview @15 :Bool;
rhdCheckedDEPRECATED @5 :Bool;
}
struct Boot {
@ -2062,5 +2122,7 @@ struct Event {
dMonitoringState @71: DMonitoringState;
liveLocationKalman @72 :LiveLocationKalman;
sentinel @73 :Sentinel;
wideFrame @74: FrameData;
modelV2 @75 :ModelDataV2;
}
}

View File

@ -3,6 +3,8 @@ from .messaging_pyx import Context, Poller, SubSocket, PubSocket # pylint: disa
from .messaging_pyx import MultiplePublishersError, MessagingError # pylint: disable=no-name-in-module, import-error
import capnp
from typing import Optional, List, Union
from cereal import log
from cereal.services import service_list
@ -19,7 +21,7 @@ except ImportError:
context = Context()
def new_message(service=None, size=None):
def new_message(service: Optional[str] = None, size: Optional[int] = None) -> capnp.lib.capnp._DynamicStructBuilder:
dat = log.Event.new_message()
dat.logMonoTime = int(sec_since_boot() * 1e9)
dat.valid = True
@ -30,15 +32,15 @@ def new_message(service=None, size=None):
dat.init(service, size)
return dat
def pub_sock(endpoint):
def pub_sock(endpoint: str) -> PubSocket:
sock = PubSocket()
sock.connect(context, endpoint)
return sock
def sub_sock(endpoint, poller=None, addr="127.0.0.1", conflate=False, timeout=None):
def sub_sock(endpoint: str, poller: Optional[Poller] = None, addr: str = "127.0.0.1",
conflate: bool = False, timeout: Optional[int] = None) -> SubSocket:
sock = SubSocket()
addr = addr.encode('utf8')
sock.connect(context, endpoint, addr, conflate)
sock.connect(context, endpoint, addr.encode('utf8'), conflate)
if timeout is not None:
sock.setTimeout(timeout)
@ -48,9 +50,9 @@ def sub_sock(endpoint, poller=None, addr="127.0.0.1", conflate=False, timeout=No
return sock
def drain_sock_raw(sock, wait_for_one=False):
def drain_sock_raw(sock: SubSocket, wait_for_one: bool = False) -> List[bytes]:
"""Receive all message currently available on the queue"""
ret = []
ret: List[bytes] = []
while 1:
if wait_for_one and len(ret) == 0:
dat = sock.receive()
@ -64,9 +66,9 @@ def drain_sock_raw(sock, wait_for_one=False):
return ret
def drain_sock(sock, wait_for_one=False):
def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.capnp._DynamicStructReader]:
"""Receive all message currently available on the queue"""
ret = []
ret: List[capnp.lib.capnp._DynamicStructReader] = []
while 1:
if wait_for_one and len(ret) == 0:
dat = sock.receive()
@ -83,7 +85,7 @@ def drain_sock(sock, wait_for_one=False):
# TODO: print when we drop packets?
def recv_sock(sock, wait=False):
def recv_sock(sock: SubSocket, wait: bool = False) -> Union[None, capnp.lib.capnp._DynamicStructReader]:
"""Same as drain sock, but only returns latest message. Consider using conflate instead."""
dat = None
@ -103,19 +105,19 @@ def recv_sock(sock, wait=False):
return dat
def recv_one(sock):
def recv_one(sock: SubSocket) -> Union[None, capnp.lib.capnp._DynamicStructReader]:
dat = sock.receive()
if dat is not None:
dat = log.Event.from_bytes(dat)
return dat
def recv_one_or_none(sock):
def recv_one_or_none(sock: SubSocket) -> Union[None, capnp.lib.capnp._DynamicStructReader]:
dat = sock.receive(non_blocking=True)
if dat is not None:
dat = log.Event.from_bytes(dat)
return dat
def recv_one_retry(sock):
def recv_one_retry(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader:
"""Keep receiving until we get a message"""
while True:
dat = sock.receive()
@ -123,8 +125,8 @@ def recv_one_retry(sock):
return log.Event.from_bytes(dat)
class SubMaster():
def __init__(self, services, ignore_alive=None, addr="127.0.0.1"):
self.poller = Poller()
def __init__(self, services: List[str], poll: Optional[List[str]] = None,
ignore_alive: Optional[List[str]] = None, addr:str ="127.0.0.1"):
self.frame = -1
self.updated = {s: False for s in services}
self.rcv_time = {s: 0. for s in services}
@ -133,8 +135,12 @@ class SubMaster():
self.sock = {}
self.freq = {}
self.data = {}
self.logMonoTime = {}
self.valid = {}
self.logMonoTime = {}
self.poller = Poller()
self.non_polled_services = [s for s in services if poll is not None and
len(poll) and s not in poll]
if ignore_alive is not None:
self.ignore_alive = ignore_alive
@ -143,30 +149,33 @@ class SubMaster():
for s in services:
if addr is not None:
self.sock[s] = sub_sock(s, poller=self.poller, addr=addr, conflate=True)
p = self.poller if s not in self.non_polled_services else None
self.sock[s] = sub_sock(s, poller=p, addr=addr, conflate=True)
self.freq[s] = service_list[s].frequency
try:
data = new_message(s)
except capnp.lib.capnp.KjException: # pylint: disable=c-extension-no-member
# lists
data = new_message(s, 0)
data = new_message(s, 0) # lists
self.data[s] = getattr(data, s)
self.logMonoTime[s] = 0
self.valid[s] = data.valid
def __getitem__(self, s):
def __getitem__(self, s: str) -> capnp.lib.capnp._DynamicStructReader:
return self.data[s]
def update(self, timeout=1000):
def update(self, timeout: int = 1000) -> None:
msgs = []
for sock in self.poller.poll(timeout):
msgs.append(recv_one_or_none(sock))
# non-blocking receive for non-polled sockets
for s in self.non_polled_services:
msgs.append(recv_one_or_none(self.sock[s]))
self.update_msgs(sec_since_boot(), msgs)
def update_msgs(self, cur_time, msgs):
# TODO: add optional input that specify the service to wait for
def update_msgs(self, cur_time: float, msgs: List[capnp.lib.capnp._DynamicStructReader]) -> None:
self.frame += 1
self.updated = dict.fromkeys(self.updated, False)
for msg in msgs:
@ -189,30 +198,28 @@ class SubMaster():
else:
self.alive[s] = True
def all_alive(self, service_list=None):
def all_alive(self, service_list=None) -> bool:
if service_list is None: # check all
service_list = self.alive.keys()
return all(self.alive[s] for s in service_list if s not in self.ignore_alive)
def all_valid(self, service_list=None):
def all_valid(self, service_list=None) -> bool:
if service_list is None: # check all
service_list = self.valid.keys()
return all(self.valid[s] for s in service_list)
def all_alive_and_valid(self, service_list=None):
def all_alive_and_valid(self, service_list=None) -> bool:
if service_list is None: # check all
service_list = self.alive.keys()
return self.all_alive(service_list=service_list) and self.all_valid(service_list=service_list)
class PubMaster():
def __init__(self, services):
def __init__(self, services: List[str]):
self.sock = {}
for s in services:
self.sock[s] = pub_sock(s)
def send(self, s, dat):
# accept either bytes or capnp builder
def send(self, s: str, dat: Union[bytes, capnp.lib.capnp._DynamicStructBuilder]) -> None:
if not isinstance(dat, bytes):
dat = dat.to_bytes()
self.sock[s].send(dat)

View File

@ -15,6 +15,18 @@ void sig_handler(int signal) {
msgq_do_exit = 1;
}
static size_t get_size(std::string endpoint){
size_t sz = DEFAULT_SEGMENT_SIZE;
#if !defined(QCOM) && !defined(QCOM2)
if (endpoint == "frame" || endpoint == "frontFrame" || endpoint == "wideFrame"){
sz *= 10;
}
#endif
return sz;
}
MSGQContext::MSGQContext() {
}
@ -49,13 +61,12 @@ MSGQMessage::~MSGQMessage() {
this->close();
}
int MSGQSubSocket::connect(Context *context, std::string endpoint, std::string address, bool conflate){
assert(context);
assert(address == "127.0.0.1");
q = new msgq_queue_t;
int r = msgq_new_queue(q, endpoint.c_str(), DEFAULT_SEGMENT_SIZE);
int r = msgq_new_queue(q, endpoint.c_str(), get_size(endpoint));
if (r != 0){
return r;
}
@ -143,7 +154,7 @@ int MSGQPubSocket::connect(Context *context, std::string endpoint){
assert(context);
q = new msgq_queue_t;
int r = msgq_new_queue(q, endpoint.c_str(), DEFAULT_SEGMENT_SIZE);
int r = msgq_new_queue(q, endpoint.c_str(), get_size(endpoint));
if (r != 0){
return r;
}

View File

@ -6,6 +6,10 @@
#include <capnp/serialize.h>
#include "../gen/cpp/log.capnp.h"
#ifdef __APPLE__
#define CLOCK_BOOTTIME CLOCK_MONOTONIC
#endif
#define MSG_MULTIPLE_PUBLISHERS 100
class Context {
@ -82,11 +86,34 @@ private:
std::map<std::string, SubMessage *> services_;
};
class MessageBuilder : public capnp::MallocMessageBuilder {
public:
MessageBuilder() = default;
cereal::Event::Builder initEvent(bool valid = true) {
cereal::Event::Builder event = initRoot<cereal::Event>();
struct timespec t;
clock_gettime(CLOCK_BOOTTIME, &t);
uint64_t current_time = t.tv_sec * 1000000000ULL + t.tv_nsec;
event.setLogMonoTime(current_time);
event.setValid(valid);
return event;
}
kj::ArrayPtr<capnp::byte> toBytes() {
heapArray_ = capnp::messageToFlatArray(*this);
return heapArray_.asBytes();
}
private:
kj::Array<capnp::word> heapArray_;
};
class PubMaster {
public:
PubMaster(const std::initializer_list<const char *> &service_list);
inline int send(const char *name, capnp::byte *data, size_t size) { return sockets_.at(name)->send((char *)data, size); }
int send(const char *name, capnp::MessageBuilder &msg);
int send(const char *name, MessageBuilder &msg);
~PubMaster();
private:

View File

@ -6,6 +6,7 @@ from distutils.core import Extension, setup # pylint: disable=import-error,no-n
from Cython.Build import cythonize
from Cython.Distutils import build_ext
TICI = os.path.isfile('/TICI')
def get_ext_filename_without_platform_suffix(filename):
name, ext = os.path.splitext(filename)
@ -30,11 +31,11 @@ class BuildExtWithoutPlatformSuffix(build_ext):
sourcefiles = ['messaging_pyx.pyx']
extra_compile_args = ["-std=c++14"]
extra_compile_args = ["-std=c++14", "-Wno-nullability-completeness"]
libraries = ['zmq']
ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg
if ARCH == "aarch64" and os.path.isdir("/system"):
if ARCH == "aarch64" and not TICI:
# android
extra_compile_args += ["-Wno-deprecated-register"]
libraries += ['gnustl_shared']

View File

@ -21,6 +21,8 @@
#include <stdio.h>
#include "services.h"
#include "msgq.hpp"
void sigusr2_handler(int signal) {
@ -81,11 +83,20 @@ void msgq_wait_for_subscriber(msgq_queue_t *q){
return;
}
bool service_exists(std::string path){
for (const auto& it : services) {
if (it.name == path) {
return true;
}
}
return false;
}
int msgq_new_queue(msgq_queue_t * q, const char * path, size_t size){
assert(size < 0xFFFFFFFF); // Buffer must be smaller than 2^32 bytes
if (!service_exists(std::string(path))){
std::cout << "Warning, " << std::string(path) << " is not in service list." << std::endl;
}
std::signal(SIGUSR2, sigusr2_handler);
const char * prefix = "/dev/shm/";
@ -102,15 +113,15 @@ int msgq_new_queue(msgq_queue_t * q, const char * path, size_t size){
delete[] full_path;
int rc = ftruncate(fd, size + sizeof(msgq_header_t));
if (rc < 0)
if (rc < 0){
return -1;
}
char * mem = (char*)mmap(NULL, size + sizeof(msgq_header_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (mem == NULL)
if (mem == NULL){
return -1;
}
q->mmap_p = mem;
msgq_header_t *header = (msgq_header_t *)mem;
@ -418,8 +429,6 @@ int msgq_msg_recv(msgq_msg_t * msg, msgq_queue_t * q){
int msgq_poll(msgq_pollitem_t * items, size_t nitems, int timeout){
assert(timeout >= 0);
int num = 0;
// Check if messages ready

View File

@ -3,10 +3,6 @@
#include "messaging.hpp"
#include "services.h"
#ifdef __APPLE__
#define CLOCK_BOOTTIME CLOCK_MONOTONIC
#endif
static inline uint64_t nanos_since_boot() {
struct timespec t;
clock_gettime(CLOCK_BOOTTIME, &t);
@ -164,9 +160,8 @@ PubMaster::PubMaster(const std::initializer_list<const char *> &service_list) {
}
}
int PubMaster::send(const char *name, capnp::MessageBuilder &msg) {
auto words = capnp::messageToFlatArray(msg);
auto bytes = words.asBytes();
int PubMaster::send(const char *name, MessageBuilder &msg) {
auto bytes = msg.toBytes();
return send(name, bytes.begin(), bytes.size());
}

View File

@ -78,6 +78,8 @@ frontFrame: [8072, true, 10.]
dMonitoringState: [8073, true, 5., 1]
offroadLayout: [8074, false, 0.]
wideEncodeIdx: [8075, true, 20.]
wideFrame: [8076, true, 20.]
modelV2: [8077, true, 20., 20]
testModel: [8040, false, 0.]
testLiveLocation: [8045, false, 0.]

View File

@ -1,286 +0,0 @@
import os
import binascii
import itertools
import re
import struct
import subprocess
import random
from cereal import log
NetworkType = log.ThermalData.NetworkType
NetworkStrength = log.ThermalData.NetworkStrength
ANDROID = os.path.isfile('/EON')
def get_sound_card_online():
return (os.path.isfile('/proc/asound/card0/state') and
open('/proc/asound/card0/state').read().strip() == 'ONLINE')
def getprop(key):
if not ANDROID:
return ""
return subprocess.check_output(["getprop", key], encoding='utf8').strip()
def get_imei(slot):
slot = str(slot)
if slot not in ("0", "1"):
raise ValueError("SIM slot must be 0 or 1")
ret = parse_service_call_string(service_call(["iphonesubinfo", "3" , "i32", str(slot)]))
if not ret:
# allow non android to be identified differently
ret = "%015d" % random.randint(0, 1 << 32)
return ret
def get_serial():
ret = getprop("ro.serialno")
if ret == "":
ret = "cccccccc"
return ret
def get_subscriber_info():
ret = parse_service_call_string(service_call(["iphonesubinfo", "7"]))
if ret is None or len(ret) < 8:
return ""
return ret
def reboot(reason=None):
if reason is None:
reason_args = ["null"]
else:
reason_args = ["s16", reason]
subprocess.check_output([
"service", "call", "power", "16", # IPowerManager.reboot
"i32", "0", # no confirmation,
*reason_args,
"i32", "1" # wait
])
def service_call(call):
if not ANDROID:
return None
ret = subprocess.check_output(["service", "call", *call], encoding='utf8').strip()
if 'Parcel' not in ret:
return None
return parse_service_call_bytes(ret)
def parse_service_call_unpack(r, fmt):
try:
return struct.unpack(fmt, r)[0]
except Exception:
return None
def parse_service_call_string(r):
try:
r = r[8:] # Cut off length field
r = r.decode('utf_16_be')
# All pairs of two characters seem to be swapped. Not sure why
result = ""
for a, b, in itertools.zip_longest(r[::2], r[1::2], fillvalue='\x00'):
result += b + a
result = result.replace('\x00', '')
return result
except Exception:
return None
def parse_service_call_bytes(ret):
try:
r = b""
for hex_part in re.findall(r'[ (]([0-9a-f]{8})', ret):
r += binascii.unhexlify(hex_part)
return r
except Exception:
return None
def get_network_type():
if not ANDROID:
return NetworkType.none
wifi_check = parse_service_call_string(service_call(["connectivity", "2"]))
if wifi_check is None:
return NetworkType.none
elif 'WIFI' in wifi_check:
return NetworkType.wifi
else:
cell_check = parse_service_call_unpack(service_call(['phone', '59']), ">q")
# from TelephonyManager.java
cell_networks = {
0: NetworkType.none,
1: NetworkType.cell2G,
2: NetworkType.cell2G,
3: NetworkType.cell3G,
4: NetworkType.cell2G,
5: NetworkType.cell3G,
6: NetworkType.cell3G,
7: NetworkType.cell3G,
8: NetworkType.cell3G,
9: NetworkType.cell3G,
10: NetworkType.cell3G,
11: NetworkType.cell2G,
12: NetworkType.cell3G,
13: NetworkType.cell4G,
14: NetworkType.cell4G,
15: NetworkType.cell3G,
16: NetworkType.cell2G,
17: NetworkType.cell3G,
18: NetworkType.cell4G,
19: NetworkType.cell4G
}
return cell_networks.get(cell_check, NetworkType.none)
def get_network_strength(network_type):
network_strength = NetworkStrength.unknown
# from SignalStrength.java
def get_lte_level(rsrp, rssnr):
INT_MAX = 2147483647
if rsrp == INT_MAX:
lvl_rsrp = NetworkStrength.unknown
elif rsrp >= -95:
lvl_rsrp = NetworkStrength.great
elif rsrp >= -105:
lvl_rsrp = NetworkStrength.good
elif rsrp >= -115:
lvl_rsrp = NetworkStrength.moderate
else:
lvl_rsrp = NetworkStrength.poor
if rssnr == INT_MAX:
lvl_rssnr = NetworkStrength.unknown
elif rssnr >= 45:
lvl_rssnr = NetworkStrength.great
elif rssnr >= 10:
lvl_rssnr = NetworkStrength.good
elif rssnr >= -30:
lvl_rssnr = NetworkStrength.moderate
else:
lvl_rssnr = NetworkStrength.poor
return max(lvl_rsrp, lvl_rssnr)
def get_tdscdma_level(tdscmadbm):
lvl = NetworkStrength.unknown
if tdscmadbm > -25:
lvl = NetworkStrength.unknown
elif tdscmadbm >= -49:
lvl = NetworkStrength.great
elif tdscmadbm >= -73:
lvl = NetworkStrength.good
elif tdscmadbm >= -97:
lvl = NetworkStrength.moderate
elif tdscmadbm >= -110:
lvl = NetworkStrength.poor
return lvl
def get_gsm_level(asu):
if asu <= 2 or asu == 99:
lvl = NetworkStrength.unknown
elif asu >= 12:
lvl = NetworkStrength.great
elif asu >= 8:
lvl = NetworkStrength.good
elif asu >= 5:
lvl = NetworkStrength.moderate
else:
lvl = NetworkStrength.poor
return lvl
def get_evdo_level(evdodbm, evdosnr):
lvl_evdodbm = NetworkStrength.unknown
lvl_evdosnr = NetworkStrength.unknown
if evdodbm >= -65:
lvl_evdodbm = NetworkStrength.great
elif evdodbm >= -75:
lvl_evdodbm = NetworkStrength.good
elif evdodbm >= -90:
lvl_evdodbm = NetworkStrength.moderate
elif evdodbm >= -105:
lvl_evdodbm = NetworkStrength.poor
if evdosnr >= 7:
lvl_evdosnr = NetworkStrength.great
elif evdosnr >= 5:
lvl_evdosnr = NetworkStrength.good
elif evdosnr >= 3:
lvl_evdosnr = NetworkStrength.moderate
elif evdosnr >= 1:
lvl_evdosnr = NetworkStrength.poor
return max(lvl_evdodbm, lvl_evdosnr)
def get_cdma_level(cdmadbm, cdmaecio):
lvl_cdmadbm = NetworkStrength.unknown
lvl_cdmaecio = NetworkStrength.unknown
if cdmadbm >= -75:
lvl_cdmadbm = NetworkStrength.great
elif cdmadbm >= -85:
lvl_cdmadbm = NetworkStrength.good
elif cdmadbm >= -95:
lvl_cdmadbm = NetworkStrength.moderate
elif cdmadbm >= -100:
lvl_cdmadbm = NetworkStrength.poor
if cdmaecio >= -90:
lvl_cdmaecio = NetworkStrength.great
elif cdmaecio >= -110:
lvl_cdmaecio = NetworkStrength.good
elif cdmaecio >= -130:
lvl_cdmaecio = NetworkStrength.moderate
elif cdmaecio >= -150:
lvl_cdmaecio = NetworkStrength.poor
return max(lvl_cdmadbm, lvl_cdmaecio)
if network_type == NetworkType.none:
return network_strength
if network_type == NetworkType.wifi:
out = subprocess.check_output('dumpsys connectivity', shell=True).decode('utf-8')
network_strength = NetworkStrength.unknown
for line in out.split('\n'):
signal_str = "SignalStrength: "
if signal_str in line:
lvl_idx_start = line.find(signal_str) + len(signal_str)
lvl_idx_end = line.find(']', lvl_idx_start)
lvl = int(line[lvl_idx_start : lvl_idx_end])
if lvl >= -50:
network_strength = NetworkStrength.great
elif lvl >= -60:
network_strength = NetworkStrength.good
elif lvl >= -70:
network_strength = NetworkStrength.moderate
else:
network_strength = NetworkStrength.poor
return network_strength
else:
# check cell strength
out = subprocess.check_output('dumpsys telephony.registry', shell=True).decode('utf-8')
for line in out.split('\n'):
if "mSignalStrength" in line:
arr = line.split(' ')
ns = 0
if ("gsm" in arr[14]):
rsrp = int(arr[9])
rssnr = int(arr[11])
ns = get_lte_level(rsrp, rssnr)
if ns == NetworkStrength.unknown:
tdscmadbm = int(arr[13])
ns = get_tdscdma_level(tdscmadbm)
if ns == NetworkStrength.unknown:
asu = int(arr[1])
ns = get_gsm_level(asu)
else:
cdmadbm = int(arr[3])
cdmaecio = int(arr[4])
evdodbm = int(arr[5])
evdosnr = int(arr[7])
lvl_cdma = get_cdma_level(cdmadbm, cdmaecio)
lvl_edmo = get_evdo_level(evdodbm, evdosnr)
if lvl_edmo == NetworkStrength.unknown:
ns = lvl_cdma
elif lvl_cdma == NetworkStrength.unknown:
ns = lvl_edmo
else:
ns = min(lvl_cdma, lvl_edmo)
network_strength = max(network_strength, ns)
return network_strength

View File

@ -1,10 +1,10 @@
import os
BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../"))
from common.android import ANDROID
if ANDROID:
PERSIST = "/persist"
PARAMS = "/data/params"
else:
from common.hardware import PC
if PC:
PERSIST = os.path.join(BASEDIR, "persist")
PARAMS = os.path.join(BASEDIR, "persist", "params")
else:
PERSIST = "/persist"
PARAMS = "/data/params"

22
common/gpio.py 100644
View File

@ -0,0 +1,22 @@
GPIO_HUB_RST_N = 30
GPIO_UBLOX_RST_N = 32
GPIO_UBLOX_SAFEBOOT_N = 33
GPIO_UBLOX_PWR_EN = 34
GPIO_STM_RST_N = 124
GPIO_STM_BOOT0 = 134
def gpio_init(pin, output):
try:
with open(f"/sys/class/gpio/gpio{pin}/direction", 'wb') as f:
f.write(b"out" if output else b"in")
except Exception as e:
print(f"Failed to set gpio {pin} direction: {e}")
def gpio_set(pin, high):
try:
with open(f"/sys/class/gpio/gpio{pin}/value", 'wb') as f:
f.write(b"1" if high else b"0")
except Exception as e:
print(f"Failed to set gpio {pin} value: {e}")

57
common/hardware.py 100644
View File

@ -0,0 +1,57 @@
import os
import random
from typing import cast
from cereal import log
from common.hardware_android import Android
from common.hardware_tici import Tici
from common.hardware_base import HardwareBase
EON = os.path.isfile('/EON')
TICI = os.path.isfile('/TICI')
PC = not (EON or TICI)
ANDROID = EON
NetworkType = log.ThermalData.NetworkType
NetworkStrength = log.ThermalData.NetworkStrength
class Pc(HardwareBase):
def get_sound_card_online(self):
return True
def get_imei(self, slot):
return "%015d" % random.randint(0, 1 << 32)
def get_serial(self):
return "cccccccc"
def get_subscriber_info(self):
return ""
def reboot(self, reason=None):
print("REBOOT!")
def get_network_type(self):
return NetworkType.wifi
def get_sim_info(self):
return {
'sim_id': '',
'mcc_mnc': None,
'network_type': ["Unknown"],
'sim_state': ["ABSENT"],
'data_connected': False
}
def get_network_strength(self, network_type):
return NetworkStrength.unknown
if EON:
HARDWARE = cast(HardwareBase, Android())
elif TICI:
HARDWARE = cast(HardwareBase, Tici())
else:
HARDWARE = cast(HardwareBase, Pc())

View File

@ -0,0 +1,302 @@
import binascii
import itertools
import os
import re
import struct
import subprocess
from cereal import log
from common.hardware_base import HardwareBase
NetworkType = log.ThermalData.NetworkType
NetworkStrength = log.ThermalData.NetworkStrength
def service_call(call):
try:
ret = subprocess.check_output(["service", "call", *call], encoding='utf8').strip()
if 'Parcel' not in ret:
return None
return parse_service_call_bytes(ret)
except subprocess.CalledProcessError:
return None
def parse_service_call_unpack(r, fmt):
try:
return struct.unpack(fmt, r)[0]
except Exception:
return None
def parse_service_call_string(r):
try:
r = r[8:] # Cut off length field
r = r.decode('utf_16_be')
# All pairs of two characters seem to be swapped. Not sure why
result = ""
for a, b, in itertools.zip_longest(r[::2], r[1::2], fillvalue='\x00'):
result += b + a
result = result.replace('\x00', '')
return result
except Exception:
return None
def parse_service_call_bytes(ret):
try:
r = b""
for hex_part in re.findall(r'[ (]([0-9a-f]{8})', ret):
r += binascii.unhexlify(hex_part)
return r
except Exception:
return None
def getprop(key):
return subprocess.check_output(["getprop", key], encoding='utf8').strip()
class Android(HardwareBase):
def get_sound_card_online(self):
return (os.path.isfile('/proc/asound/card0/state') and
open('/proc/asound/card0/state').read().strip() == 'ONLINE')
def get_imei(self, slot):
slot = str(slot)
if slot not in ("0", "1"):
raise ValueError("SIM slot must be 0 or 1")
return parse_service_call_string(service_call(["iphonesubinfo", "3", "i32", str(slot)]))
def get_serial(self):
ret = getprop("ro.serialno")
if ret == "":
ret = "cccccccc"
return ret
def get_subscriber_info(self):
ret = parse_service_call_string(service_call(["iphonesubinfo", "7"]))
if ret is None or len(ret) < 8:
return ""
return ret
def reboot(self, reason=None):
# e.g. reason="recovery" to go into recover mode
if reason is None:
reason_args = ["null"]
else:
reason_args = ["s16", reason]
subprocess.check_output([
"service", "call", "power", "16", # IPowerManager.reboot
"i32", "0", # no confirmation,
*reason_args,
"i32", "1" # wait
])
def get_sim_info(self):
# Used for athena
# TODO: build using methods from this class
sim_state = getprop("gsm.sim.state").split(",")
network_type = getprop("gsm.network.type").split(',')
mcc_mnc = getprop("gsm.sim.operator.numeric") or None
sim_id = parse_service_call_string(service_call(['iphonesubinfo', '11']))
cell_data_state = parse_service_call_unpack(service_call(['phone', '46']), ">q")
cell_data_connected = (cell_data_state == 2)
return {
'sim_id': sim_id,
'mcc_mnc': mcc_mnc,
'network_type': network_type,
'sim_state': sim_state,
'data_connected': cell_data_connected
}
def get_network_type(self):
wifi_check = parse_service_call_string(service_call(["connectivity", "2"]))
if wifi_check is None:
return NetworkType.none
elif 'WIFI' in wifi_check:
return NetworkType.wifi
else:
cell_check = parse_service_call_unpack(service_call(['phone', '59']), ">q")
# from TelephonyManager.java
cell_networks = {
0: NetworkType.none,
1: NetworkType.cell2G,
2: NetworkType.cell2G,
3: NetworkType.cell3G,
4: NetworkType.cell2G,
5: NetworkType.cell3G,
6: NetworkType.cell3G,
7: NetworkType.cell3G,
8: NetworkType.cell3G,
9: NetworkType.cell3G,
10: NetworkType.cell3G,
11: NetworkType.cell2G,
12: NetworkType.cell3G,
13: NetworkType.cell4G,
14: NetworkType.cell4G,
15: NetworkType.cell3G,
16: NetworkType.cell2G,
17: NetworkType.cell3G,
18: NetworkType.cell4G,
19: NetworkType.cell4G
}
return cell_networks.get(cell_check, NetworkType.none)
def get_network_strength(self, network_type):
network_strength = NetworkStrength.unknown
# from SignalStrength.java
def get_lte_level(rsrp, rssnr):
INT_MAX = 2147483647
if rsrp == INT_MAX:
lvl_rsrp = NetworkStrength.unknown
elif rsrp >= -95:
lvl_rsrp = NetworkStrength.great
elif rsrp >= -105:
lvl_rsrp = NetworkStrength.good
elif rsrp >= -115:
lvl_rsrp = NetworkStrength.moderate
else:
lvl_rsrp = NetworkStrength.poor
if rssnr == INT_MAX:
lvl_rssnr = NetworkStrength.unknown
elif rssnr >= 45:
lvl_rssnr = NetworkStrength.great
elif rssnr >= 10:
lvl_rssnr = NetworkStrength.good
elif rssnr >= -30:
lvl_rssnr = NetworkStrength.moderate
else:
lvl_rssnr = NetworkStrength.poor
return max(lvl_rsrp, lvl_rssnr)
def get_tdscdma_level(tdscmadbm):
lvl = NetworkStrength.unknown
if tdscmadbm > -25:
lvl = NetworkStrength.unknown
elif tdscmadbm >= -49:
lvl = NetworkStrength.great
elif tdscmadbm >= -73:
lvl = NetworkStrength.good
elif tdscmadbm >= -97:
lvl = NetworkStrength.moderate
elif tdscmadbm >= -110:
lvl = NetworkStrength.poor
return lvl
def get_gsm_level(asu):
if asu <= 2 or asu == 99:
lvl = NetworkStrength.unknown
elif asu >= 12:
lvl = NetworkStrength.great
elif asu >= 8:
lvl = NetworkStrength.good
elif asu >= 5:
lvl = NetworkStrength.moderate
else:
lvl = NetworkStrength.poor
return lvl
def get_evdo_level(evdodbm, evdosnr):
lvl_evdodbm = NetworkStrength.unknown
lvl_evdosnr = NetworkStrength.unknown
if evdodbm >= -65:
lvl_evdodbm = NetworkStrength.great
elif evdodbm >= -75:
lvl_evdodbm = NetworkStrength.good
elif evdodbm >= -90:
lvl_evdodbm = NetworkStrength.moderate
elif evdodbm >= -105:
lvl_evdodbm = NetworkStrength.poor
if evdosnr >= 7:
lvl_evdosnr = NetworkStrength.great
elif evdosnr >= 5:
lvl_evdosnr = NetworkStrength.good
elif evdosnr >= 3:
lvl_evdosnr = NetworkStrength.moderate
elif evdosnr >= 1:
lvl_evdosnr = NetworkStrength.poor
return max(lvl_evdodbm, lvl_evdosnr)
def get_cdma_level(cdmadbm, cdmaecio):
lvl_cdmadbm = NetworkStrength.unknown
lvl_cdmaecio = NetworkStrength.unknown
if cdmadbm >= -75:
lvl_cdmadbm = NetworkStrength.great
elif cdmadbm >= -85:
lvl_cdmadbm = NetworkStrength.good
elif cdmadbm >= -95:
lvl_cdmadbm = NetworkStrength.moderate
elif cdmadbm >= -100:
lvl_cdmadbm = NetworkStrength.poor
if cdmaecio >= -90:
lvl_cdmaecio = NetworkStrength.great
elif cdmaecio >= -110:
lvl_cdmaecio = NetworkStrength.good
elif cdmaecio >= -130:
lvl_cdmaecio = NetworkStrength.moderate
elif cdmaecio >= -150:
lvl_cdmaecio = NetworkStrength.poor
return max(lvl_cdmadbm, lvl_cdmaecio)
if network_type == NetworkType.none:
return network_strength
if network_type == NetworkType.wifi:
out = subprocess.check_output('dumpsys connectivity', shell=True).decode('utf-8')
network_strength = NetworkStrength.unknown
for line in out.split('\n'):
signal_str = "SignalStrength: "
if signal_str in line:
lvl_idx_start = line.find(signal_str) + len(signal_str)
lvl_idx_end = line.find(']', lvl_idx_start)
lvl = int(line[lvl_idx_start : lvl_idx_end])
if lvl >= -50:
network_strength = NetworkStrength.great
elif lvl >= -60:
network_strength = NetworkStrength.good
elif lvl >= -70:
network_strength = NetworkStrength.moderate
else:
network_strength = NetworkStrength.poor
return network_strength
else:
# check cell strength
out = subprocess.check_output('dumpsys telephony.registry', shell=True).decode('utf-8')
for line in out.split('\n'):
if "mSignalStrength" in line:
arr = line.split(' ')
ns = 0
if ("gsm" in arr[14]):
rsrp = int(arr[9])
rssnr = int(arr[11])
ns = get_lte_level(rsrp, rssnr)
if ns == NetworkStrength.unknown:
tdscmadbm = int(arr[13])
ns = get_tdscdma_level(tdscmadbm)
if ns == NetworkStrength.unknown:
asu = int(arr[1])
ns = get_gsm_level(asu)
else:
cdmadbm = int(arr[3])
cdmaecio = int(arr[4])
evdodbm = int(arr[5])
evdosnr = int(arr[7])
lvl_cdma = get_cdma_level(cdmadbm, cdmaecio)
lvl_edmo = get_evdo_level(evdodbm, evdosnr)
if lvl_edmo == NetworkStrength.unknown:
ns = lvl_cdma
elif lvl_cdma == NetworkStrength.unknown:
ns = lvl_edmo
else:
ns = min(lvl_cdma, lvl_edmo)
network_strength = max(network_strength, ns)
return network_strength

View File

@ -0,0 +1,41 @@
from abc import abstractmethod
class HardwareBase:
@staticmethod
def get_cmdline():
with open('/proc/cmdline') as f:
cmdline = f.read()
return {kv[0]: kv[1] for kv in [s.split('=') for s in cmdline.split(' ')] if len(kv) == 2}
@abstractmethod
def get_sound_card_online(self):
pass
@abstractmethod
def get_imei(self, slot):
pass
@abstractmethod
def get_serial(self):
pass
@abstractmethod
def get_subscriber_info(self):
pass
@abstractmethod
def reboot(self, reason=None):
pass
@abstractmethod
def get_network_type(self):
pass
@abstractmethod
def get_sim_info(self):
pass
@abstractmethod
def get_network_strength(self, network_type):
pass

View File

@ -0,0 +1,58 @@
import serial
from common.hardware_base import HardwareBase
from cereal import log
NetworkType = log.ThermalData.NetworkType
NetworkStrength = log.ThermalData.NetworkStrength
def run_at_command(cmd, timeout=0.1):
with serial.Serial("/dev/ttyUSB2", timeout=timeout) as ser:
ser.write(cmd + b"\r\n")
ser.readline() # Modem echos request
return ser.readline().decode().rstrip()
class Tici(HardwareBase):
def get_sound_card_online(self):
return True
def get_imei(self, slot):
if slot != 0:
return ""
for _ in range(10):
try:
imei = run_at_command(b"AT+CGSN")
if len(imei) == 15:
return imei
except serial.SerialException:
pass
raise RuntimeError("Error getting IMEI")
def get_serial(self):
return self.get_cmdline()['androidboot.serialno']
def get_subscriber_info(self):
return ""
def reboot(self, reason=None):
print("REBOOT!")
def get_network_type(self):
return NetworkType.wifi
def get_sim_info(self):
return {
'sim_id': '',
'mcc_mnc': None,
'network_type': ["Unknown"],
'sim_state': ["ABSENT"],
'data_connected': False
}
def get_network_strength(self, network_type):
return NetworkStrength.unknown

View File

@ -53,12 +53,12 @@ keys = {
"AccessToken": [TxType.CLEAR_ON_MANAGER_START],
"AthenadPid": [TxType.PERSISTENT],
"CalibrationParams": [TxType.PERSISTENT],
"CarBatteryCapacity": [TxType.PERSISTENT],
"CarParams": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"CarParamsCache": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"CarVin": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"CommunityFeaturesToggle": [TxType.PERSISTENT],
"CompletedTrainingVersion": [TxType.PERSISTENT],
"ControlsParams": [TxType.PERSISTENT],
"DisablePowerDown": [TxType.PERSISTENT],
"DisableUpdates": [TxType.PERSISTENT],
"DoUninstall": [TxType.CLEAR_ON_MANAGER_START],
@ -71,7 +71,6 @@ keys = {
"HasCompletedSetup": [TxType.PERSISTENT],
"IsDriverViewEnabled": [TxType.CLEAR_ON_MANAGER_START],
"IsLdwEnabled": [TxType.PERSISTENT],
"IsGeofenceEnabled": [TxType.PERSISTENT],
"IsMetric": [TxType.PERSISTENT],
"IsOffroad": [TxType.CLEAR_ON_MANAGER_START],
"IsRHD": [TxType.PERSISTENT],
@ -81,10 +80,7 @@ keys = {
"LastAthenaPingTime": [TxType.PERSISTENT],
"LastUpdateTime": [TxType.PERSISTENT],
"LastUpdateException": [TxType.PERSISTENT],
"LimitSetSpeed": [TxType.PERSISTENT],
"LimitSetSpeedNeural": [TxType.PERSISTENT],
"LiveParameters": [TxType.PERSISTENT],
"LongitudinalControl": [TxType.PERSISTENT],
"OpenpilotEnabledToggle": [TxType.PERSISTENT],
"LaneChangeEnabled": [TxType.PERSISTENT],
"PandaFirmware": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
@ -94,7 +90,6 @@ keys = {
"RecordFront": [TxType.PERSISTENT],
"ReleaseNotes": [TxType.PERSISTENT],
"ShouldDoUpdate": [TxType.CLEAR_ON_MANAGER_START],
"SpeedLimitOffset": [TxType.PERSISTENT],
"SubscriberInfo": [TxType.PERSISTENT],
"TermsVersion": [TxType.PERSISTENT],
"TrainingVersion": [TxType.PERSISTENT],
@ -122,14 +117,15 @@ def fsync_dir(path):
class FileLock():
def __init__(self, path, create):
def __init__(self, path, create, lock_ex):
self._path = path
self._create = create
self._fd = None
self._lock_ex = lock_ex
def acquire(self):
self._fd = os.open(self._path, os.O_CREAT if self._create else 0)
fcntl.flock(self._fd, fcntl.LOCK_EX)
fcntl.flock(self._fd, fcntl.LOCK_EX if self._lock_ex else fcntl.LOCK_SH)
def release(self):
if self._fd is not None:
@ -157,8 +153,8 @@ class DBAccessor():
except KeyError:
return None
def _get_lock(self, create):
lock = FileLock(os.path.join(self._path, ".lock"), create)
def _get_lock(self, create, lock_ex):
lock = FileLock(os.path.join(self._path, ".lock"), create, lock_ex)
lock.acquire()
return lock
@ -190,7 +186,7 @@ class DBAccessor():
class DBReader(DBAccessor):
def __enter__(self):
try:
lock = self._get_lock(False)
lock = self._get_lock(False, False)
except OSError as e:
# Do not create lock if it does not exist.
if e.errno == errno.ENOENT:
@ -228,7 +224,7 @@ class DBWriter(DBAccessor):
try:
os.chmod(self._path, 0o777)
self._lock = self._get_lock(True)
self._lock = self._get_lock(True, True)
self._vals = self._read_values_locked()
except Exception:
os.umask(self._prev_umask)
@ -317,7 +313,7 @@ def write_db(params_path, key, value):
value = value.encode('utf8')
prev_umask = os.umask(0)
lock = FileLock(params_path + "/.lock", True)
lock = FileLock(params_path + "/.lock", True, True)
lock.acquire()
try:

View File

@ -1,12 +1,10 @@
"""Utilities for reading real time clocks and keeping soft real time constraints."""
import gc
import os
import time
import platform
import subprocess
import multiprocessing
from cffi import FFI
from common.android import ANDROID
from common.hardware import PC
from common.common_pyx import sec_since_boot # pylint: disable=no-name-in-module, import-error
@ -17,37 +15,26 @@ DT_DMON = 0.1 # driver monitoring
DT_TRML = 0.5 # thermald and manager
ffi = FFI()
ffi.cdef("long syscall(long number, ...);")
libc = ffi.dlopen(None)
def _get_tid():
if platform.machine() == "x86_64":
NR_gettid = 186
elif platform.machine() == "aarch64":
NR_gettid = 178
else:
raise NotImplementedError
return libc.syscall(NR_gettid)
class Priority:
MIN_REALTIME = 52 # highest android process priority is 51
CTRL_LOW = MIN_REALTIME
CTRL_HIGH = MIN_REALTIME + 1
def set_realtime_priority(level):
if os.getuid() != 0:
print("not setting priority, not root")
return
if not PC:
os.sched_setscheduler(0, os.SCHED_FIFO, os.sched_param(level))
return subprocess.call(['chrt', '-f', '-p', str(level), str(_get_tid())])
def set_core_affinity(core):
if os.getuid() != 0:
print("not setting affinity, not root")
return
if not PC:
os.sched_setaffinity(0, [core,])
if ANDROID:
return subprocess.call(['taskset', '-p', str(core), str(_get_tid())])
else:
return -1
def config_rt_process(core, priority):
gc.disable()
set_realtime_priority(priority)
set_core_affinity(core)
class Ratekeeper():

View File

@ -5,7 +5,7 @@ import subprocess
from common.basedir import BASEDIR
class TextWindow():
class TextWindow:
def __init__(self, s, noop=False):
# text window is only implemented for android currently
self.text_proc = None

View File

@ -8,6 +8,60 @@ source "$BASEDIR/launch_env.sh"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
function two_init {
# Restrict Android and other system processes to the first two cores
echo 0-1 > /dev/cpuset/background/cpus
echo 0-1 > /dev/cpuset/system-background/cpus
echo 0-1 > /dev/cpuset/foreground/boost/cpus
echo 0-1 > /dev/cpuset/foreground/cpus
echo 0-1 > /dev/cpuset/android/cpus
# openpilot gets all the cores
echo 0-3 > /dev/cpuset/app/cpus
# Collect RIL and other possibly long-running I/O interrupts onto CPU 1
echo 1 > /proc/irq/78/smp_affinity_list # qcom,smd-modem (LTE radio)
echo 1 > /proc/irq/33/smp_affinity_list # ufshcd (flash storage)
echo 1 > /proc/irq/35/smp_affinity_list # wifi (wlan_pci)
# USB traffic needs realtime handling on cpu 3
[ -d "/proc/irq/733" ] && echo 3 > /proc/irq/733/smp_affinity_list # USB for LeEco
[ -d "/proc/irq/736" ] && echo 3 > /proc/irq/736/smp_affinity_list # USB for OP3T
# Check for NEOS update
if [ $(< /VERSION) != "$REQUIRED_NEOS_VERSION" ]; then
if [ -f "$DIR/scripts/continue.sh" ]; then
cp "$DIR/scripts/continue.sh" "/data/data/com.termux/files/continue.sh"
fi
if [ ! -f "$BASEDIR/prebuilt" ]; then
# Clean old build products, but preserve the scons cache
cd $DIR
scons --clean
git clean -xdf
git submodule foreach --recursive git clean -xdf
fi
"$DIR/installer/updater/updater" "file://$DIR/installer/updater/update.json"
else
if [[ $(uname -v) == "#1 SMP PREEMPT Wed Jun 10 12:40:53 PDT 2020" ]]; then
"$DIR/installer/updater/updater" "file://$DIR/installer/updater/update_kernel.json"
fi
fi
# One-time fix for a subset of OP3T with gyro orientation offsets.
# Remove and regenerate qcom sensor registry. Only done on OP3T mainboards.
# Performed exactly once. The old registry is preserved just-in-case, and
# doubles as a flag denoting we've already done the reset.
if ! $(grep -q "letv" /proc/cmdline) && [ ! -f "/persist/comma/op3t-sns-reg-backup" ]; then
echo "Performing OP3T sensor registry reset"
mv /persist/sensors/sns.reg /persist/comma/op3t-sns-reg-backup &&
rm -f /persist/sensors/sensors_settings /persist/sensors/error_log /persist/sensors/gyro_sensitity_cal &&
echo "restart" > /sys/kernel/debug/msm_subsys/slpi &&
sleep 5 # Give Android sensor subsystem a moment to recover
fi
}
function launch {
# Wifi scan
wpa_cli IFNAME=wlan0 SCAN
@ -54,56 +108,9 @@ function launch {
fi
fi
# Android and other system processes are not permitted to run on CPU 3
# NEOS installed app processes can run anywhere
echo 0-2 > /dev/cpuset/background/cpus
echo 0-2 > /dev/cpuset/system-background/cpus
[ -d "/dev/cpuset/foreground/boost/cpus" ] && echo 0-2 > /dev/cpuset/foreground/boost/cpus # Not present in < NEOS 15
echo 0-2 > /dev/cpuset/foreground/cpus
echo 0-2 > /dev/cpuset/android/cpus
echo 0-3 > /dev/cpuset/app/cpus
# Collect RIL and other possibly long-running I/O interrupts onto CPU 1
echo 1 > /proc/irq/78/smp_affinity_list # qcom,smd-modem (LTE radio)
echo 1 > /proc/irq/33/smp_affinity_list # ufshcd (flash storage)
echo 1 > /proc/irq/35/smp_affinity_list # wifi (wlan_pci)
# USB traffic needs realtime handling on cpu 3
[ -d "/proc/irq/733" ] && echo 3 > /proc/irq/733/smp_affinity_list # USB for LeEco
[ -d "/proc/irq/736" ] && echo 3 > /proc/irq/736/smp_affinity_list # USB for OP3T
# Check for NEOS update
if [ $(< /VERSION) != "$REQUIRED_NEOS_VERSION" ]; then
if [ -f "$DIR/scripts/continue.sh" ]; then
cp "$DIR/scripts/continue.sh" "/data/data/com.termux/files/continue.sh"
fi
if [ ! -f "$BASEDIR/prebuilt" ]; then
# Clean old build products, but preserve the scons cache
cd $DIR
scons --clean
git clean -xdf
git submodule foreach --recursive git clean -xdf
fi
"$DIR/installer/updater/updater" "file://$DIR/installer/updater/update.json"
else
if [[ $(uname -v) == "#1 SMP PREEMPT Wed Jun 10 12:40:53 PDT 2020" ]]; then
"$DIR/installer/updater/updater" "file://$DIR/installer/updater/update_kernel.json"
fi
fi
# One-time fix for a subset of OP3T with gyro orientation offsets.
# Remove and regenerate qcom sensor registry. Only done on OP3T mainboards.
# Performed exactly once. The old registry is preserved just-in-case, and
# doubles as a flag denoting we've already done the reset.
# TODO: we should really grow per-platform detect and setup routines
if ! $(grep -q "letv" /proc/cmdline) && [ ! -f "/persist/comma/op3t-sns-reg-backup" ]; then
echo "Performing OP3T sensor registry reset"
mv /persist/sensors/sns.reg /persist/comma/op3t-sns-reg-backup &&
rm -f /persist/sensors/sensors_settings /persist/sensors/error_log /persist/sensors/gyro_sensitity_cal &&
echo "restart" > /sys/kernel/debug/msm_subsys/slpi &&
sleep 5 # Give Android sensor subsystem a moment to recover
# comma two init
if [ -f /EON ]; then
two_init
fi
# handle pythonpath

View File

@ -34,7 +34,7 @@ class BuildExtWithoutPlatformSuffix(build_ext):
return get_ext_filename_without_platform_suffix(filename)
extra_compile_args = ["-std=c++14"]
extra_compile_args = ["-std=c++14", "-Wno-nullability-completeness"]
ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg
if ARCH == "aarch64":
extra_compile_args += ["-Wno-deprecated-register"]

View File

@ -20,9 +20,11 @@ cdef class CANPacker:
map[int, int] address_to_size
def __init__(self, dbc_name):
self.packer = new cpp_CANPacker(dbc_name)
self.dbc = dbc_lookup(dbc_name)
if not self.dbc:
raise RuntimeError("Can't lookup" + dbc_name)
self.packer = new cpp_CANPacker(dbc_name)
num_msgs = self.dbc[0].num_msgs
for i in range(num_msgs):
msg = self.dbc[0].msgs[i]
@ -37,7 +39,7 @@ cdef class CANPacker:
for name, value in values.iteritems():
n = name.encode('utf8')
names.append(n) # TODO: find better way to keep reference to temp string arround
names.append(n) # TODO: find better way to keep reference to temp string around
spv.name = n
spv.value = value

View File

@ -187,7 +187,7 @@ void CANParser::UpdateCans(uint64_t sec, const capnp::List<cereal::CanData>::Rea
continue;
}
if (cmsg.getDat().size() > 8) continue; //shouldnt ever happen
if (cmsg.getDat().size() > 8) continue; //shouldn't ever happen
uint8_t dat[8] = {0};
memcpy(dat, cmsg.getDat().begin(), cmsg.getDat().size());

View File

@ -1,2 +1,2 @@
from opendbc.can.parser_pyx import CANParser # pylint: disable=no-name-in-module, import-error
assert CANParser
from opendbc.can.parser_pyx import CANParser, CANDefine # pylint: disable=no-name-in-module, import-error
assert CANParser, CANDefine

View File

@ -17,7 +17,6 @@ from collections import defaultdict
cdef int CAN_INVALID_CNT = 5
cdef class CANParser:
cdef:
cpp_CANParser *can
@ -37,10 +36,11 @@ cdef class CANParser:
def __init__(self, dbc_name, signals, checks=None, bus=0):
if checks is None:
checks = []
self.can_valid = True
self.dbc_name = dbc_name
self.dbc = dbc_lookup(dbc_name)
if not self.dbc:
raise RuntimeError("Can't lookup" + dbc_name)
self.vl = {}
self.ts = {}
@ -110,7 +110,7 @@ cdef class CANParser:
for cv in can_values:
# Cast char * directly to unicde
# Cast char * directly to unicode
name = <unicode>self.address_to_msg_name[cv.address].c_str()
cv_name = <unicode>cv.name
@ -148,7 +148,9 @@ cdef class CANDefine():
def __init__(self, dbc_name):
self.dbc_name = dbc_name
self.dbc = dbc_lookup(dbc_name)
if not self.dbc:
raise RuntimeError("Can't lookup" + dbc_name)
num_vals = self.dbc[0].num_vals
address_to_msg_name = {}

View File

@ -81,7 +81,7 @@ def process(in_fn, out_fn):
if sig.start_bit % 8 != checksum_start_bit:
sys.exit("%s: CHECKSUM starts at wrong bit" % dbc_msg_name)
if little_endian != sig.is_little_endian:
sys.exit("%s: CHECKSUM has wrong endianess" % dbc_msg_name)
sys.exit("%s: CHECKSUM has wrong endianness" % dbc_msg_name)
# counter rules
if sig.name == "COUNTER":
if counter_size is not None and sig.size != counter_size:
@ -90,7 +90,7 @@ def process(in_fn, out_fn):
print(counter_start_bit, sig.start_bit)
sys.exit("%s: COUNTER starts at wrong bit" % dbc_msg_name)
if little_endian != sig.is_little_endian:
sys.exit("%s: COUNTER has wrong endianess" % dbc_msg_name)
sys.exit("%s: COUNTER has wrong endianness" % dbc_msg_name)
# pedal rules
if address in [0x200, 0x201]:
if sig.name == "COUNTER_PEDAL" and sig.size != 4:

View File

@ -409,7 +409,7 @@ CM_ SG_ 571 CHECKSUM "standard checksum";
CM_ SG_ 825 BEEP_339 "sent every 0.5s. 0050 is no beep. To beep send 4355 or 4155. Used by ParkSense warning.";
CM_ SG_ 270 ELECTRIC_MOTOR "0x7fff indicates electric motor not in use";
CM_ SG_ 291 ENERGY_GAIN_LOSS "unsure what this actually is";
CM_ SG_ 291 ENERGY_SMOOTHER_CURVE "unusre what it is, but smoother";
CM_ SG_ 291 ENERGY_SMOOTHER_CURVE "unsure what it is, but smoother";
CM_ SG_ 308 ACCEL_134 "only set when human presses accel pedal";
CM_ SG_ 532 NOISY_SLOWLY_DECREASING "perhaps battery but do not know";
CM_ SG_ 816 TRACTION_OFF "set when traction off button is enabled";

View File

@ -37,7 +37,7 @@ BU_: K109_FCM B233B_LRR NEO VIS_FO VIS2_FO K124_ASCM Vector__XXX EOCM_F_FO EOCM2
VAL_TABLE_ RangeMode 1 "Active" 0 "Inactive" ;
VAL_TABLE_ TrkConf 3 "Confident" 2 "Speculative" 1 "Highly speculative" 0 "Invalid" ;
VAL_TABLE_ TrkMeasStatus 3 "Measured current cycle" 2 "Latent track not detected" 1 "New object" 0 "No object" ;
VAL_TABLE_ TrkDynProp 4 "Moving in opposite direction" 3 "Moving in same direction" 2 "Has moved but currenty stopped" 1 "Has never moved," 0 "Unkown" ;
VAL_TABLE_ TrkDynProp 4 "Moving in opposite direction" 3 "Moving in same direction" 2 "Has moved but currently stopped" 1 "Has never moved," 0 "Unknown" ;
VAL_TABLE_ FrntVsnInPthVehBrkNwSt 10 "Active" 5 "Inactive" ;
VAL_TABLE_ FrntVsnClostPedBrkNwSt 10 "Active" 5 "Inactive" ;
VAL_TABLE_ LaneSnsLLnPosValid 1 "Invalid" 0 "Valid" ;

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";
@ -375,7 +375,7 @@ BO_ 705 GAS_PEDAL: 8 XXX
SG_ GAS_PEDAL : 55|8@0+ (0.005,0) [0|1] "" XXX
BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
SG_ STEER_TORQUE_EPS : 47|16@0- (1.0,0) [-20000|20000] "" XXX
SG_ STEER_TORQUE_EPS : 47|16@0- (0.88,0) [-20000|20000] "" XXX
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -328,7 +328,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -328,7 +328,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -311,7 +311,7 @@ CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd";
CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set";
CM_ SG_ 37 STEER_RATE "factor is tbd";
CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isnt perfect";
CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect";
CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph";
CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?";
CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque";

View File

@ -1,3 +1,3 @@
# flake8: noqa
# pylint: skip-file
from .python import Panda, PandaWifiStreaming, PandaDFU, ESPROM, CesantaFlasher, flash_release, BASEDIR, ensure_st_up_to_date, build_st, PandaSerial
from .python import Panda, PandaWifiStreaming, PandaDFU, flash_release, BASEDIR, ensure_st_up_to_date, build_st, PandaSerial

View File

@ -9,6 +9,7 @@
#ifdef PANDA
#include "drivers/fan.h"
#include "drivers/rtc.h"
#include "drivers/clock_source.h"
#include "boards/white.h"
#include "boards/grey.h"
#include "boards/black.h"
@ -23,7 +24,7 @@ void detect_board_type(void) {
// SPI lines floating: white (TODO: is this reliable? Not really, we have to enable ESP/GPS to be able to detect this on the UART)
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 1);
if(!detect_with_pull(GPIOB, 1, PULL_UP) && detect_with_pull(GPIOB, 15, PULL_UP)){
if(!detect_with_pull(GPIOB, 1, PULL_UP) && !detect_with_pull(GPIOB, 7, PULL_UP)){
hw_type = HW_TYPE_DOS;
current_board = &board_dos;
} else if((detect_with_pull(GPIOA, 4, PULL_DOWN)) || (detect_with_pull(GPIOA, 5, PULL_DOWN)) || (detect_with_pull(GPIOA, 6, PULL_DOWN)) || (detect_with_pull(GPIOA, 7, PULL_DOWN))){
@ -53,22 +54,10 @@ void detect_board_type(void) {
// ///// Configuration detection ///// //
bool has_external_debug_serial = 0;
bool is_entering_bootmode = 0;
void detect_configuration(void) {
// detect if external serial debugging is present
has_external_debug_serial = detect_with_pull(GPIOA, 3, PULL_DOWN);
#ifdef PANDA
if(hw_type == HW_TYPE_WHITE_PANDA) {
// check if the ESP is trying to put me in boot mode
is_entering_bootmode = !detect_with_pull(GPIOB, 0, PULL_UP);
} else {
is_entering_bootmode = 0;
}
#else
is_entering_bootmode = 0;
#endif
}
// ///// Board functions ///// //

View File

@ -1,10 +1,10 @@
// ******************** Prototypes ********************
typedef void (*board_init)(void);
typedef void (*board_enable_can_transciever)(uint8_t transciever, bool enabled);
typedef void (*board_enable_can_transcievers)(bool enabled);
typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled);
typedef void (*board_enable_can_transceivers)(bool enabled);
typedef void (*board_set_led)(uint8_t color, bool enabled);
typedef void (*board_set_usb_power_mode)(uint8_t mode);
typedef void (*board_set_esp_gps_mode)(uint8_t mode);
typedef void (*board_set_gps_mode)(uint8_t mode);
typedef void (*board_set_can_mode)(uint8_t mode);
typedef void (*board_usb_power_mode_tick)(uint32_t uptime);
typedef bool (*board_check_ignition)(void);
@ -12,16 +12,18 @@ typedef uint32_t (*board_read_current)(void);
typedef void (*board_set_ir_power)(uint8_t percentage);
typedef void (*board_set_fan_power)(uint8_t percentage);
typedef void (*board_set_phone_power)(bool enabled);
typedef void (*board_set_clock_source_mode)(uint8_t mode);
typedef void (*board_set_siren)(bool enabled);
struct board {
const char *board_type;
const harness_configuration *harness_config;
board_init init;
board_enable_can_transciever enable_can_transciever;
board_enable_can_transcievers enable_can_transcievers;
board_enable_can_transceiver enable_can_transceiver;
board_enable_can_transceivers enable_can_transceivers;
board_set_led set_led;
board_set_usb_power_mode set_usb_power_mode;
board_set_esp_gps_mode set_esp_gps_mode;
board_set_gps_mode set_gps_mode;
board_set_can_mode set_can_mode;
board_usb_power_mode_tick usb_power_mode_tick;
board_check_ignition check_ignition;
@ -29,6 +31,8 @@ struct board {
board_set_ir_power set_ir_power;
board_set_fan_power set_fan_power;
board_set_phone_power set_phone_power;
board_set_clock_source_mode set_clock_source_mode;
board_set_siren set_siren;
};
// ******************* Definitions ********************
@ -52,10 +56,10 @@ struct board {
#define USB_POWER_CDP 2U
#define USB_POWER_DCP 3U
// ESP modes
#define ESP_GPS_DISABLED 0U
#define ESP_GPS_ENABLED 1U
#define ESP_GPS_BOOTMODE 2U
// GPS modes
#define GPS_DISABLED 0U
#define GPS_ENABLED 1U
#define GPS_BOOTMODE 2U
// CAN modes
#define CAN_MODE_NORMAL 0U
@ -72,4 +76,4 @@ bool board_has_gmlan(void);
bool board_has_obd(void);
bool board_has_lin(void);
bool board_has_rtc(void);
bool board_has_relay(void);
bool board_has_relay(void);

View File

@ -2,8 +2,8 @@
// Black Panda + Harness //
// ///////////////////// //
void black_enable_can_transciever(uint8_t transciever, bool enabled) {
switch (transciever){
void black_enable_can_transceiver(uint8_t transceiver, bool enabled) {
switch (transceiver){
case 1U:
set_gpio_output(GPIOC, 1, !enabled);
break;
@ -17,18 +17,18 @@ void black_enable_can_transciever(uint8_t transciever, bool enabled) {
set_gpio_output(GPIOB, 10, !enabled);
break;
default:
puts("Invalid CAN transciever ("); puth(transciever); puts("): enabling failed\n");
puts("Invalid CAN transceiver ("); puth(transceiver); puts("): enabling failed\n");
break;
}
}
void black_enable_can_transcievers(bool enabled) {
void black_enable_can_transceivers(bool enabled) {
for(uint8_t i=1U; i<=4U; i++){
// Leave main CAN always on for CAN-based ignition detection
if((car_harness_status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
black_enable_can_transciever(i, true);
black_enable_can_transceiver(i, true);
} else {
black_enable_can_transciever(i, enabled);
black_enable_can_transceiver(i, enabled);
}
}
}
@ -77,24 +77,24 @@ void black_set_usb_power_mode(uint8_t mode) {
}
}
void black_set_esp_gps_mode(uint8_t mode) {
void black_set_gps_mode(uint8_t mode) {
switch (mode) {
case ESP_GPS_DISABLED:
case GPS_DISABLED:
// GPS OFF
set_gpio_output(GPIOC, 14, 0);
set_gpio_output(GPIOC, 5, 0);
break;
case ESP_GPS_ENABLED:
case GPS_ENABLED:
// GPS ON
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 1);
break;
case ESP_GPS_BOOTMODE:
case GPS_BOOTMODE:
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 0);
break;
default:
puts("Invalid ESP/GPS mode\n");
puts("Invalid GPS mode\n");
break;
}
}
@ -154,6 +154,14 @@ void black_set_phone_power(bool enabled){
UNUSED(enabled);
}
void black_set_clock_source_mode(uint8_t mode){
UNUSED(mode);
}
void black_set_siren(bool enabled){
UNUSED(enabled);
}
void black_init(void) {
common_init_gpio();
@ -167,7 +175,7 @@ void black_init(void) {
set_gpio_mode(GPIOC, 3, MODE_ANALOG);
// Set default state of GPS
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
current_board->set_gps_mode(GPS_ENABLED);
// C10: OBD_SBU1_RELAY (harness relay driving output)
// C11: OBD_SBU2_RELAY (harness relay driving output)
@ -190,8 +198,8 @@ void black_init(void) {
// Initialize harness
harness_init();
// Enable CAN transcievers
black_enable_can_transcievers(true);
// Enable CAN transceivers
black_enable_can_transceivers(true);
// Disable LEDs
black_set_led(LED_RED, false);
@ -228,16 +236,18 @@ const board board_black = {
.board_type = "Black",
.harness_config = &black_harness_config,
.init = black_init,
.enable_can_transciever = black_enable_can_transciever,
.enable_can_transcievers = black_enable_can_transcievers,
.enable_can_transceiver = black_enable_can_transceiver,
.enable_can_transceivers = black_enable_can_transceivers,
.set_led = black_set_led,
.set_usb_power_mode = black_set_usb_power_mode,
.set_esp_gps_mode = black_set_esp_gps_mode,
.set_gps_mode = black_set_gps_mode,
.set_can_mode = black_set_can_mode,
.usb_power_mode_tick = black_usb_power_mode_tick,
.check_ignition = black_check_ignition,
.read_current = black_read_current,
.set_fan_power = black_set_fan_power,
.set_ir_power = black_set_ir_power,
.set_phone_power = black_set_phone_power
.set_phone_power = black_set_phone_power,
.set_clock_source_mode = black_set_clock_source_mode,
.set_siren = black_set_siren
};

View File

@ -23,7 +23,7 @@ void common_init_gpio(void){
set_gpio_alternate(GPIOA, 12, GPIO_AF10_OTG_FS);
GPIOA->OSPEEDR = GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12;
// A9,A10: USART 1 for talking to the ESP / GPS
// A9,A10: USART 1 for talking to the GPS
set_gpio_alternate(GPIOA, 9, GPIO_AF7_USART1);
set_gpio_alternate(GPIOA, 10, GPIO_AF7_USART1);
@ -65,7 +65,7 @@ void peripherals_init(void){
RCC->APB1ENR |= RCC_APB1ENR_PWREN; // for RTC config
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
//RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // clock source timer
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
@ -81,4 +81,4 @@ bool detect_with_pull(GPIO_TypeDef *GPIO, int pin, int mode) {
bool ret = get_gpio_input(GPIO, pin);
set_gpio_pullup(GPIO, pin, PULL_NONE);
return ret;
}
}

View File

@ -2,8 +2,8 @@
// Dos + Harness //
// ///////////// //
void dos_enable_can_transciever(uint8_t transciever, bool enabled) {
switch (transciever){
void dos_enable_can_transceiver(uint8_t transceiver, bool enabled) {
switch (transceiver){
case 1U:
set_gpio_output(GPIOC, 1, !enabled);
break;
@ -17,18 +17,18 @@ void dos_enable_can_transciever(uint8_t transciever, bool enabled) {
set_gpio_output(GPIOB, 10, !enabled);
break;
default:
puts("Invalid CAN transciever ("); puth(transciever); puts("): enabling failed\n");
puts("Invalid CAN transceiver ("); puth(transceiver); puts("): enabling failed\n");
break;
}
}
void dos_enable_can_transcievers(bool enabled) {
void dos_enable_can_transceivers(bool enabled) {
for(uint8_t i=1U; i<=4U; i++){
// Leave main CAN always on for CAN-based ignition detection
if((car_harness_status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
uno_enable_can_transciever(i, true);
uno_enable_can_transceiver(i, true);
} else {
uno_enable_can_transciever(i, enabled);
uno_enable_can_transceiver(i, enabled);
}
}
}
@ -54,20 +54,18 @@ void dos_set_gps_load_switch(bool enabled) {
}
void dos_set_bootkick(bool enabled){
UNUSED(enabled);
set_gpio_output(GPIOC, 4, !enabled);
}
void dos_bootkick(void) {}
void dos_set_phone_power(bool enabled){
UNUSED(enabled);
}
void dos_set_usb_power_mode(uint8_t mode) {
UNUSED(mode);
dos_set_bootkick(mode == USB_POWER_CDP);
}
void dos_set_esp_gps_mode(uint8_t mode) {
void dos_set_gps_mode(uint8_t mode) {
UNUSED(mode);
}
@ -101,11 +99,6 @@ void dos_set_can_mode(uint8_t mode){
void dos_usb_power_mode_tick(uint32_t uptime){
UNUSED(uptime);
if(bootkick_timer != 0U){
bootkick_timer--;
} else {
dos_set_bootkick(false);
}
}
bool dos_check_ignition(void){
@ -132,6 +125,14 @@ uint32_t dos_read_current(void){
return 0U;
}
void dos_set_clock_source_mode(uint8_t mode){
clock_source_init(mode);
}
void dos_set_siren(bool enabled){
set_gpio_output(GPIOC, 12, enabled);
}
void dos_init(void) {
common_init_gpio();
@ -171,8 +172,8 @@ void dos_init(void) {
// Initialize RTC
rtc_init();
// Enable CAN transcievers
dos_enable_can_transcievers(true);
// Enable CAN transceivers
dos_enable_can_transceivers(true);
// Disable LEDs
dos_set_led(LED_RED, false);
@ -189,6 +190,9 @@ void dos_init(void) {
// init multiplexer
can_set_obd(car_harness_status, false);
// Init clock source as internal free running
dos_set_clock_source_mode(CLOCK_SOURCE_MODE_FREE_RUNNING);
}
const harness_configuration dos_harness_config = {
@ -209,16 +213,18 @@ const board board_dos = {
.board_type = "Dos",
.harness_config = &dos_harness_config,
.init = dos_init,
.enable_can_transciever = dos_enable_can_transciever,
.enable_can_transcievers = dos_enable_can_transcievers,
.enable_can_transceiver = dos_enable_can_transceiver,
.enable_can_transceivers = dos_enable_can_transceivers,
.set_led = dos_set_led,
.set_usb_power_mode = dos_set_usb_power_mode,
.set_esp_gps_mode = dos_set_esp_gps_mode,
.set_gps_mode = dos_set_gps_mode,
.set_can_mode = dos_set_can_mode,
.usb_power_mode_tick = dos_usb_power_mode_tick,
.check_ignition = dos_check_ignition,
.read_current = dos_read_current,
.set_fan_power = dos_set_fan_power,
.set_ir_power = dos_set_ir_power,
.set_phone_power = dos_set_phone_power
.set_phone_power = dos_set_phone_power,
.set_clock_source_mode = dos_set_clock_source_mode,
.set_siren = dos_set_siren
};

View File

@ -8,22 +8,22 @@ void grey_init(void) {
white_grey_common_init();
// Set default state of GPS
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
current_board->set_gps_mode(GPS_ENABLED);
}
void grey_set_esp_gps_mode(uint8_t mode) {
void grey_set_gps_mode(uint8_t mode) {
switch (mode) {
case ESP_GPS_DISABLED:
case GPS_DISABLED:
// GPS OFF
set_gpio_output(GPIOC, 14, 0);
set_gpio_output(GPIOC, 5, 0);
break;
case ESP_GPS_ENABLED:
case GPS_ENABLED:
// GPS ON
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 1);
break;
case ESP_GPS_BOOTMODE:
case GPS_BOOTMODE:
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 0);
break;
@ -37,16 +37,18 @@ const board board_grey = {
.board_type = "Grey",
.harness_config = &white_harness_config,
.init = grey_init,
.enable_can_transciever = white_enable_can_transciever,
.enable_can_transcievers = white_enable_can_transcievers,
.enable_can_transceiver = white_enable_can_transceiver,
.enable_can_transceivers = white_enable_can_transceivers,
.set_led = white_set_led,
.set_usb_power_mode = white_set_usb_power_mode,
.set_esp_gps_mode = grey_set_esp_gps_mode,
.set_gps_mode = grey_set_gps_mode,
.set_can_mode = white_set_can_mode,
.usb_power_mode_tick = white_usb_power_mode_tick,
.check_ignition = white_check_ignition,
.read_current = white_read_current,
.set_fan_power = white_set_fan_power,
.set_ir_power = white_set_ir_power,
.set_phone_power = white_set_phone_power
};
.set_phone_power = white_set_phone_power,
.set_clock_source_mode = white_set_clock_source_mode,
.set_siren = white_set_siren
};

View File

@ -2,19 +2,19 @@
// Pedal //
// ///// //
void pedal_enable_can_transciever(uint8_t transciever, bool enabled) {
switch (transciever){
void pedal_enable_can_transceiver(uint8_t transceiver, bool enabled) {
switch (transceiver){
case 1:
set_gpio_output(GPIOB, 3, !enabled);
break;
default:
puts("Invalid CAN transciever ("); puth(transciever); puts("): enabling failed\n");
puts("Invalid CAN transceiver ("); puth(transceiver); puts("): enabling failed\n");
break;
}
}
void pedal_enable_can_transcievers(bool enabled) {
pedal_enable_can_transciever(1U, enabled);
void pedal_enable_can_transceivers(bool enabled) {
pedal_enable_can_transceiver(1U, enabled);
}
void pedal_set_led(uint8_t color, bool enabled) {
@ -35,7 +35,7 @@ void pedal_set_usb_power_mode(uint8_t mode){
puts("Trying to set USB power mode on pedal. This is not supported.\n");
}
void pedal_set_esp_gps_mode(uint8_t mode) {
void pedal_set_gps_mode(uint8_t mode) {
UNUSED(mode);
puts("Trying to set ESP/GPS mode on pedal. This is not supported.\n");
}
@ -77,6 +77,14 @@ void pedal_set_phone_power(bool enabled){
UNUSED(enabled);
}
void pedal_set_clock_source_mode(uint8_t mode){
UNUSED(mode);
}
void pedal_set_siren(bool enabled){
UNUSED(enabled);
}
void pedal_init(void) {
common_init_gpio();
@ -86,8 +94,8 @@ void pedal_init(void) {
// DAC outputs on A4 and A5
// apparently they don't need GPIO setup
// Enable transciever
pedal_enable_can_transcievers(true);
// Enable transceiver
pedal_enable_can_transceivers(true);
// Disable LEDs
pedal_set_led(LED_RED, false);
@ -102,16 +110,18 @@ const board board_pedal = {
.board_type = "Pedal",
.harness_config = &pedal_harness_config,
.init = pedal_init,
.enable_can_transciever = pedal_enable_can_transciever,
.enable_can_transcievers = pedal_enable_can_transcievers,
.enable_can_transceiver = pedal_enable_can_transceiver,
.enable_can_transceivers = pedal_enable_can_transceivers,
.set_led = pedal_set_led,
.set_usb_power_mode = pedal_set_usb_power_mode,
.set_esp_gps_mode = pedal_set_esp_gps_mode,
.set_gps_mode = pedal_set_gps_mode,
.set_can_mode = pedal_set_can_mode,
.usb_power_mode_tick = pedal_usb_power_mode_tick,
.check_ignition = pedal_check_ignition,
.read_current = pedal_read_current,
.set_fan_power = pedal_set_fan_power,
.set_ir_power = pedal_set_ir_power,
.set_phone_power = pedal_set_phone_power
};
.set_phone_power = pedal_set_phone_power,
.set_clock_source_mode = pedal_set_clock_source_mode,
.set_siren = pedal_set_siren
};

View File

@ -4,8 +4,8 @@
#define BOOTKICK_TIME 3U
uint8_t bootkick_timer = 0U;
void uno_enable_can_transciever(uint8_t transciever, bool enabled) {
switch (transciever){
void uno_enable_can_transceiver(uint8_t transceiver, bool enabled) {
switch (transceiver){
case 1U:
set_gpio_output(GPIOC, 1, !enabled);
break;
@ -19,18 +19,18 @@ void uno_enable_can_transciever(uint8_t transciever, bool enabled) {
set_gpio_output(GPIOB, 10, !enabled);
break;
default:
puts("Invalid CAN transciever ("); puth(transciever); puts("): enabling failed\n");
puts("Invalid CAN transceiver ("); puth(transceiver); puts("): enabling failed\n");
break;
}
}
void uno_enable_can_transcievers(bool enabled) {
void uno_enable_can_transceivers(bool enabled) {
for(uint8_t i=1U; i<=4U; i++){
// Leave main CAN always on for CAN-based ignition detection
if((car_harness_status == HARNESS_STATUS_FLIPPED) ? (i == 3U) : (i == 1U)){
uno_enable_can_transciever(i, true);
uno_enable_can_transceiver(i, true);
} else {
uno_enable_can_transciever(i, enabled);
uno_enable_can_transceiver(i, enabled);
}
}
}
@ -89,21 +89,21 @@ void uno_set_usb_power_mode(uint8_t mode) {
}
}
void uno_set_esp_gps_mode(uint8_t mode) {
void uno_set_gps_mode(uint8_t mode) {
switch (mode) {
case ESP_GPS_DISABLED:
case GPS_DISABLED:
// GPS OFF
set_gpio_output(GPIOB, 1, 0);
set_gpio_output(GPIOC, 5, 0);
uno_set_gps_load_switch(false);
break;
case ESP_GPS_ENABLED:
case GPS_ENABLED:
// GPS ON
set_gpio_output(GPIOB, 1, 1);
set_gpio_output(GPIOC, 5, 1);
uno_set_gps_load_switch(true);
break;
case ESP_GPS_BOOTMODE:
case GPS_BOOTMODE:
set_gpio_output(GPIOB, 1, 1);
set_gpio_output(GPIOC, 5, 0);
uno_set_gps_load_switch(true);
@ -175,6 +175,14 @@ uint32_t uno_read_current(void){
return 0U;
}
void uno_set_clock_source_mode(uint8_t mode){
UNUSED(mode);
}
void uno_set_siren(bool enabled){
UNUSED(enabled);
}
void uno_init(void) {
common_init_gpio();
@ -188,7 +196,7 @@ void uno_init(void) {
set_gpio_mode(GPIOC, 3, MODE_ANALOG);
// Set default state of GPS
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
current_board->set_gps_mode(GPS_ENABLED);
// C10: OBD_SBU1_RELAY (harness relay driving output)
// C11: OBD_SBU2_RELAY (harness relay driving output)
@ -223,8 +231,8 @@ void uno_init(void) {
// Initialize RTC
rtc_init();
// Enable CAN transcievers
uno_enable_can_transcievers(true);
// Enable CAN transceivers
uno_enable_can_transceivers(true);
// Disable LEDs
uno_set_led(LED_RED, false);
@ -271,16 +279,18 @@ const board board_uno = {
.board_type = "Uno",
.harness_config = &uno_harness_config,
.init = uno_init,
.enable_can_transciever = uno_enable_can_transciever,
.enable_can_transcievers = uno_enable_can_transcievers,
.enable_can_transceiver = uno_enable_can_transceiver,
.enable_can_transceivers = uno_enable_can_transceivers,
.set_led = uno_set_led,
.set_usb_power_mode = uno_set_usb_power_mode,
.set_esp_gps_mode = uno_set_esp_gps_mode,
.set_gps_mode = uno_set_gps_mode,
.set_can_mode = uno_set_can_mode,
.usb_power_mode_tick = uno_usb_power_mode_tick,
.check_ignition = uno_check_ignition,
.read_current = uno_read_current,
.set_fan_power = uno_set_fan_power,
.set_ir_power = uno_set_ir_power,
.set_phone_power = uno_set_phone_power
.set_phone_power = uno_set_phone_power,
.set_clock_source_mode = uno_set_clock_source_mode,
.set_siren = uno_set_siren
};

View File

@ -2,8 +2,8 @@
// White Panda //
// /////////// //
void white_enable_can_transciever(uint8_t transciever, bool enabled) {
switch (transciever){
void white_enable_can_transceiver(uint8_t transceiver, bool enabled) {
switch (transceiver){
case 1U:
set_gpio_output(GPIOC, 1, !enabled);
break;
@ -14,15 +14,15 @@ void white_enable_can_transciever(uint8_t transciever, bool enabled) {
set_gpio_output(GPIOA, 0, !enabled);
break;
default:
puts("Invalid CAN transciever ("); puth(transciever); puts("): enabling failed\n");
puts("Invalid CAN transceiver ("); puth(transceiver); puts("): enabling failed\n");
break;
}
}
void white_enable_can_transcievers(bool enabled) {
uint8_t t1 = enabled ? 1U : 2U; // leave transciever 1 enabled to detect CAN ignition
void white_enable_can_transceivers(bool enabled) {
uint8_t t1 = enabled ? 1U : 2U; // leave transceiver 1 enabled to detect CAN ignition
for(uint8_t i=t1; i<=3U; i++) {
white_enable_can_transciever(i, enabled);
white_enable_can_transceiver(i, enabled);
}
}
@ -71,21 +71,21 @@ void white_set_usb_power_mode(uint8_t mode){
}
}
void white_set_esp_gps_mode(uint8_t mode) {
void white_set_gps_mode(uint8_t mode) {
switch (mode) {
case ESP_GPS_DISABLED:
case GPS_DISABLED:
// ESP OFF
set_gpio_output(GPIOC, 14, 0);
set_gpio_output(GPIOC, 5, 0);
break;
#ifndef EON
case ESP_GPS_ENABLED:
case GPS_ENABLED:
// ESP ON
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 1);
break;
#endif
case ESP_GPS_BOOTMODE:
case GPS_BOOTMODE:
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 0);
break;
@ -242,6 +242,14 @@ void white_set_phone_power(bool enabled){
UNUSED(enabled);
}
void white_set_clock_source_mode(uint8_t mode){
UNUSED(mode);
}
void white_set_siren(bool enabled){
UNUSED(enabled);
}
void white_grey_common_init(void) {
common_init_gpio();
@ -291,8 +299,8 @@ void white_grey_common_init(void) {
set_gpio_alternate(GPIOC, 11, GPIO_AF7_USART3);
set_gpio_pullup(GPIOC, 11, PULL_UP);
// Enable CAN transcievers
white_enable_can_transcievers(true);
// Enable CAN transceivers
white_enable_can_transceivers(true);
// Disable LEDs
white_set_led(LED_RED, false);
@ -316,12 +324,8 @@ void white_grey_common_init(void) {
void white_init(void) {
white_grey_common_init();
// Set default state of ESP
#ifdef EON
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
#else
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
#endif
// Set ESP off by default
current_board->set_gps_mode(GPS_DISABLED);
}
const harness_configuration white_harness_config = {
@ -332,16 +336,18 @@ const board board_white = {
.board_type = "White",
.harness_config = &white_harness_config,
.init = white_init,
.enable_can_transciever = white_enable_can_transciever,
.enable_can_transcievers = white_enable_can_transcievers,
.enable_can_transceiver = white_enable_can_transceiver,
.enable_can_transceivers = white_enable_can_transceivers,
.set_led = white_set_led,
.set_usb_power_mode = white_set_usb_power_mode,
.set_esp_gps_mode = white_set_esp_gps_mode,
.set_gps_mode = white_set_gps_mode,
.set_can_mode = white_set_can_mode,
.usb_power_mode_tick = white_usb_power_mode_tick,
.check_ignition = white_check_ignition,
.read_current = white_read_current,
.set_fan_power = white_set_fan_power,
.set_ir_power = white_set_ir_power,
.set_phone_power = white_set_phone_power
.set_phone_power = white_set_phone_power,
.set_clock_source_mode = white_set_clock_source_mode,
.set_siren = white_set_siren
};

View File

@ -0,0 +1,100 @@
#define CLOCK_SOURCE_MODE_DISABLED 0U
#define CLOCK_SOURCE_MODE_FREE_RUNNING 1U
#define CLOCK_SOURCE_MODE_EXTERNAL_SYNC 2U
#define CLOCK_SOURCE_PERIOD_MS 50U
#define CLOCK_SOURCE_PULSE_LEN_MS 2U
uint8_t clock_source_mode = CLOCK_SOURCE_MODE_DISABLED;
void EXTI0_IRQ_Handler(void) {
volatile unsigned int pr = EXTI->PR & (1U << 0);
if (pr != 0U) {
if(clock_source_mode == CLOCK_SOURCE_MODE_EXTERNAL_SYNC){
// TODO: Implement!
}
}
EXTI->PR = (1U << 0);
}
void TIM1_UP_TIM10_IRQ_Handler(void) {
if((TIM1->SR & TIM_SR_UIF) != 0) {
if(clock_source_mode != CLOCK_SOURCE_MODE_DISABLED) {
// Start clock pulse
set_gpio_output(GPIOB, 14, true);
set_gpio_output(GPIOB, 15, true);
}
// Reset interrupt
TIM1->SR &= ~(TIM_SR_UIF);
}
}
void TIM1_CC_IRQ_Handler(void) {
if((TIM1->SR & TIM_SR_CC1IF) != 0) {
if(clock_source_mode != CLOCK_SOURCE_MODE_DISABLED) {
// End clock pulse
set_gpio_output(GPIOB, 14, false);
set_gpio_output(GPIOB, 15, false);
}
// Reset interrupt
TIM1->SR &= ~(TIM_SR_CC1IF);
}
}
void clock_source_init(uint8_t mode){
// Setup external clock signal interrupt
REGISTER_INTERRUPT(EXTI0_IRQn, EXTI0_IRQ_Handler, 110U, FAULT_INTERRUPT_RATE_CLOCK_SOURCE)
register_set(&(SYSCFG->EXTICR[0]), SYSCFG_EXTICR1_EXTI0_PB, 0xFU);
register_set_bits(&(EXTI->IMR), (1U << 0));
register_set_bits(&(EXTI->RTSR), (1U << 0));
register_clear_bits(&(EXTI->FTSR), (1U << 0));
// Setup timer
REGISTER_INTERRUPT(TIM1_UP_TIM10_IRQn, TIM1_UP_TIM10_IRQ_Handler, (1200U / CLOCK_SOURCE_PERIOD_MS) , FAULT_INTERRUPT_RATE_TIM1)
REGISTER_INTERRUPT(TIM1_CC_IRQn, TIM1_CC_IRQ_Handler, (1200U / CLOCK_SOURCE_PERIOD_MS) , FAULT_INTERRUPT_RATE_TIM1)
register_set(&(TIM1->PSC), (9600-1), 0xFFFFU); // Tick on 0.1 ms
register_set(&(TIM1->ARR), ((CLOCK_SOURCE_PERIOD_MS*10U) - 1U), 0xFFFFU); // Period
register_set(&(TIM1->CCMR1), 0U, 0xFFFFU); // No output on compare
register_set_bits(&(TIM1->CCER), TIM_CCER_CC1E); // Enable compare 1
register_set(&(TIM1->CCR1), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value
register_set_bits(&(TIM1->DIER), TIM_DIER_UIE | TIM_DIER_CC1IE); // Enable interrupts
register_set(&(TIM1->CR1), TIM_CR1_CEN, 0x3FU); // Enable timer
// Set mode
switch(mode) {
case CLOCK_SOURCE_MODE_DISABLED:
// No clock signal
NVIC_DisableIRQ(EXTI0_IRQn);
NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);
NVIC_DisableIRQ(TIM1_CC_IRQn);
// Disable pulse if we were in the middle of it
set_gpio_output(GPIOB, 14, false);
set_gpio_output(GPIOB, 15, false);
clock_source_mode = CLOCK_SOURCE_MODE_DISABLED;
break;
case CLOCK_SOURCE_MODE_FREE_RUNNING:
// Clock signal is based on internal timer
NVIC_DisableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
NVIC_EnableIRQ(TIM1_CC_IRQn);
clock_source_mode = CLOCK_SOURCE_MODE_FREE_RUNNING;
break;
case CLOCK_SOURCE_MODE_EXTERNAL_SYNC:
// Clock signal is based on external timer
NVIC_EnableIRQ(EXTI0_IRQn);
NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
NVIC_EnableIRQ(TIM1_CC_IRQn);
clock_source_mode = CLOCK_SOURCE_MODE_EXTERNAL_SYNC;
break;
default:
puts("Unknown clock source mode: "); puth(mode); puts("\n");
break;
}
}

View File

@ -50,8 +50,8 @@ void debug_ring_callback(uart_ring *ring);
// ******************************** UART buffers ********************************
// esp_gps = USART1
UART_BUFFER(esp_gps, FIFO_SIZE_DMA, FIFO_SIZE_INT, USART1, NULL, true)
// gps = USART1
UART_BUFFER(gps, FIFO_SIZE_DMA, FIFO_SIZE_INT, USART1, NULL, true)
// lin1, K-LINE = UART5
// lin2, L-LINE = USART3
@ -68,7 +68,7 @@ uart_ring *get_ring_by_number(int a) {
ring = &uart_ring_debug;
break;
case 1:
ring = &uart_ring_esp_gps;
ring = &uart_ring_gps;
break;
case 2:
ring = &uart_ring_lin1;
@ -185,8 +185,8 @@ void uart_interrupt_handler(uart_ring *q) {
// Reset IDLE flag
UART_READ_DR(q->uart)
if(q == &uart_ring_esp_gps){
dma_pointer_handler(&uart_ring_esp_gps, DMA2_Stream5->NDTR);
if(q == &uart_ring_gps){
dma_pointer_handler(&uart_ring_gps, DMA2_Stream5->NDTR);
} else {
#ifdef DEBUG_UART
puts("No IDLE dma_pointer_handler implemented for this UART.");
@ -197,7 +197,7 @@ void uart_interrupt_handler(uart_ring *q) {
EXIT_CRITICAL();
}
void USART1_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_esp_gps); }
void USART1_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_gps); }
void USART2_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_debug); }
void USART3_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_lin2); }
void UART5_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_lin1); }
@ -219,7 +219,7 @@ void DMA2_Stream5_IRQ_Handler(void) {
}
// Re-calculate write pointer and reset flags
dma_pointer_handler(&uart_ring_esp_gps, DMA2_Stream5->NDTR);
dma_pointer_handler(&uart_ring_gps, DMA2_Stream5->NDTR);
DMA2->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5;
EXIT_CRITICAL();
@ -229,7 +229,7 @@ void DMA2_Stream5_IRQ_Handler(void) {
void dma_rx_init(uart_ring *q) {
// Initialization is UART-dependent
if(q == &uart_ring_esp_gps){
if(q == &uart_ring_gps){
// DMA2, stream 5, channel 4
// Disable FIFO mode (enable direct)

View File

@ -3,26 +3,28 @@
#define FAULT_STATUS_PERMANENT 2U
// Fault types
#define FAULT_RELAY_MALFUNCTION (1U << 0)
#define FAULT_UNUSED_INTERRUPT_HANDLED (1U << 1)
#define FAULT_INTERRUPT_RATE_CAN_1 (1U << 2)
#define FAULT_INTERRUPT_RATE_CAN_2 (1U << 3)
#define FAULT_INTERRUPT_RATE_CAN_3 (1U << 4)
#define FAULT_INTERRUPT_RATE_TACH (1U << 5)
#define FAULT_INTERRUPT_RATE_GMLAN (1U << 6)
#define FAULT_INTERRUPT_RATE_INTERRUPTS (1U << 7)
#define FAULT_INTERRUPT_RATE_SPI_DMA (1U << 8)
#define FAULT_INTERRUPT_RATE_SPI_CS (1U << 9)
#define FAULT_INTERRUPT_RATE_UART_1 (1U << 10)
#define FAULT_INTERRUPT_RATE_UART_2 (1U << 11)
#define FAULT_INTERRUPT_RATE_UART_3 (1U << 12)
#define FAULT_INTERRUPT_RATE_UART_5 (1U << 13)
#define FAULT_INTERRUPT_RATE_UART_DMA (1U << 14)
#define FAULT_INTERRUPT_RATE_USB (1U << 15)
#define FAULT_INTERRUPT_RATE_TIM1 (1U << 16)
#define FAULT_INTERRUPT_RATE_TIM3 (1U << 17)
#define FAULT_REGISTER_DIVERGENT (1U << 18)
#define FAULT_INTERRUPT_RATE_KLINE_INIT (1U << 19)
#define FAULT_RELAY_MALFUNCTION (1U << 0)
#define FAULT_UNUSED_INTERRUPT_HANDLED (1U << 1)
#define FAULT_INTERRUPT_RATE_CAN_1 (1U << 2)
#define FAULT_INTERRUPT_RATE_CAN_2 (1U << 3)
#define FAULT_INTERRUPT_RATE_CAN_3 (1U << 4)
#define FAULT_INTERRUPT_RATE_TACH (1U << 5)
#define FAULT_INTERRUPT_RATE_GMLAN (1U << 6)
#define FAULT_INTERRUPT_RATE_INTERRUPTS (1U << 7)
#define FAULT_INTERRUPT_RATE_SPI_DMA (1U << 8)
#define FAULT_INTERRUPT_RATE_SPI_CS (1U << 9)
#define FAULT_INTERRUPT_RATE_UART_1 (1U << 10)
#define FAULT_INTERRUPT_RATE_UART_2 (1U << 11)
#define FAULT_INTERRUPT_RATE_UART_3 (1U << 12)
#define FAULT_INTERRUPT_RATE_UART_5 (1U << 13)
#define FAULT_INTERRUPT_RATE_UART_DMA (1U << 14)
#define FAULT_INTERRUPT_RATE_USB (1U << 15)
#define FAULT_INTERRUPT_RATE_TIM1 (1U << 16)
#define FAULT_INTERRUPT_RATE_TIM3 (1U << 17)
#define FAULT_REGISTER_DIVERGENT (1U << 18)
#define FAULT_INTERRUPT_RATE_KLINE_INIT (1U << 19)
#define FAULT_INTERRUPT_RATE_CLOCK_SOURCE (1U << 20)
#define FAULT_INTERRUPT_RATE_TIM9 (1U << 21)
// Permanent faults
#define PERMANENT_FAULTS 0U

View File

@ -64,13 +64,9 @@ void early(void) {
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
#ifdef PANDA
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
current_board->set_gps_mode(GPS_DISABLED);
#endif
current_board->set_led(LED_GREEN, 1);
jump_to_bootloader();
}
if (is_entering_bootmode) {
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC;
}
}
}

View File

@ -400,24 +400,24 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
// **** 0xd9: set ESP power
case 0xd9:
if (setup->b.wValue.w == 1U) {
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
current_board->set_gps_mode(GPS_ENABLED);
} else if (setup->b.wValue.w == 2U) {
current_board->set_esp_gps_mode(ESP_GPS_BOOTMODE);
current_board->set_gps_mode(GPS_BOOTMODE);
} else {
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
current_board->set_gps_mode(GPS_DISABLED);
}
break;
// **** 0xda: reset ESP, with optional boot mode
case 0xda:
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
current_board->set_gps_mode(GPS_DISABLED);
delay(1000000);
if (setup->b.wValue.w == 1U) {
current_board->set_esp_gps_mode(ESP_GPS_BOOTMODE);
current_board->set_gps_mode(GPS_BOOTMODE);
} else {
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
current_board->set_gps_mode(GPS_ENABLED);
}
delay(1000000);
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
current_board->set_gps_mode(GPS_ENABLED);
break;
// **** 0xdb: set GMLAN (white/grey) or OBD CAN (black) multiplexing mode
case 0xdb:
@ -493,7 +493,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
}
// TODO: Remove this again and fix boardd code to hande the message bursts instead of single chars
if (ur == &uart_ring_esp_gps) {
if (ur == &uart_ring_gps) {
dma_pointer_handler(ur, DMA2_Stream5->NDTR);
}
@ -606,6 +606,14 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
}
}
break;
// **** 0xf5: set clock source mode
case 0xf5:
current_board->set_clock_source_mode(setup->b.wValue.w);
break;
// **** 0xf6: set siren enabled
case 0xf6:
siren_enabled = (setup->b.wValue.w != 0U);
break;
default:
puts("NO HANDLER ");
puth(setup->b.bRequest);
@ -663,87 +671,97 @@ void __attribute__ ((noinline)) enable_fpu(void) {
#define EON_HEARTBEAT_IGNITION_CNT_ON 5U
#define EON_HEARTBEAT_IGNITION_CNT_OFF 2U
// called at 1Hz
// called at 8Hz
uint8_t loop_counter = 0U;
void TIM1_BRK_TIM9_IRQ_Handler(void) {
if (TIM9->SR != 0) {
can_live = pending_can_live;
// siren
current_board->set_siren((loop_counter & 1U) && siren_enabled);
current_board->usb_power_mode_tick(uptime_cnt);
// decimated to 1Hz
if(loop_counter == 0U){
can_live = pending_can_live;
//puth(usart1_dma); puts(" "); puth(DMA2_Stream5->M0AR); puts(" "); puth(DMA2_Stream5->NDTR); puts("\n");
current_board->usb_power_mode_tick(uptime_cnt);
// reset this every 16th pass
if ((uptime_cnt & 0xFU) == 0U) {
pending_can_live = 0;
}
#ifdef DEBUG
puts("** blink ");
puth(can_rx_q.r_ptr); puts(" "); puth(can_rx_q.w_ptr); puts(" ");
puth(can_tx1_q.r_ptr); puts(" "); puth(can_tx1_q.w_ptr); puts(" ");
puth(can_tx2_q.r_ptr); puts(" "); puth(can_tx2_q.w_ptr); puts("\n");
#endif
//puth(usart1_dma); puts(" "); puth(DMA2_Stream5->M0AR); puts(" "); puth(DMA2_Stream5->NDTR); puts("\n");
// Tick drivers
fan_tick();
// set green LED to be controls allowed
current_board->set_led(LED_GREEN, controls_allowed);
// turn off the blue LED, turned on by CAN
// unless we are in power saving mode
current_board->set_led(LED_BLUE, (uptime_cnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
// increase heartbeat counter and cap it at the uint32 limit
if (heartbeat_counter < __UINT32_MAX__) {
heartbeat_counter += 1U;
}
#ifdef EON
// check heartbeat counter if we are running EON code.
// if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save
if (heartbeat_counter >= (check_started() ? EON_HEARTBEAT_IGNITION_CNT_ON : EON_HEARTBEAT_IGNITION_CNT_OFF)) {
puts("EON hasn't sent a heartbeat for 0x");
puth(heartbeat_counter);
puts(" seconds. Safety is set to SILENT mode.\n");
if (current_safety_mode != SAFETY_SILENT) {
set_safety_mode(SAFETY_SILENT, 0U);
// reset this every 16th pass
if ((uptime_cnt & 0xFU) == 0U) {
pending_can_live = 0;
}
if (power_save_status != POWER_SAVE_STATUS_ENABLED) {
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
#ifdef DEBUG
puts("** blink ");
puth(can_rx_q.r_ptr); puts(" "); puth(can_rx_q.w_ptr); puts(" ");
puth(can_tx1_q.r_ptr); puts(" "); puth(can_tx1_q.w_ptr); puts(" ");
puth(can_tx2_q.r_ptr); puts(" "); puth(can_tx2_q.w_ptr); puts("\n");
#endif
// Tick drivers
fan_tick();
// set green LED to be controls allowed
current_board->set_led(LED_GREEN, controls_allowed);
// turn off the blue LED, turned on by CAN
// unless we are in power saving mode
current_board->set_led(LED_BLUE, (uptime_cnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
// increase heartbeat counter and cap it at the uint32 limit
if (heartbeat_counter < __UINT32_MAX__) {
heartbeat_counter += 1U;
}
// Also disable IR when the heartbeat goes missing
current_board->set_ir_power(0U);
#ifdef EON
// check heartbeat counter if we are running EON code.
// if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save
if (heartbeat_counter >= (check_started() ? EON_HEARTBEAT_IGNITION_CNT_ON : EON_HEARTBEAT_IGNITION_CNT_OFF)) {
puts("EON hasn't sent a heartbeat for 0x");
puth(heartbeat_counter);
puts(" seconds. Safety is set to SILENT mode.\n");
if (current_safety_mode != SAFETY_SILENT) {
set_safety_mode(SAFETY_SILENT, 0U);
}
if (power_save_status != POWER_SAVE_STATUS_ENABLED) {
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
}
// If enumerated but no heartbeat (phone up, boardd not running), turn the fan on to cool the device
if(usb_enumerated()){
current_board->set_fan_power(50U);
} else {
current_board->set_fan_power(0U);
// Also disable IR when the heartbeat goes missing
current_board->set_ir_power(0U);
// If enumerated but no heartbeat (phone up, boardd not running), turn the fan on to cool the device
if(usb_enumerated()){
current_board->set_fan_power(50U);
} else {
current_board->set_fan_power(0U);
}
}
// enter CDP mode when car starts to ensure we are charging a turned off EON
if (check_started() && (usb_power_mode != USB_POWER_CDP)) {
current_board->set_usb_power_mode(USB_POWER_CDP);
}
#endif
// check registers
check_registers();
// set ignition_can to false after 2s of no CAN seen
if (ignition_can_cnt > 2U) {
ignition_can = false;
};
// on to the next one
uptime_cnt += 1U;
safety_mode_cnt += 1U;
ignition_can_cnt += 1U;
// synchronous safety check
safety_tick(current_hooks);
}
// enter CDP mode when car starts to ensure we are charging a turned off EON
if (check_started() && (usb_power_mode != USB_POWER_CDP)) {
current_board->set_usb_power_mode(USB_POWER_CDP);
}
#endif
// check registers
check_registers();
// set ignition_can to false after 2s of no CAN seen
if (ignition_can_cnt > 2U) {
ignition_can = false;
};
// on to the next one
uptime_cnt += 1U;
safety_mode_cnt += 1U;
ignition_can_cnt += 1U;
// synchronous safety check
safety_tick(current_hooks);
loop_counter++;
loop_counter %= 8U;
}
TIM9->SR = 0;
}
@ -753,8 +771,8 @@ int main(void) {
// Init interrupt table
init_interrupts(true);
// 1s timer
REGISTER_INTERRUPT(TIM1_BRK_TIM9_IRQn, TIM1_BRK_TIM9_IRQ_Handler, 2U, FAULT_INTERRUPT_RATE_TIM1)
// 8Hz timer
REGISTER_INTERRUPT(TIM1_BRK_TIM9_IRQn, TIM1_BRK_TIM9_IRQ_Handler, 10U, FAULT_INTERRUPT_RATE_TIM9)
// shouldn't have interrupts here, but just in case
disable_interrupts();
@ -778,7 +796,6 @@ int main(void) {
puts("Config:\n");
puts(" Board type: "); puts(current_board->board_type); puts("\n");
puts(has_external_debug_serial ? " Real serial\n" : " USB serial\n");
puts(is_entering_bootmode ? " ESP wants bootmode\n" : " No bootmode\n");
// init board
current_board->init();
@ -794,10 +811,10 @@ int main(void) {
}
if (board_has_gps()) {
uart_init(&uart_ring_esp_gps, 9600);
uart_init(&uart_ring_gps, 9600);
} else {
// enable ESP uart
uart_init(&uart_ring_esp_gps, 115200);
uart_init(&uart_ring_gps, 115200);
}
if(board_has_lin()){
@ -820,14 +837,14 @@ int main(void) {
set_safety_mode(SAFETY_SILENT, 0);
// enable CAN TXs
current_board->enable_can_transcievers(true);
current_board->enable_can_transceivers(true);
#ifndef EON
spi_init();
#endif
// 1hz
timer_init(TIM9, 1464);
// 8hz
timer_init(TIM9, 183);
NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
#ifdef DEBUG

View File

@ -13,3 +13,4 @@ const board *current_board;
bool is_enumerated = 0;
uint32_t heartbeat_counter = 0;
uint32_t uptime_cnt = 0;
bool siren_enabled = false;

View File

@ -28,13 +28,13 @@ void set_power_save_state(int state) {
enable = true;
}
current_board->enable_can_transcievers(enable);
current_board->enable_can_transceivers(enable);
// Switch EPS/GPS
if (enable) {
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
current_board->set_gps_mode(GPS_ENABLED);
} else {
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
current_board->set_gps_mode(GPS_DISABLED);
}
if(board_has_gmlan()){

View File

@ -1,4 +1,4 @@
const int HYUNDAI_MAX_STEER = 255; // like stock
const int HYUNDAI_MAX_STEER = 384; // like stock
const int HYUNDAI_MAX_RT_DELTA = 112; // max delta torque allowed for real time checks
const uint32_t HYUNDAI_RT_INTERVAL = 250000; // 250ms between real time checks
const int HYUNDAI_MAX_RATE_UP = 3;

View File

@ -290,7 +290,7 @@ void soft_flasher_start(void) {
// B8,B9: CAN 1
set_gpio_alternate(GPIOB, 8, GPIO_AF9_CAN1);
set_gpio_alternate(GPIOB, 9, GPIO_AF9_CAN1);
current_board->enable_can_transciever(1, true);
current_board->enable_can_transceiver(1, true);
// init can
llcan_set_speed(CAN1, 5000, false, false);

View File

@ -1,15 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCjIHvrSCWN0Nec6ozbImYik30PIF7JSWgdwDKTxSJ05RM3pj5E
LQEGt3qcaVrTokO68tpt5Gu1p6ZsNqWg7iVTW9M7Qj7IH45YDzQP/PSRjgSosQA6
6f5Gokba5QrW38myqimvj+0p+YH+CNGCBRlTUQGCO8uLCspMZneRSLPW9QIDAQAB
AoGADaUn+HRef9BaWMvd4G6uMHI54cwJYbj8NpDfKjExQqnuw5bqWnWRQmiSnwbJ
DC7kj3zE/LBAuj890ot3q1CAWqh47ZICZfoX9Qbi5TpvIHFCGy6YkOliF6iIQhR2
4+zNKTAA0zNKskOM25PdI+grK1Ni/bEofSA6TrqvEwsmxnkCQQDVp9FUUor2Bo/h
/3oAIP51LTw7vfpztYbJr+BDV63czV2DLXzSwzeNrwH4sA3oy1mjUgMBBgAarNGE
DYlc4H5jAkEAw3UCHzzXPlxkw2QGp7nBly5y3p80Uqc31NuYz8rdX/U8KTngi2No
Ft/SGCEXNpeYbToj+WK3RJJ2Ey0mK8+IxwJAcpGd/5CPsaQNLcw4WK9Yo+8Q2Jxk
G/4gfDCSmqn+smNxnLEcuUwzkwdgkEGgA9BfjeOhdsAH+EXpx90WZrZ/LwJBAK0k
jq+rTqUQZbZsejTEKYjJ/bnV4BzDwoKN0Q1pkLc7X4LJoW74rTFuLgdv8MdMfRtt
IIb/eoeFEpGkMicnHesCQHgR7BTUGBM6Uxam7RCdsgVsxoHBma21E/44ivWUMZzN
3oVt0mPnjS4speOlqwED5pCJ7yw7jwLPFMs8kNxuIKU=
-----END RSA PRIVATE KEY-----

View File

@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCjIHvrSCWN0Nec6ozbImYik30PIF7JSWgdwDKTxSJ05RM3pj5ELQEGt3qcaVrTokO68tpt5Gu1p6ZsNqWg7iVTW9M7Qj7IH45YDzQP/PSRjgSosQA66f5Gokba5QrW38myqimvj+0p+YH+CNGCBRlTUQGCO8uLCspMZneRSLPW9Q== batman@y840

View File

@ -1 +0,0 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDN4pVyGuJJSde1l3Fjay8qPxog09DsAJZtYPk+armoYO1L6YKReUTcMNyHQYZZMZFmhCdgjCgTIF2QYWMoP4KSe8l6JF04YPP51dIgefc6UXjtlSI8Pyutr0v9xXjSfsVm3RAJxDSHgzs9AoMsluKCL+LhAR1nd7cuHXITJ80O4w== batman@y840

View File

@ -10,7 +10,6 @@ import traceback
import subprocess
import sys
from .dfu import PandaDFU # pylint: disable=import-error
from .esptool import ESPROM, CesantaFlasher # noqa pylint: disable=import-error
from .flash_release import flash_release # noqa pylint: disable=import-error
from .update import ensure_st_up_to_date # noqa pylint: disable=import-error
from .serial import PandaSerial # noqa pylint: disable=import-error
@ -148,6 +147,10 @@ class Panda(object):
HW_TYPE_PEDAL = b'\x04'
HW_TYPE_UNO = b'\x05'
CLOCK_SOURCE_MODE_DISABLED = 0
CLOCK_SOURCE_MODE_FREE_RUNNING = 1
CLOCK_SOURCE_MODE_EXTERNAL_SYNC = 2
def __init__(self, serial=None, claim=True):
self._serial = serial
self._handle = None
@ -458,7 +461,7 @@ class Panda(object):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe5, int(enable), 0, b'')
def set_can_enable(self, bus_num, enable):
# sets the can transciever enable pin
# sets the can transceiver enable pin
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf4, int(bus_num), int(enable), b'')
def set_can_speed_kbps(self, bus, speed):
@ -665,3 +668,11 @@ class Panda(object):
# ****************** Phone *****************
def set_phone_power(self, enabled):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xb3, int(enabled), 0, b'')
# ************** Clock Source **************
def set_clock_source_mode(self, mode):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf5, int(mode), 0, b'')
# ****************** Siren *****************
def set_siren(self, enabled):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf6, int(enabled), 0, b'')

View File

@ -24,7 +24,7 @@ class PandaDFU(object):
self._handle = device.open()
self.legacy = "07*128Kg" in self._handle.getASCIIStringDescriptor(4)
return
raise Exception("failed to open " + dfu_serial)
raise Exception("failed to open " + dfu_serial if dfu_serial is not None else "DFU device")
@staticmethod
def list():

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ import json
import io
def flash_release(path=None, st_serial=None):
from panda import Panda, PandaDFU, ESPROM, CesantaFlasher
from panda import Panda, PandaDFU
from zipfile import ZipFile
def status(x):
@ -23,33 +23,28 @@ def flash_release(path=None, st_serial=None):
st_serial = panda_list[0]
print("Using panda with serial %s" % st_serial)
if path is not None:
if path is None:
print("Fetching latest firmware from github.com/commaai/panda-artifacts")
r = requests.get("https://raw.githubusercontent.com/commaai/panda-artifacts/master/latest.json")
url = json.loads(r.text)['url']
r = requests.get(url)
print("Fetching firmware from %s" % url)
path = io.StringIO(r.content)
path = io.BytesIO(r.content)
zf = ZipFile(path)
zf.printdir()
version = zf.read("version")
status("0. Preparing to flash " + version)
version = zf.read("version").decode()
status("0. Preparing to flash " + str(version))
code_bootstub = zf.read("bootstub.panda.bin")
code_panda = zf.read("panda.bin")
code_boot_15 = zf.read("boot_v1.5.bin")
code_boot_15 = code_boot_15[0:2] + "\x00\x30" + code_boot_15[4:]
code_user1 = zf.read("user1.bin")
code_user2 = zf.read("user2.bin")
# enter DFU mode
status("1. Entering DFU mode")
panda = Panda(st_serial)
panda.enter_bootloader()
panda.reset(enter_bootstub=True)
panda.reset(enter_bootloader=True)
time.sleep(1)
# program bootstub
@ -64,29 +59,8 @@ def flash_release(path=None, st_serial=None):
panda.flash(code=code_panda)
panda.close()
# flashing ESP
if panda.is_white():
status("4. Flashing ESP (slow!)")
def align(x, sz=0x1000):
x + "\xFF" * ((sz - len(x)) % sz)
esp = ESPROM(st_serial)
esp.connect()
flasher = CesantaFlasher(esp, 230400)
flasher.flash_write(0x0, align(code_boot_15), True)
flasher.flash_write(0x1000, align(code_user1), True)
flasher.flash_write(0x81000, align(code_user2), True)
flasher.flash_write(0x3FE000, "\xFF" * 0x1000)
flasher.boot_fw()
del flasher
del esp
time.sleep(1)
else:
status("4. No ESP in non-white panda")
# check for connection
status("5. Verifying version")
status("4. Verifying version")
panda = Panda(st_serial)
my_version = panda.get_version()
print("dongle id: %s" % panda.get_serial()[0])

View File

@ -1,4 +1,5 @@
import os
import platform
from cffi import FFI
TEMPLATE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'templates'))
@ -13,7 +14,8 @@ def write_code(folder, name, code, header):
def load_code(folder, name):
shared_fn = os.path.join(folder, f"lib{name}.so")
shared_ext = "dylib" if platform.system() == "Darwin" else "so"
shared_fn = os.path.join(folder, f"lib{name}.{shared_ext}")
header_fn = os.path.join(folder, f"{name}.h")
with open(header_fn) as f:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Some files were not shown because too many files have changed in this diff Show More