Compare commits

...

65 Commits
v0.1 ... v0.3.4

Author SHA1 Message Date
Vehicle Researcher
1b8c44b506 openpilot v0.3.4 tweaks 2017-07-28 20:51:27 -07:00
Vehicle Researcher
6f46f988d9 openpilot v0.3.4 release 2017-07-28 03:23:57 -07:00
George Hotz
68485aa4e4 Merge pull request #116 from commaai/revert-114-new_panda_code
Revert "Pulled in new panda firmware and updated boardd to support the changes."
2017-07-17 23:17:13 -07:00
George Hotz
1581fdc198 Revert "Pulled in new panda firmware and updated boardd to support the changes." 2017-07-17 23:16:57 -07:00
George Hotz
317ae0fb37 Merge pull request #114 from diamondman/new_panda_code
Pulled in new panda firmware and updated boardd to support the changes.
2017-07-11 22:24:38 -07:00
Jessy Diamond Exum
5bf4196aed Removed unnecessary TODO 2017-07-11 22:01:04 -07:00
Jessy Diamond Exum
38aa03e0f7 Moved boardd loopback config to envvar. 2017-07-11 21:59:03 -07:00
Jessy Diamond Exum
9a9dc3ab23 Pulled in new panda firmware and updated boardd to support the changes. 2017-07-11 21:45:16 -07:00
George Hotz
e4aa959e2c Merge pull request #113 from pjlao307/update-alert-text
Update alert text
2017-07-07 10:25:59 -07:00
Joey Lao
2aa9a56f40 Update steering controls saturated message 2017-07-06 22:36:55 -07:00
pjlao307
721ed4ec0e Merge pull request #2 from commaai/release
Release
2017-07-03 11:15:42 -07:00
George Hotz
70be4ceab1 Merge pull request #109 from commaai/devel
openpilot 0.3.3
2017-06-30 18:23:10 -07:00
Vehicle Researcher
5cf91d0496 openpilot v0.3.3 release 2017-06-28 13:57:09 -07:00
George Hotz
6fee0bdb2d Merge pull request #102 from energee/devel-crv
Bounty: 2016 Honda CR-V Touring
2017-06-22 11:52:38 -07:00
Ted Slesinski
e40c161125 Addresses brake error review comment 2017-06-20 02:51:58 -04:00
Ted Slesinski
97eb55cc55 Fixes global saturation change 2017-06-20 02:47:47 -04:00
Ted Slesinski
65134be0d1 Adds correct value of 8 to gearshifter check array 2017-06-20 02:46:59 -04:00
Ted Slesinski
dbf71a23aa Init crv variable 2017-06-20 02:26:50 -04:00
George Hotz
7fec3db1d6 Merge pull request #103 from pjlao307/pjlao-update-ui
Update UI to make text more readable in all conditions as requested by community
2017-06-19 20:37:37 -07:00
Joey Lao
26b573c1d0 Make lead car text a little brighter 2017-06-12 16:39:10 -07:00
Vehicle Researcher
5ec1e7307e Revert last commit since KPH can get 3 digits long 2017-06-12 09:30:47 -07:00
Vehicle Researcher
8bc36b7f21 Adjust position of left speed to align with label (based on 2 digit speeds) 2017-06-12 09:03:49 -07:00
Vehicle Researcher
3b909eb693 More code cleanup 2017-06-12 08:41:11 -07:00
Vehicle Researcher
57e39c4472 Use color param in ui_draw_rounded_rect instead of hard coding 2017-06-12 08:27:57 -07:00
Vehicle Researcher
ff7672339c Add background to radar text. Code cleanup. 2017-06-12 08:19:47 -07:00
John Jones
6e824a2c22 missed one update in latcontrol 2017-06-11 21:33:44 -04:00
Vehicle Researcher
32fa49e093 Clean up code 2017-06-11 15:18:39 -07:00
Vehicle Researcher
2250eac58f Remove commented line 2017-06-11 15:16:46 -07:00
Vehicle Researcher
97be6b3a0e Update UI to make speed text more readable in all conditions as requested by community 2017-06-11 15:12:50 -07:00
John Jones
942655c947 adding steering change from video and removing integer div and adding ki/kp changes 2017-06-11 13:20:19 -04:00
Ted Slesinski
615db3f7fd Reverting steering to original value 2017-06-08 13:15:30 -04:00
Ted Slesinski
0bb75c5389 Syntax typo 2017-06-08 02:33:31 -04:00
Ted Slesinski
7b5ee81d2d Adds support for 2016 Honda CR-V Touring 2017-06-08 01:37:39 -04:00
Vehicle Researcher
7fe46f1e1d openpilot v0.3.2 release 2017-05-22 22:26:12 -07:00
George Hotz
50c0d1c9da Merge pull request #82 from energee/devel
DBC file for 2017 Honda CR-V
2017-05-22 09:00:44 -07:00
Ted Slesinski
6dbf544d06 Adds 2017 CR-V dbc file 2017-05-21 19:46:34 -04:00
Vehicle Researcher
41e3a0f699 openpilot v0.3.1 release 2017-05-17 00:40:33 -07:00
Vehicle Researcher
c5d8aec28b openpilot v0.3.0 release 2017-05-12 16:46:20 -07:00
Vehicle Researcher
4653a9aef0 openpilot v0.3.0-devel release 2017-05-11 12:41:17 -07:00
George Hotz
ab3492bb90 Merge pull request #93 from heidecjj/master
Bug fixes for testing suite
2017-05-02 23:34:32 -07:00
George Hotz
ed7cbb3866 Merge pull request #90 from heidecjj/patch-1
Update maneuver.py
2017-05-02 23:30:36 -07:00
Josh Heidecker
a30626cfe3 Fixed relative distance errors in testing 2017-05-02 22:01:03 -04:00
heidecjj
d2c087b3e2 Update maneuver.py
self.speed_lead_breakpoints was reading from "speed_lead_values" instead of "speed_lead_breakpoints"
2017-04-20 17:09:15 -04:00
George Hotz
0a747f991d Merge pull request #65 from jeankalud/master
Fixed little endian (and scaling/offset)
2017-03-01 16:09:46 -08:00
jeankalud
f5a1e86d85 Add files via upload
Removed unused debug strings
2017-03-01 18:13:37 -05:00
Vehicle Researcher
693bcb0f83 openpilot v0.2.9 release 2017-03-01 10:54:12 -08:00
jeankalud
0d0daed86e Add files via upload
Fixed little endian handling
Fixed offset / scaling handling
2017-03-01 11:02:46 -05:00
Vehicle Researcher
95a349abcc openpilot v0.2.8 release 2017-02-28 00:03:11 -08:00
Vehicle Researcher
c6ba5dc539 openpilot v0.2.7 release 2017-02-08 15:01:17 -08:00
Vehicle Researcher
6c3afeec0f openpilot v0.2.6 release 2017-01-31 01:33:55 -08:00
Vehicle Researcher
29c58b4588 openpilot v0.2.5 release 2017-01-30 14:10:01 -08:00
Vehicle Researcher
ecc565aa3f openpilot v0.2.4 release 2017-01-29 16:10:13 -08:00
George Hotz
db61810f98 Merge pull request #49 from mullakhmetov/master
Added context manager to file reading
2017-01-27 01:17:23 -08:00
Artur Mullakhmetov
48f203ad5b Added context manager to file reading 2017-01-27 11:33:27 +03:00
George Hotz
6ab4ac2dfb Merge pull request #47 from mullakhmetov/crossplatform-gettime
Refactor cross-platform libc usage
2017-01-25 09:19:22 -08:00
Artur Mullakhmetov
9cb3c7b6e6 Refactor cross-platform libc usage 2017-01-25 16:16:00 +03:00
Vehicle Researcher
adaa4ed350 openpilot v0.2.3 release 2017-01-11 14:30:55 -08:00
Vehicle Researcher
a64b9aa9b8 openpilot v0.2.2 release 2017-01-10 11:10:04 -08:00
George Hotz
0138eca61d Merge pull request #40 from TheMutley/master
DBC modified to match the Vector format
2017-01-09 20:47:52 -08:00
Mutley
139a40de29 DBC modified to match the Vector format 2017-01-05 16:55:54 -05:00
Vehicle Researcher
17d9becd3c openpilot v0.2.1 release 2016-12-14 21:29:12 -08:00
Vehicle Researcher
449b482cc3 openpilot v0.2 release 2016-12-12 20:18:19 -08:00
espes
a7e099c946 Update README.md 2016-11-30 14:31:28 -08:00
espes
610462be5a Merge pull request #2 from autti/ford-fusion
Ford Fusion 2017 dbc can file. refs #1.
2016-11-30 11:57:31 -08:00
Ariel Nuñez
207d32668f Added ford fusion dbc can file. refs #1.
Obtained from:

https://bitbucket.org/DataspeedInc/dbw_mkz_ros/downloads
2016-11-30 14:52:47 -05:00
169 changed files with 10162 additions and 28485 deletions

29
.gitignore vendored Normal file
View File

@@ -0,0 +1,29 @@
.DS_Store
.tags
.ipynb_checkpoints
.idea
model2.png
*.d
*.pyc
*.pyo
.*.swp
.*.swo
.*.un~
*.o
*.so
*.a
*.clb
*.class
*.pyxbldc
*.vcd
config.json
clcache
board/obj/
selfdrive/boardd/boardd
selfdrive/logcatd/logcatd
selfdrive/proclogd/proclogd
selfdrive/ui/ui
/src/

9
.gitmodules vendored Normal file
View File

@@ -0,0 +1,9 @@
[submodule "panda"]
path = panda
url = https://github.com/commaai/panda.git
[submodule "opendbc"]
path = opendbc
url = https://github.com/commaai/opendbc.git
[submodule "pyextra"]
path = pyextra
url = https://github.com/commaai/openpilot-pyextra.git

12
.travis.yml Normal file
View File

@@ -0,0 +1,12 @@
sudo: required
services:
- docker
install:
- docker build -t tmppilot -f Dockerfile.openpilot .
script:
- docker run --rm
-v "$(pwd)"/selfdrive/test/plant/out:/tmp/openpilot/selfdrive/test/plant/out
tmppilot /bin/sh -c 'cd /tmp/openpilot/selfdrive/test/plant && ./runtest.sh'

13
Dockerfile.openpilot Normal file
View File

@@ -0,0 +1,13 @@
FROM ubuntu:16.04
ENV PYTHONUNBUFFERED 1
RUN apt-get update && apt-get install -y build-essential clang vim screen wget bzip2 git libglib2.0-0 python-pip capnproto libcapnp-dev libzmq5-dev libffi-dev
RUN pip install numpy==1.11.2 scipy==0.18.1 matplotlib
COPY requirements_openpilot.txt /tmp/
RUN pip install -r /tmp/requirements_openpilot.txt
ENV PYTHONPATH /tmp/openpilot:$PYTHONPATH
COPY . /tmp/openpilot

View File

@@ -1,4 +1,4 @@
Copyright (c) 2016, comma.ai
Copyright (c) 2016, Comma.ai, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

6
Makefile Normal file
View File

@@ -0,0 +1,6 @@
.PHONY: all
# TODO: Add a global build system to openpilot
all:
cd /data/openpilot/selfdrive && PYTHONPATH=/data/openpilot PREPAREONLY=1 /data/openpilot/selfdrive/manager.py

View File

@@ -7,60 +7,73 @@ Currently it performs the functions of Adaptive Cruise Control (ACC) and Lane Ke
The openpilot codebase has been written to be concise and enable rapid prototyping. We look forward to your contributions - improving real vehicle automation has never been easier.
Here are [some](https://www.youtube.com/watch?v=9OwTJFuDI7g) [videos](https://www.youtube.com/watch?v=64Wvt5pYQmE) [of](https://www.youtube.com/watch?v=6IW7Nejsr3A) [it](https://www.youtube.com/watch?v=-VN1YcC83nA) [running](https://www.youtube.com/watch?v=EQJZvVeihZk). And a really cool [tutorial](https://www.youtube.com/watch?v=PwOnsT2UW5o).
Hardware
------
Right now openpilot supports the [neo research platform](http://github.com/commaai/neo) for vehicle control. We'd like to support [Open Source Car Control](https://github.com/PolySync/OSCC) as well.
Right now openpilot supports the [neo research platform](http://github.com/commaai/neo) for vehicle control. We'd like to support other platforms as well.
To install it on the NEO:
```bash
# Requires working adb in PATH
cd installation
./install.sh
```
Install openpilot on a neo device by entering ``https://openpilot.comma.ai`` during NEOS setup.
Supported Cars
------
- Acura ILX 2016 with AcuraWatch Plus
- Limitations: Due to use of the cruise control for gas, it can only be enabled above 25 mph
- Due to use of the cruise control for gas, it can only be enabled above 25 mph
- Honda Civic 2016 Touring Edition
- Limitations: Due to limitations in steering firmware, steering is disabled below 18 mph
- Honda Civic 2016 with Honda Sensing
- Due to limitations in steering firmware, steering is disabled below 12 mph
- Honda CR-V Touring 2015-2016 (very alpha!)
- Can only be enabled above 25 mph
Directory structure
------
- board -- Code that runs on the USB interface board
- cereal -- The messaging spec used for all logs on the phone
- common -- Library like functionality we've developed here
- dbcs -- Files showing how to interpret data from cars
- installation -- Installation on the neo platform
- opendbc -- Files showing how to interpret data from cars
- panda -- Code used to communicate on CAN and LIN
- phonelibs -- Libraries used on the phone
- selfdrive -- Code needed to drive the car
- assets -- Fonts for ui
- boardd -- Daemon to talk to the board
- calibrationd -- Camera calibration server
- car -- Code that talks to the car and implements CarInterface
- common -- Shared C/C++ code for the daemons
- controls -- Python controls (PID loops etc) for the car
- debug -- Tools to help you debug and do car ports
- logcatd -- Android logcat as a service
- loggerd -- Logger and uploader of car data
- proclogd -- Logs information from proc
- radar -- Code that talks to the radar and implements RadarInterface
- sensord -- IMU / GPS interface code
- test/plant -- Car simulator running code through virtual maneuvers
- ui -- The UI
- visiond -- embedded vision pipeline
To understand how the services interact, see `common/services.py`
To understand how the services interact, see `selfdrive/service_list.yaml`
Testing on PC
------
There is rudimentary infrastructure to run a basic simulation and generate a report of openpilot's behavior in different scenarios.
```bash
# Requires working docker
./run_docker_tests.sh
```
The results are written to `selfdrive/test/plant/out/index.html`
More extensive testing infrastructure and simulation environments are coming soon.
Adding Car Support
------
It should be relatively easy to add support for the Honda CR-V Touring. The brake message is the same. Steering has a slightly different message with a different message id. Sniff CAN while using LKAS to find it.
The Honda Accord uses different signalling for the steering and probably requires new hardware.
Adding other manufacturers besides Honda/Acura is doable but will be more of an undertaking.
comma.ai offers [bounties](http://comma.ai/bounties.html) for adding additional car support.
CR-V Touring support came in through this program. Chevy Volt is close. Accord is close as well.
User Data / chffr Account / Crash Reporting
------
@@ -81,13 +94,15 @@ We welcome both pull requests and issues on
[github](http://github.com/commaai/openpilot). See the TODO file for a list of
good places to start.
Want to get paid to work on openpilot? [comma.ai is hiring](http://comma.ai/positions.html)
Licensing
------
openpilot is released under the MIT license.
Any user of this software shall indemnify and hold harmless Comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys fees and costs) which arise out of, relate to or result from any use of this software by user.
**THIS IS ALPHA QUALITY SOFTWARE FOR RESEARCH PURPOSES ONLY. THIS IS NOT A PRODUCT.
YOU ARE RESPONSIBLE FOR COMPLYING WITH LOCAL LAWS AND REGULATIONS.
NO WARRANTY EXPRESSED OR IMPLIED.**

105
RELEASES.md Normal file
View File

@@ -0,0 +1,105 @@
Version 0.3.4 (2017-07-28)
==========================
* Improved model trained on more data
* Much improved controls tuning
* Performance improvements
* Bugfixes and improvements to calibration
* Driving log can play back video
* Acura only: system now stays engaged below 25mph as long as brakes are applied
Version 0.3.3 (2017-06-28)
===========================
* Improved model trained on more data
* Alpha CR-V support thanks to energee and johnnwvs!
* Using the opendbc project for DBC files
* Minor performance improvements
* UI update thanks to pjlao307
* Power off button
* 6% more torque on the Civic
Version 0.3.2 (2017-05-22)
===========================
* Minor stability bugfixes
* Added metrics and rear view mirror disable to settings
* Update model with more crowdsourced data
Version 0.3.1 (2017-05-17)
===========================
* visiond stability bugfix
* Add logging for angle and flashing
Version 0.3.0 (2017-05-12)
===========================
* Add CarParams struct to improve the abstraction layer
* Refactor visiond IPC to support multiple clients
* Add raw GPS and beginning support for navigation
* Improve model in visiond using crowdsourced data
* Add improved system logging to diagnose instability
* Rewrite baseui in React Native
* Moved calibration to the cloud
Version 0.2.9 (2017-03-01)
===========================
* Retain compatibility with NEOS v1
Version 0.2.8 (2017-02-27)
===========================
* Fix bug where frames were being dropped in minute 71
Version 0.2.7 (2017-02-08)
===========================
* Better performance and pictures at night
* Fix ptr alignment issue in boardd
* Fix brake error light, fix crash if too cold
Version 0.2.6 (2017-01-31)
===========================
* Fix bug in visiond model execution
Version 0.2.5 (2017-01-30)
===========================
* Fix race condition in manager
Version 0.2.4 (2017-01-27)
===========================
* OnePlus 3T support
* Enable installation as NEOS app
* Various minor bugfixes
Version 0.2.3 (2017-01-11)
===========================
* Reduce space usage by 80%
* Add better logging
* Add Travis CI
Version 0.2.2 (2017-01-10)
===========================
* Board triggers started signal on CAN messages
* Improved autoexposure
* Handle out of space, improve upload status
Version 0.2.1 (2016-12-14)
===========================
* Performance improvements, removal of more numpy
* Fix boardd process priority
* Make counter timer reset on use of steering wheel
Version 0.2 (2016-12-12)
=========================
* Car/Radar abstraction layers have shipped, see cereal/car.capnp
* controlsd has been refactored
* Shipped plant model and testing maneuvers
* visiond exits more gracefully now
* Hardware encoder in visiond should always init
* ui now turns off the screen after 30 seconds
* Switch to openpilot release branch for future releases
* Added preliminary Docker container to run tests on PC
Version 0.1 (2016-11-29)
=========================
* Initial release of openpilot
* Adaptive cruise control is working
* Lane keep assist is working
* Support for Acura ILX 2016 with AcuraWatch Plus
* Support for Honda Civic 2016 Touring Edition

14
TODO.md
View File

@@ -1,14 +0,0 @@
TODO
======
An incomplete list of known issues and desired featues.
- TX and RX amounts on UI are wrong for a few frames at startup because we
subtract (total sent - 0). We should initialize sent bytes before displaying.
- Rewrite common/dbc.py to be faster and cleaner, potentially in C++.
- Add module and class level documentation where appropriate.
- Fix lock file cleanup so there isn't always 1 pending upload when the vehicle
shuts off.

BIN
apk/com.baseui.apk Normal file

Binary file not shown.

View File

@@ -1,43 +0,0 @@
# :set noet
PROJ_NAME = comma
CFLAGS = -g -O0 -Wall
CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3
CFLAGS += -msoft-float -DSTM32F2 -DSTM32F205xx
CFLAGS += -I inc -nostdlib
CFLAGS += -Tstm32_flash.ld
CC = arm-none-eabi-gcc
OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump
MACHINE = $(shell uname -m)
all: obj/$(PROJ_NAME).bin
#$(OBJDUMP) -d obj/$(PROJ_NAME).elf
./tools/enter_download_mode.py
./tools/dfu-util-$(MACHINE) -a 0 -s 0x08000000 -D $<
./tools/dfu-util-$(MACHINE) --reset-stm32 -a 0 -s 0x08000000
ifneq ($(wildcard ../.git/HEAD),)
obj/gitversion.h: ../.git/HEAD ../.git/index
echo "const uint8_t gitversion[] = \"$(shell git rev-parse HEAD)\";" > $@
else
obj/gitversion.h:
echo "const uint8_t gitversion[] = \"RELEASE\";" > $@
endif
obj/main.o: main.c *.h obj/gitversion.h
$(CC) $(CFLAGS) -o $@ -c $<
obj/startup_stm32f205xx.o: startup_stm32f205xx.s
mkdir -p obj
$(CC) $(CFLAGS) -o $@ -c $<
obj/$(PROJ_NAME).bin: obj/startup_stm32f205xx.o obj/main.o
$(CC) $(CFLAGS) -o obj/$(PROJ_NAME).elf $^
$(OBJCOPY) -v -O binary obj/$(PROJ_NAME).elf $@
clean:
rm -f obj/*

View File

@@ -1,38 +0,0 @@
// ACCEL1 = ADC10
// ACCEL2 = ADC11
// VOLT_S = ADC12
// CURR_S = ADC13
#define ADCCHAN_ACCEL0 10
#define ADCCHAN_ACCEL1 11
#define ADCCHAN_VOLTAGE 12
#define ADCCHAN_CURRENT 13
void adc_init() {
// global setup
ADC->CCR = ADC_CCR_TSVREFE | ADC_CCR_VBATE;
//ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_EOCS | ADC_CR2_DDS;
ADC1->CR2 = ADC_CR2_ADON;
// long
ADC1->SMPR1 = ADC_SMPR1_SMP10 | ADC_SMPR1_SMP11 | ADC_SMPR1_SMP12 | ADC_SMPR1_SMP13;
}
uint32_t adc_get(int channel) {
// includes length
//ADC1->SQR1 = 0;
// select channel
ADC1->JSQR = channel << 15;
//ADC1->CR1 = ADC_CR1_DISCNUM_0;
//ADC1->CR1 = ADC_CR1_EOCIE;
ADC1->SR &= ~(ADC_SR_JEOC);
ADC1->CR2 |= ADC_CR2_JSWSTART;
while (!(ADC1->SR & ADC_SR_JEOC));
return ADC1->JDR1;
}

View File

@@ -1,75 +0,0 @@
void can_init(CAN_TypeDef *CAN) {
CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
puts("CAN initting\n");
// PCLK = 24000000, 500000 is 48 clocks
// from http://www.bittiming.can-wiki.ino/
CAN->BTR = 0x001c0002;
// loopback mode for debugging
#ifdef CAN_LOOPBACK_MODE
CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
#endif
// reset
CAN->MCR = CAN_MCR_TTCM;
while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK);
puts("CAN init done\n");
// accept all filter
CAN->FMR |= CAN_FMR_FINIT;
// no mask
CAN->sFilterRegister[0].FR1 = 0;
CAN->sFilterRegister[0].FR2 = 0;
CAN->sFilterRegister[14].FR1 = 0;
CAN->sFilterRegister[14].FR2 = 0;
CAN->FA1R |= 1 | (1 << 14);
CAN->FMR &= ~(CAN_FMR_FINIT);
// enable all CAN interrupts
CAN->IER = 0xFFFFFFFF;
//CAN->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_FMPIE1;
}
// CAN error
void can_sce(CAN_TypeDef *CAN) {
#ifdef DEBUG
puts("MSR:");
puth(CAN->MSR);
puts(" TSR:");
puth(CAN->TSR);
puts(" RF0R:");
puth(CAN->RF0R);
puts(" RF1R:");
puth(CAN->RF1R);
puts(" ESR:");
puth(CAN->ESR);
puts("\n");
#endif
// clear
//CAN->sTxMailBox[0].TIR &= ~(CAN_TI0R_TXRQ);
CAN->TSR |= CAN_TSR_ABRQ0;
//CAN->ESR |= CAN_ESR_LEC;
//CAN->MSR &= ~(CAN_MSR_ERRI);
CAN->MSR = CAN->MSR;
}
int can_cksum(uint8_t *dat, int len, int addr, int idx) {
int i;
int s = 0;
for (i = 0; i < len; i++) {
s += (dat[i] >> 4);
s += dat[i] & 0xF;
}
s += (addr>>0)&0xF;
s += (addr>>4)&0xF;
s += (addr>>8)&0xF;
s += idx;
s = 8-s;
return s&0xF;
}

View File

@@ -1,16 +0,0 @@
void dac_init() {
// no buffers required since we have an opamp
//DAC->CR = DAC_CR_EN1 | DAC_CR_BOFF1 | DAC_CR_EN2 | DAC_CR_BOFF2;
DAC->DHR12R1 = 0;
DAC->DHR12R2 = 0;
DAC->CR = DAC_CR_EN1 | DAC_CR_EN2;
}
void dac_set(int channel, uint32_t value) {
if (channel == 0) {
DAC->DHR12R1 = value;
} else if (channel == 1) {
DAC->DHR12R2 = value;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,609 +0,0 @@
/**************************************************************************//**
* @file core_cmFunc.h
* @brief CMSIS Cortex-M Core Function Access Header File
* @version V2.10
* @date 26. July 2011
*
* @note
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __CORE_CMFUNC_H
#define __CORE_CMFUNC_H
/* ########################### Core Function Access ########################### */
/** \ingroup CMSIS_Core_FunctionInterface
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/* intrinsic void __enable_irq(); */
/* intrinsic void __disable_irq(); */
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
static __INLINE uint32_t __get_CONTROL(void)
{
register uint32_t __regControl __ASM("control");
return(__regControl);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
static __INLINE void __set_CONTROL(uint32_t control)
{
register uint32_t __regControl __ASM("control");
__regControl = control;
}
/** \brief Get ISPR Register
This function returns the content of the ISPR Register.
\return ISPR Register value
*/
static __INLINE uint32_t __get_IPSR(void)
{
register uint32_t __regIPSR __ASM("ipsr");
return(__regIPSR);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
static __INLINE uint32_t __get_APSR(void)
{
register uint32_t __regAPSR __ASM("apsr");
return(__regAPSR);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
static __INLINE uint32_t __get_xPSR(void)
{
register uint32_t __regXPSR __ASM("xpsr");
return(__regXPSR);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
static __INLINE uint32_t __get_PSP(void)
{
register uint32_t __regProcessStackPointer __ASM("psp");
return(__regProcessStackPointer);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
static __INLINE void __set_PSP(uint32_t topOfProcStack)
{
register uint32_t __regProcessStackPointer __ASM("psp");
__regProcessStackPointer = topOfProcStack;
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
static __INLINE uint32_t __get_MSP(void)
{
register uint32_t __regMainStackPointer __ASM("msp");
return(__regMainStackPointer);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
static __INLINE void __set_MSP(uint32_t topOfMainStack)
{
register uint32_t __regMainStackPointer __ASM("msp");
__regMainStackPointer = topOfMainStack;
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
static __INLINE uint32_t __get_PRIMASK(void)
{
register uint32_t __regPriMask __ASM("primask");
return(__regPriMask);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
static __INLINE void __set_PRIMASK(uint32_t priMask)
{
register uint32_t __regPriMask __ASM("primask");
__regPriMask = (priMask);
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __enable_fault_irq __enable_fiq
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
#define __disable_fault_irq __disable_fiq
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
static __INLINE uint32_t __get_BASEPRI(void)
{
register uint32_t __regBasePri __ASM("basepri");
return(__regBasePri);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
static __INLINE void __set_BASEPRI(uint32_t basePri)
{
register uint32_t __regBasePri __ASM("basepri");
__regBasePri = (basePri & 0xff);
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
static __INLINE uint32_t __get_FAULTMASK(void)
{
register uint32_t __regFaultMask __ASM("faultmask");
return(__regFaultMask);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
static __INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
__regFaultMask = (faultMask & (uint32_t)1);
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
static __INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
static __INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief Enable IRQ Interrupts
This function enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __enable_irq(void)
{
__ASM volatile ("cpsie i");
}
/** \brief Disable IRQ Interrupts
This function disables IRQ interrupts by setting the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __disable_irq(void)
{
__ASM volatile ("cpsid i");
}
/** \brief Get Control Register
This function returns the content of the Control Register.
\return Control Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_CONTROL(void)
{
uint32_t result;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/** \brief Set Control Register
This function writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
/** \brief Get ISPR Register
This function returns the content of the ISPR Register.
\return ISPR Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_IPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, ipsr" : "=r" (result) );
return(result);
}
/** \brief Get APSR Register
This function returns the content of the APSR Register.
\return APSR Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_APSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, apsr" : "=r" (result) );
return(result);
}
/** \brief Get xPSR Register
This function returns the content of the xPSR Register.
\return xPSR Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_xPSR(void)
{
uint32_t result;
__ASM volatile ("MRS %0, xpsr" : "=r" (result) );
return(result);
}
/** \brief Get Process Stack Pointer
This function returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_PSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, psp\n" : "=r" (result) );
return(result);
}
/** \brief Set Process Stack Pointer
This function assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) );
}
/** \brief Get Main Stack Pointer
This function returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_MSP(void)
{
register uint32_t result;
__ASM volatile ("MRS %0, msp\n" : "=r" (result) );
return(result);
}
/** \brief Set Main Stack Pointer
This function assigns the given value to the Main Stack Pointer (MSP).
\param [in] topOfMainStack Main Stack Pointer value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) );
}
/** \brief Get Priority Mask
This function returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_PRIMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/** \brief Set Priority Mask
This function assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
#if (__CORTEX_M >= 0x03)
/** \brief Enable FIQ
This function enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __enable_fault_irq(void)
{
__ASM volatile ("cpsie f");
}
/** \brief Disable FIQ
This function disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __disable_fault_irq(void)
{
__ASM volatile ("cpsid f");
}
/** \brief Get Base Priority
This function returns the current value of the Base Priority register.
\return Base Priority register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_BASEPRI(void)
{
uint32_t result;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/** \brief Set Base Priority
This function assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/** \brief Get Fault Mask
This function returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_FAULTMASK(void)
{
uint32_t result;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/** \brief Set Fault Mask
This function assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
#endif /* (__CORTEX_M >= 0x03) */
#if (__CORTEX_M == 0x04)
/** \brief Get FPSCR
This function returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __get_FPSCR(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
uint32_t result;
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
return(result);
#else
return(0);
#endif
}
/** \brief Set FPSCR
This function assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
__attribute__( ( always_inline ) ) static __INLINE void __set_FPSCR(uint32_t fpscr)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
__ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) );
#endif
}
#endif /* (__CORTEX_M == 0x04) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
/*@} end of CMSIS_Core_RegAccFunctions */
#endif /* __CORE_CMFUNC_H */

View File

@@ -1,585 +0,0 @@
/**************************************************************************//**
* @file core_cmInstr.h
* @brief CMSIS Cortex-M Core Instruction Access Header File
* @version V2.10
* @date 19. July 2011
*
* @note
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#ifndef __CORE_CMINSTR_H
#define __CORE_CMINSTR_H
/* ########################## Core Instruction Access ######################### */
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
Access to dedicated instructions
@{
*/
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
#if (__ARMCC_VERSION < 400677)
#error "Please use ARM Compiler Toolchain V4.0.677 or later!"
#endif
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
#define __NOP __nop
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
#define __WFI __wfi
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
#define __WFE __wfe
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
#define __SEV __sev
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
#define __ISB() __isb(0xF)
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
#define __DSB() __dsb(0xF)
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
#define __DMB() __dmb(0xF)
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __REV __rev
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
static __INLINE __ASM uint32_t __REV16(uint32_t value)
{
rev16 r0, r0
bx lr
}
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
static __INLINE __ASM int32_t __REVSH(int32_t value)
{
revsh r0, r0
bx lr
}
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
#define __RBIT __rbit
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXB(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXH(value, ptr) __strex(value, ptr)
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
#define __STREXW(value, ptr) __strex(value, ptr)
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
#define __CLREX __clrex
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT __ssat
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT __usat
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
#define __CLZ __clz
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#include <cmsis_iar.h>
#elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/** \brief No Operation
No Operation does nothing. This instruction can be used for code alignment purposes.
*/
__attribute__( ( always_inline ) ) static __INLINE void __NOP(void)
{
__ASM volatile ("nop");
}
/** \brief Wait For Interrupt
Wait For Interrupt is a hint instruction that suspends execution
until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) static __INLINE void __WFI(void)
{
__ASM volatile ("wfi");
}
/** \brief Wait For Event
Wait For Event is a hint instruction that permits the processor to enter
a low-power state until one of a number of events occurs.
*/
__attribute__( ( always_inline ) ) static __INLINE void __WFE(void)
{
__ASM volatile ("wfe");
}
/** \brief Send Event
Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
__attribute__( ( always_inline ) ) static __INLINE void __SEV(void)
{
__ASM volatile ("sev");
}
/** \brief Instruction Synchronization Barrier
Instruction Synchronization Barrier flushes the pipeline in the processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed.
*/
__attribute__( ( always_inline ) ) static __INLINE void __ISB(void)
{
__ASM volatile ("isb");
}
/** \brief Data Synchronization Barrier
This function acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
__attribute__( ( always_inline ) ) static __INLINE void __DSB(void)
{
__ASM volatile ("dsb");
}
/** \brief Data Memory Barrier
This function ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
__attribute__( ( always_inline ) ) static __INLINE void __DMB(void)
{
__ASM volatile ("dmb");
}
/** \brief Reverse byte order (32 bit)
This function reverses the byte order in integer value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __REV(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief Reverse byte order (16 bit)
This function reverses the byte order in two unsigned short values.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief Reverse byte order in signed short value
This function reverses the byte order in a signed short value with sign extension to integer.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) static __INLINE int32_t __REVSH(int32_t value)
{
uint32_t result;
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
return((int32_t)result);
}
#if (__CORTEX_M >= 0x03)
/** \brief Reverse bit order of value
This function reverses the bit order of the given value.
\param [in] value Value to reverse
\return Reversed value
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/** \brief LDR Exclusive (8 bit)
This function performs a exclusive LDR command for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
__attribute__( ( always_inline ) ) static __INLINE uint8_t __LDREXB(volatile uint8_t *addr)
{
uint8_t result;
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief LDR Exclusive (16 bit)
This function performs a exclusive LDR command for 16 bit values.
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
__attribute__( ( always_inline ) ) static __INLINE uint16_t __LDREXH(volatile uint16_t *addr)
{
uint16_t result;
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief LDR Exclusive (32 bit)
This function performs a exclusive LDR command for 32 bit values.
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __LDREXW(volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/** \brief STR Exclusive (8 bit)
This function performs a exclusive STR command for 8 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
uint32_t result;
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief STR Exclusive (16 bit)
This function performs a exclusive STR command for 16 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
{
uint32_t result;
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief STR Exclusive (32 bit)
This function performs a exclusive STR command for 32 bit values.
\param [in] value Value to store
\param [in] ptr Pointer to location
\return 0 Function succeeded
\return 1 Function failed
*/
__attribute__( ( always_inline ) ) static __INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
{
uint32_t result;
__ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/** \brief Remove the exclusive lock
This function removes the exclusive lock which is created by LDREX.
*/
__attribute__( ( always_inline ) ) static __INLINE void __CLREX(void)
{
__ASM volatile ("clrex");
}
/** \brief Signed Saturate
This function saturates a signed value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Unsigned Saturate
This function saturates an unsigned value.
\param [in] value Value to be saturated
\param [in] sat Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT(ARG1,ARG2) \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
/** \brief Count leading zeros
This function counts the number of leading zeros of a data value.
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
__attribute__( ( always_inline ) ) static __INLINE uint8_t __CLZ(uint32_t value)
{
uint8_t result;
__ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
#endif /* (__CORTEX_M >= 0x03) */
#elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all intrinsics,
* Including the CMSIS ones.
*/
#endif
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
#endif /* __CORE_CMINSTR_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,197 +0,0 @@
/**
******************************************************************************
* @file stm32f2xx.h
* @author MCD Application Team
* @version V2.0.1
* @date 25-March-2014
* @brief CMSIS STM32F2xx Device Peripheral Access Layer Header File.
*
* The file is the unique include file that the application programmer
* is using in the C source code, usually in main.c. This file contains:
* - Configuration section that allows to select:
* - The STM32F2xx device used in the target application
* - To use or not the peripheral's drivers in application code(i.e.
* code will be based on direct access to peripheral's registers
* rather than drivers API), this option is controlled by
* "#define USE_HAL_DRIVER"
*
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f2xx
* @{
*/
#ifndef __STM32F2xx_H
#define __STM32F2xx_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** @addtogroup Library_configuration_section
* @{
*/
/* Uncomment the line below according to the target STM32 device used in your
application
*/
#if !defined (STM32F205xx) && !defined (STM32F215xx) && !defined (STM32F207xx) && !defined (STM32F217xx)
/* #define STM32F205xx */ /*!< STM32Fxx Devices */
/* #define STM32F215xx */ /*!< STM32Fxx Devices */
/* #define STM32F207xx */ /*!< STM32Fxx Devices */
/* #define STM32F217xx */ /*!< STM32Fxx Devices */
#endif
/* Tip: To avoid modifying this file each time you need to switch between these
devices, you can define the device in your toolchain compiler preprocessor.
*/
#if !defined (USE_HAL_DRIVER)
/**
* @brief Comment the line below if you will not use the peripherals drivers.
In this case, these drivers will not be included and the application code will
be based on direct access to peripherals registers
*/
/*#define USE_HAL_DRIVER */
#endif /* USE_HAL_DRIVER */
/**
* @brief CMSIS Device version number V2.0.1
*/
#define __STM32F2xx_CMSIS_DEVICE_VERSION_MAIN (0x02) /*!< [31:24] main version */
#define __STM32F2xx_CMSIS_DEVICE_VERSION_SUB1 (0x00) /*!< [23:16] sub1 version */
#define __STM32F2xx_CMSIS_DEVICE_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */
#define __STM32F2xx_CMSIS_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */
#define __STM32F2xx_CMSIS_DEVICE_VERSION ((__CMSIS_DEVICE_VERSION_MAIN << 24)\
|(__CMSIS_DEVICE_HAL_VERSION_SUB1 << 16)\
|(__CMSIS_DEVICE_HAL_VERSION_SUB2 << 8 )\
|(__CMSIS_DEVICE_HAL_VERSION_RC))
/**
* @}
*/
/** @addtogroup Device_Included
* @{
*/
#if defined(STM32F205xx)
#include "stm32f205xx.h"
#elif defined(STM32F215xx)
#include "stm32f215xx.h"
#elif defined(STM32F207xx)
#include "stm32f207xx.h"
#elif defined(STM32F217xx)
#include "stm32f217xx.h"
#else
#error "Please select first the target STM32F2xx device used in your application (in stm32f2xx.h file)"
#endif
/**
* @}
*/
/** @addtogroup Exported_types
* @{
*/
typedef enum
{
RESET = 0,
SET = !RESET
} FlagStatus, ITStatus;
typedef enum
{
DISABLE = 0,
ENABLE = !DISABLE
} FunctionalState;
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
typedef enum
{
ERROR = 0,
SUCCESS = !ERROR
} ErrorStatus;
/**
* @}
*/
/** @addtogroup Exported_macro
* @{
*/
#define SET_BIT(REG, BIT) ((REG) |= (BIT))
#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT))
#define READ_BIT(REG, BIT) ((REG) & (BIT))
#define CLEAR_REG(REG) ((REG) = (0x0))
#define WRITE_REG(REG, VAL) ((REG) = (VAL))
#define READ_REG(REG) ((REG))
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL)))
/**
* @}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __STM32F2xx_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -1,99 +0,0 @@
/**
******************************************************************************
* @file system_stm32f2xx.h
* @author MCD Application Team
* @version V1.0.0
* @date 18-April-2011
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f2xx_system
* @{
*/
/**
* @brief Define to prevent recursive inclusion
*/
#ifndef __SYSTEM_STM32F2XX_H
#define __SYSTEM_STM32F2XX_H
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup STM32F2xx_System_Includes
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F2xx_System_Exported_types
* @{
*/
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/**
* @}
*/
/** @addtogroup STM32F2xx_System_Exported_Constants
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F2xx_System_Exported_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F2xx_System_Exported_Functions
* @{
*/
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /*__SYSTEM_STM32F2XX_H */
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

View File

@@ -1,226 +0,0 @@
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#define __DIV(_PCLK_, _BAUD_) (((_PCLK_)*25)/(4*(_BAUD_)))
#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_))/100)
#define __DIVFRAQ(_PCLK_, _BAUD_) (((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100)) * 16 + 50) / 100)
#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4)|(__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0F))
#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */
#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */
#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */
#define GPIO_AF9_CAN1 ((uint8_t)0x09) /* CAN1 Alternate Function mapping */
#define GPIO_AF10_OTG_FS ((uint8_t)0xA) /* OTG_FS Alternate Function mapping */
#define GPIO_AF12_OTG_HS_FS ((uint8_t)0xC) /* OTG HS configured in FS */
#ifdef OLD_BOARD
#define USART USART2
#else
#define USART USART3
#endif
// **** shitty libc ****
void clock_init() {
#ifdef USE_INTERNAL_OSC
// enable internal oscillator
RCC->CR |= RCC_CR_HSION;
while ((RCC->CR & RCC_CR_HSIRDY) == 0);
#else
// enable external oscillator
RCC->CR |= RCC_CR_HSEON;
while ((RCC->CR & RCC_CR_HSERDY) == 0);
#endif
// divide shit
RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4;
#ifdef USE_INTERNAL_OSC
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSI;
#else
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLSRC_HSE;
#endif
// start PLL
RCC->CR |= RCC_CR_PLLON;
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
// Configure Flash prefetch, Instruction cache, Data cache and wait state
// *** without this, it breaks ***
FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
// switch to PLL
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
// *** running on PLL ***
// enable GPIOB, UART2, CAN, USB clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
RCC->APB1ENR |= RCC_APB1ENR_CAN2EN;
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
//RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
// turn on alt USB
RCC->AHB1ENR |= RCC_AHB1ENR_OTGHSEN;
// fix interrupt vectors
}
// board specific
void gpio_init() {
// analog mode
GPIOC->MODER = GPIO_MODER_MODER3 | GPIO_MODER_MODER2 |
GPIO_MODER_MODER1 | GPIO_MODER_MODER0;
// FAN on C9, aka TIM3_CH4
#ifdef OLD_BOARD
GPIOC->MODER |= GPIO_MODER_MODER9_1;
GPIOC->AFR[1] = GPIO_AF2_TIM3 << ((9-8)*4);
#else
GPIOC->MODER |= GPIO_MODER_MODER8_1;
GPIOC->AFR[1] = GPIO_AF2_TIM3 << ((8-8)*4);
#endif
// IGNITION on C13
// set mode for LEDs and CAN
GPIOB->MODER = GPIO_MODER_MODER10_0 | GPIO_MODER_MODER11_0;
// CAN 2
GPIOB->MODER |= GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1;
// CAN 1
GPIOB->MODER |= GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1;
// CAN enables
GPIOB->MODER |= GPIO_MODER_MODER3_0 | GPIO_MODER_MODER4_0;
// set mode for SERIAL and USB (DAC should be configured to in)
GPIOA->MODER = GPIO_MODER_MODER2_1 | GPIO_MODER_MODER3_1;
GPIOA->AFR[0] = GPIO_AF7_USART2 << (2*4) | GPIO_AF7_USART2 << (3*4);
// GPIOC USART3
GPIOC->MODER |= GPIO_MODER_MODER10_1 | GPIO_MODER_MODER11_1;
GPIOC->AFR[1] |= GPIO_AF7_USART3 << ((10-8)*4) | GPIO_AF7_USART3 << ((11-8)*4);
if (USBx == USB_OTG_FS) {
GPIOA->MODER |= GPIO_MODER_MODER11_1 | GPIO_MODER_MODER12_1;
GPIOA->OSPEEDR = GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12;
GPIOA->AFR[1] = GPIO_AF10_OTG_FS << ((11-8)*4) | GPIO_AF10_OTG_FS << ((12-8)*4);
}
GPIOA->PUPDR = GPIO_PUPDR_PUPDR2_0 | GPIO_PUPDR_PUPDR3_0;
// set mode for CAN / USB_HS pins
GPIOB->AFR[0] = GPIO_AF9_CAN1 << (5*4) | GPIO_AF9_CAN1 << (6*4);
GPIOB->AFR[1] = GPIO_AF9_CAN1 << ((8-8)*4) | GPIO_AF9_CAN1 << ((9-8)*4);
if (USBx == USB_OTG_HS) {
GPIOB->AFR[1] |= GPIO_AF12_OTG_HS_FS << ((15-8)*4) | GPIO_AF12_OTG_HS_FS << ((14-8)*4);
GPIOB->MODER |= GPIO_MODER_MODER14_1 | GPIO_MODER_MODER15_1;
}
GPIOB->OSPEEDR = GPIO_OSPEEDER_OSPEEDR14 | GPIO_OSPEEDER_OSPEEDR15;
// enable CAN busses
GPIOB->ODR |= (1 << 3) | (1 << 4);
// enable OTG out tied to ground
GPIOA->ODR = 0;
GPIOA->MODER |= GPIO_MODER_MODER1_0;
// enable USB power tied to +
GPIOA->ODR |= 1;
GPIOA->MODER |= GPIO_MODER_MODER0_0;
}
void uart_init() {
// enable uart and tx+rx mode
USART->CR1 = USART_CR1_UE;
USART->BRR = __USART_BRR(24000000, 115200);
USART->CR1 |= USART_CR1_TE | USART_CR1_RE;
USART->CR2 = USART_CR2_STOP_0 | USART_CR2_STOP_1;
// ** UART is ready to work **
// enable interrupts
USART->CR1 |= USART_CR1_RXNEIE;
}
void delay(int a) {
volatile int i;
for (i=0;i<a;i++);
}
void putch(const char a) {
while (!(USART->SR & USART_SR_TXE));
USART->DR = a;
}
int puts(const char *a) {
for (;*a;a++) {
if (*a == '\n') putch('\r');
putch(*a);
}
return 0;
}
void puth(unsigned int i) {
int pos;
char c[] = "0123456789abcdef";
for (pos = 28; pos != -4; pos -= 4) {
putch(c[(i >> pos) & 0xF]);
}
}
void puth2(unsigned int i) {
int pos;
char c[] = "0123456789abcdef";
for (pos = 4; pos != -4; pos -= 4) {
putch(c[(i >> pos) & 0xF]);
}
}
void hexdump(void *a, int l) {
int i;
for (i=0;i<l;i++) {
if (i != 0 && (i&0xf) == 0) puts("\n");
puth2(((unsigned char*)a)[i]);
puts(" ");
}
puts("\n");
}
void *memset(void *str, int c, unsigned int n) {
int i;
for (i = 0; i < n; i++) {
*((uint8_t*)str) = c;
++str;
}
return str;
}
void *memcpy(void *dest, const void *src, unsigned int n) {
int i;
// TODO: make not slow
for (i = 0; i < n; i++) {
((uint8_t*)dest)[i] = *(uint8_t*)src;
++src;
}
return dest;
}

View File

@@ -1,499 +0,0 @@
//#define DEBUG
//#define CAN_LOOPBACK_MODE
//#define USE_INTERNAL_OSC
//#define OLD_BOARD
#define USB_VID 0xbbaa
#define USB_PID 0xddcc
// *** end config ***
#include "stm32f2xx.h"
#include "obj/gitversion.h"
#define ENTER_BOOTLOADER_MAGIC 0xdeadbeef
uint32_t enter_bootloader_mode;
USB_OTG_GlobalTypeDef *USBx = USB_OTG_FS;
#include "libc.h"
#include "adc.h"
#include "timer.h"
#include "usb.h"
#include "can.h"
// debug safety check: is controls allowed?
int controls_allowed = 0;
int gas_interceptor_detected = 0;
// ********************* instantiate queues *********************
#define FIFO_SIZE 0x100
typedef struct {
uint8_t w_ptr;
uint8_t r_ptr;
CAN_FIFOMailBox_TypeDef elems[FIFO_SIZE];
} can_ring;
can_ring can_rx_q = { .w_ptr = 0, .r_ptr = 0 };
can_ring can_tx1_q = { .w_ptr = 0, .r_ptr = 0 };
can_ring can_tx2_q = { .w_ptr = 0, .r_ptr = 0 };
// ********************* interrupt safe queue *********************
inline int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
if (q->w_ptr != q->r_ptr) {
*elem = q->elems[q->r_ptr];
q->r_ptr += 1;
return 1;
}
return 0;
}
inline int push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
uint8_t next_w_ptr = q->w_ptr + 1;
if (next_w_ptr != q->r_ptr) {
q->elems[q->w_ptr] = *elem;
q->w_ptr = next_w_ptr;
return 1;
}
return 0;
}
// ***************************** CAN *****************************
void process_can(CAN_TypeDef *CAN, can_ring *can_q, int can_number) {
#ifdef DEBUG
puts("process CAN TX\n");
#endif
// add successfully transmitted message to my fifo
if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
CAN_FIFOMailBox_TypeDef to_push;
to_push.RIR = CAN->sTxMailBox[0].TIR;
to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((can_number+2) << 4);
to_push.RDLR = CAN->sTxMailBox[0].TDLR;
to_push.RDHR = CAN->sTxMailBox[0].TDHR;
push(&can_rx_q, &to_push);
}
// check for empty mailbox
CAN_FIFOMailBox_TypeDef to_send;
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
if (pop(can_q, &to_send)) {
// BRAKE: safety check
if ((to_send.RIR>>21) == 0x1FA) {
if (controls_allowed) {
to_send.RDLR &= 0xFFFFFF3F;
} else {
to_send.RDLR &= 0xFFFF0000;
}
}
// STEER: safety check
if ((to_send.RIR>>21) == 0xE4) {
if (controls_allowed) {
to_send.RDLR &= 0xFFFFFFFF;
} else {
to_send.RDLR &= 0xFFFF0000;
}
}
// GAS: safety check
if ((to_send.RIR>>21) == 0x200) {
if (controls_allowed) {
to_send.RDLR &= 0xFFFFFFFF;
} else {
to_send.RDLR &= 0xFFFF0000;
}
}
// only send if we have received a packet
CAN->sTxMailBox[0].TDLR = to_send.RDLR;
CAN->sTxMailBox[0].TDHR = to_send.RDHR;
CAN->sTxMailBox[0].TDTR = to_send.RDTR;
CAN->sTxMailBox[0].TIR = to_send.RIR;
}
}
// clear interrupt
CAN->TSR |= CAN_TSR_RQCP0;
}
// send more, possible for these to not trigger?
void CAN1_TX_IRQHandler() {
process_can(CAN1, &can_tx1_q, 1);
}
void CAN2_TX_IRQHandler() {
process_can(CAN2, &can_tx2_q, 0);
}
// board enforces
// in-state
// accel set/resume
// out-state
// cancel button
// all commands: brake and steering
// if controls_allowed
// allow all commands up to limit
// else
// block all commands that produce actuation
// CAN receive handlers
void can_rx(CAN_TypeDef *CAN, int can_number) {
while (CAN->RF0R & CAN_RF0R_FMP0) {
// add to my fifo
CAN_FIFOMailBox_TypeDef to_push;
to_push.RIR = CAN->sFIFOMailBox[0].RIR;
// top 16-bits is the timestamp
to_push.RDTR = (CAN->sFIFOMailBox[0].RDTR & 0xFFFF000F) | (can_number << 4);
to_push.RDLR = CAN->sFIFOMailBox[0].RDLR;
to_push.RDHR = CAN->sFIFOMailBox[0].RDHR;
// state machine to enter and exit controls
// 0x1A6 for the ILX, 0x296 for the Civic Touring
if ((to_push.RIR>>21) == 0x1A6 || (to_push.RIR>>21) == 0x296) {
int buttons = (to_push.RDLR & 0xE0) >> 5;
if (buttons == 4 || buttons == 3) {
controls_allowed = 1;
} else if (buttons == 2) {
controls_allowed = 0;
}
}
// exit controls on brake press
if ((to_push.RIR>>21) == 0x17C) {
// bit 50
if (to_push.RDHR & 0x200000) {
controls_allowed = 0;
}
}
// exit controls on gas press if interceptor
if ((to_push.RIR>>21) == 0x201) {
gas_interceptor_detected = 1;
int gas = ((to_push.RDLR & 0xFF) << 8) | ((to_push.RDLR & 0xFF00) >> 8);
if (gas > 328) {
controls_allowed = 0;
}
}
// exit controls on gas press if no interceptor
if (!gas_interceptor_detected) {
if ((to_push.RIR>>21) == 0x17C) {
if (to_push.RDLR & 0xFF) {
controls_allowed = 0;
}
}
}
push(&can_rx_q, &to_push);
// next
CAN->RF0R |= CAN_RF0R_RFOM0;
}
}
void CAN1_RX0_IRQHandler() {
//puts("CANRX1");
//delay(10000);
can_rx(CAN1, 1);
}
void CAN2_RX0_IRQHandler() {
//puts("CANRX0");
//delay(10000);
can_rx(CAN2, 0);
}
void CAN1_SCE_IRQHandler() {
//puts("CAN1_SCE\n");
can_sce(CAN1);
}
void CAN2_SCE_IRQHandler() {
//puts("CAN2_SCE\n");
can_sce(CAN2);
}
// ***************************** serial port *****************************
void USART_IRQHandler(void) {
puts("S");
// echo characters
if (USART->SR & USART_SR_RXNE) {
char rcv = USART->DR;
putch(rcv);
// jump to DFU flash
if (rcv == 'z') {
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
NVIC_SystemReset();
}
}
}
void USART2_IRQHandler(void) {
USART_IRQHandler();
}
void USART3_IRQHandler(void) {
USART_IRQHandler();
}
// ***************************** USB port *****************************
int get_health_pkt(void *dat) {
struct {
uint32_t voltage;
uint32_t current;
uint8_t started;
uint8_t controls_allowed;
uint8_t gas_interceptor_detected;
} *health = dat;
health->voltage = adc_get(ADCCHAN_VOLTAGE);
health->current = adc_get(ADCCHAN_CURRENT);
health->started = (GPIOC->IDR & (1 << 13)) != 0;
health->controls_allowed = controls_allowed;
health->gas_interceptor_detected = gas_interceptor_detected;
return sizeof(*health);
}
void set_fan_speed(int fan_speed) {
#ifdef OLD_BOARD
TIM3->CCR4 = fan_speed;
#else
TIM3->CCR3 = fan_speed;
#endif
}
void usb_cb_ep1_in(int len) {
CAN_FIFOMailBox_TypeDef reply[4];
int ilen = 0;
while (ilen < min(len/0x10, 4) && pop(&can_rx_q, &reply[ilen])) ilen++;
#ifdef DEBUG
puts("FIFO SENDING ");
puth(ilen);
puts("\n");
#endif
USB_WritePacket((void *)reply, ilen*0x10, 1);
}
void usb_cb_ep2_out(uint8_t *usbdata, int len) {
}
// send on CAN
void usb_cb_ep3_out(uint8_t *usbdata, int len) {
int dpkt = 0;
for (dpkt = 0; dpkt < len; dpkt += 0x10) {
uint32_t *tf = (uint32_t*)(&usbdata[dpkt]);
int flags = tf[1] >> 4;
CAN_TypeDef *CAN;
can_ring *can_q;
int can_number = 0;
if (flags & 1) {
CAN=CAN1;
can_q = &can_tx1_q;
can_number = 1;
} else {
CAN=CAN2;
can_q = &can_tx2_q;
}
// add CAN packet to send queue
CAN_FIFOMailBox_TypeDef to_push;
to_push.RDHR = tf[3];
to_push.RDLR = tf[2];
to_push.RDTR = tf[1] & 0xF;
to_push.RIR = tf[0];
push(can_q, &to_push);
process_can(CAN, can_q, can_number);
}
}
void usb_cb_control_msg() {
uint8_t resp[0x20];
int resp_len;
switch (setup.b.bRequest) {
case 0xd1:
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
NVIC_SystemReset();
break;
case 0xd2:
resp_len = get_health_pkt(resp);
USB_WritePacket(resp, resp_len, 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
case 0xd3:
set_fan_speed(setup.b.wValue.w);
USB_WritePacket(0, 0, 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
case 0xd6: // GET_VERSION
USB_WritePacket(gitversion, min(sizeof(gitversion), setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
case 0xd8: // RESET
NVIC_SystemReset();
break;
default:
puts("NO HANDLER ");
puth(setup.b.bRequest);
puts("\n");
break;
}
}
void OTG_FS_IRQHandler(void) {
NVIC_DisableIRQ(OTG_FS_IRQn);
//__disable_irq();
usb_irqhandler();
//__enable_irq();
NVIC_EnableIRQ(OTG_FS_IRQn);
}
void OTG_HS_IRQHandler(void) {
//puts("HS_IRQ\n");
NVIC_DisableIRQ(OTG_FS_IRQn);
//__disable_irq();
usb_irqhandler();
//__enable_irq();
NVIC_EnableIRQ(OTG_FS_IRQn);
}
void ADC_IRQHandler(void) {
puts("ADC_IRQ\n");
}
// ***************************** main code *****************************
void __initialize_hardware_early() {
// set USB power + and OTG mode
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// enable OTG out tied to ground
GPIOA->ODR = 0;
GPIOA->MODER |= GPIO_MODER_MODER1_0;
// enable USB power tied to +
GPIOA->ODR |= 1;
GPIOA->MODER |= GPIO_MODER_MODER0_0;
// enable pull DOWN on OTG_FS_DP
// must be done a while before reading it
GPIOA->PUPDR = GPIO_PUPDR_PUPDR12_1;
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
enter_bootloader_mode = 0;
void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *)0x1fff0004));
// jump to bootloader
bootloader();
// LOOP
while(1);
}
}
int main() {
// init devices
clock_init();
// test the USB choice before GPIO init
if (GPIOA->IDR & (1 << 12)) {
USBx = USB_OTG_HS;
}
gpio_init();
uart_init();
usb_init();
can_init(CAN1);
can_init(CAN2);
adc_init();
// timer for fan PWM
#ifdef OLD_BOARD
TIM3->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1;
TIM3->CCER = TIM_CCER_CC4E;
#else
TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1;
TIM3->CCER = TIM_CCER_CC3E;
#endif
// max value of the timer
// 64 makes it above the audible range
//TIM3->ARR = 64;
// 10 prescale makes it below the audible range
timer_init(TIM3, 10);
// set PWM
set_fan_speed(65535);
puts("**** INTERRUPTS ON ****\n");
__disable_irq();
NVIC_EnableIRQ(USART2_IRQn);
NVIC_EnableIRQ(USART3_IRQn);
NVIC_EnableIRQ(OTG_FS_IRQn);
NVIC_EnableIRQ(OTG_HS_IRQn);
NVIC_EnableIRQ(ADC_IRQn);
// CAN has so many interrupts!
NVIC_EnableIRQ(CAN1_TX_IRQn);
NVIC_EnableIRQ(CAN1_RX0_IRQn);
NVIC_EnableIRQ(CAN1_SCE_IRQn);
NVIC_EnableIRQ(CAN2_TX_IRQn);
NVIC_EnableIRQ(CAN2_RX0_IRQn);
NVIC_EnableIRQ(CAN2_SCE_IRQn);
__enable_irq();
// LED should keep on blinking all the time
while (1) {
#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
/*puts("voltage: "); puth(adc_get(ADCCHAN_VOLTAGE)); puts(" ");
puts("current: "); puth(adc_get(ADCCHAN_CURRENT)); puts("\n");*/
// set LED to be controls allowed
GPIOB->ODR = (GPIOB->ODR | (1 << 11)) & ~(controls_allowed << 11);
// blink the other LED if in FS mode
if (USBx == USB_OTG_FS) {
GPIOB->ODR |= (1 << 10);
}
delay(1000000);
GPIOB->ODR &= ~(1 << 10);
delay(1000000);
if (GPIOC->IDR & (1 << 13)) {
// turn on fan at half speed
set_fan_speed(32768);
} else {
// turn off fan
set_fan_speed(0);
}
}
return 0;
}

View File

@@ -1,511 +0,0 @@
/**
******************************************************************************
* @file startup_stm32f205xx.s
* @author MCD Application Team
* @version V2.0.1
* @date 25-March-2014
* @brief STM32F205xx Devices vector table for Atollic TrueSTUDIO toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Branches to main in the C library (which eventually
* calls main()).
* After Reset the Cortex-M3 processor is in Thread mode,
* priority is Privileged, and the Stack is set to Main.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
.syntax unified
.cpu cortex-m3
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
bl __initialize_hardware_early
ldr sp, =_estack /* set stack pointer */
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2], #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
/* bl SystemInit */
/* Call static constructors */
/* bl __libc_init_array */
/* Call the application's entry point.*/
bl main
bx lr
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
* @param None
* @retval None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M3. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
*******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
/* External Interrupts */
.word WWDG_IRQHandler /* Window WatchDog */
.word PVD_IRQHandler /* PVD through EXTI Line detection */
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_IRQHandler /* EXTI Line0 */
.word EXTI1_IRQHandler /* EXTI Line1 */
.word EXTI2_IRQHandler /* EXTI Line2 */
.word EXTI3_IRQHandler /* EXTI Line3 */
.word EXTI4_IRQHandler /* EXTI Line4 */
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
.word CAN1_TX_IRQHandler /* CAN1 TX */
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_IRQHandler /* USART3 */
.word EXTI15_10_IRQHandler /* External Line[15:10]s */
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
.word FSMC_IRQHandler /* FSMC */
.word SDIO_IRQHandler /* SDIO */
.word TIM5_IRQHandler /* TIM5 */
.word SPI3_IRQHandler /* SPI3 */
.word UART4_IRQHandler /* UART4 */
.word UART5_IRQHandler /* UART5 */
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
.word TIM7_IRQHandler /* TIM7 */
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word CAN2_TX_IRQHandler /* CAN2 TX */
.word CAN2_RX0_IRQHandler /* CAN2 RX0 */
.word CAN2_RX1_IRQHandler /* CAN2 RX1 */
.word CAN2_SCE_IRQHandler /* CAN2 SCE */
.word OTG_FS_IRQHandler /* USB OTG FS */
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
.word USART6_IRQHandler /* USART6 */
.word I2C3_EV_IRQHandler /* I2C3 event */
.word I2C3_ER_IRQHandler /* I2C3 error */
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
.word OTG_HS_IRQHandler /* USB OTG HS */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word HASH_RNG_IRQHandler /* Hash and Rng */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_IRQHandler
.thumb_set PVD_IRQHandler,Default_Handler
.weak TAMP_STAMP_IRQHandler
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler
.weak RTC_WKUP_IRQHandler
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Stream0_IRQHandler
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler
.weak DMA1_Stream1_IRQHandler
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler
.weak DMA1_Stream2_IRQHandler
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler
.weak DMA1_Stream3_IRQHandler
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler
.weak DMA1_Stream4_IRQHandler
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler
.weak DMA1_Stream5_IRQHandler
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler
.weak DMA1_Stream6_IRQHandler
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler
.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler
.weak CAN1_TX_IRQHandler
.thumb_set CAN1_TX_IRQHandler,Default_Handler
.weak CAN1_RX0_IRQHandler
.thumb_set CAN1_RX0_IRQHandler,Default_Handler
.weak CAN1_RX1_IRQHandler
.thumb_set CAN1_RX1_IRQHandler,Default_Handler
.weak CAN1_SCE_IRQHandler
.thumb_set CAN1_SCE_IRQHandler,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_TIM9_IRQHandler
.thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
.weak TIM1_UP_TIM10_IRQHandler
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_TIM11_IRQHandler
.thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak OTG_FS_WKUP_IRQHandler
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
.weak TIM8_BRK_TIM12_IRQHandler
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
.weak TIM8_UP_TIM13_IRQHandler
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
.weak TIM8_TRG_COM_TIM14_IRQHandler
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
.weak DMA1_Stream7_IRQHandler
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler
.weak FSMC_IRQHandler
.thumb_set FSMC_IRQHandler,Default_Handler
.weak SDIO_IRQHandler
.thumb_set SDIO_IRQHandler,Default_Handler
.weak TIM5_IRQHandler
.thumb_set TIM5_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak UART5_IRQHandler
.thumb_set UART5_IRQHandler,Default_Handler
.weak TIM6_DAC_IRQHandler
.thumb_set TIM6_DAC_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak DMA2_Stream0_IRQHandler
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler
.weak DMA2_Stream1_IRQHandler
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler
.weak DMA2_Stream2_IRQHandler
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler
.weak DMA2_Stream3_IRQHandler
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler
.weak DMA2_Stream4_IRQHandler
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler
.weak CAN2_TX_IRQHandler
.thumb_set CAN2_TX_IRQHandler,Default_Handler
.weak CAN2_RX0_IRQHandler
.thumb_set CAN2_RX0_IRQHandler,Default_Handler
.weak CAN2_RX1_IRQHandler
.thumb_set CAN2_RX1_IRQHandler,Default_Handler
.weak CAN2_SCE_IRQHandler
.thumb_set CAN2_SCE_IRQHandler,Default_Handler
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
.weak DMA2_Stream5_IRQHandler
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler
.weak DMA2_Stream6_IRQHandler
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler
.weak DMA2_Stream7_IRQHandler
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler
.weak USART6_IRQHandler
.thumb_set USART6_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak OTG_HS_EP1_OUT_IRQHandler
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
.weak OTG_HS_EP1_IN_IRQHandler
.thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
.weak OTG_HS_WKUP_IRQHandler
.thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
.weak OTG_HS_IRQHandler
.thumb_set OTG_HS_IRQHandler,Default_Handler
.weak HASH_RNG_IRQHandler
.thumb_set HASH_RNG_IRQHandler,Default_Handler
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -1,163 +0,0 @@
/*
*****************************************************************************
**
** File : stm32_flash.ld
**
** Abstract : Linker script for STM32F407VG Device with
** 1024KByte FLASH, 192KByte RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used.
**
** Target : STMicroelectronics STM32
**
** Environment : Atollic TrueSTUDIO(R)
**
** Distribution: The file is distributed “as is,” without any warranty
** of any kind.
**
** (c)Copyright Atollic AB.
** You may use this file as-is or modify it according to the needs of your
** project. Distribution of this file (unmodified or modified) is not
** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the
** rights to distribute the assembled, compiled & linked contents of this
** file as part of an application binary file, provided that it is built
** using the Atollic TrueSTUDIO(R) toolchain.
**
*****************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20020000; /* end of 128K RAM on AHB bus*/
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
_exit = .;
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = .;
/* Initialized data sections goes into RAM, load LMA copy after code */
.data : AT ( _sidata )
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/* MEMORY_bank1 section, code must be located here explicitly */
/* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */
.memory_b1_text :
{
*(.mb1text) /* .mb1text sections (code) */
*(.mb1text*) /* .mb1text* sections (code) */
*(.mb1rodata) /* read-only data (constants) */
*(.mb1rodata*)
} >MEMORY_B1
.ARM.attributes 0 : { *(.ARM.attributes) }
}

View File

@@ -1,7 +0,0 @@
void timer_init(TIM_TypeDef *TIM, int psc) {
TIM->PSC = psc-1;
TIM->DIER = TIM_DIER_UIE;
TIM->CR1 = TIM_CR1_CEN;
TIM->SR = 0;
}

Binary file not shown.

Binary file not shown.

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env python
import usb1
import time
import traceback
if __name__ == "__main__":
context = usb1.USBContext()
for device in context.getDeviceList(skip_on_error=True):
if device.getVendorID() == 0xbbaa and device.getProductID()&0xFF00 == 0xdd00:
print "found device"
handle = device.open()
handle.claimInterface(0)
try:
handle.controlWrite(usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE, 0xd1, 0, 0, '')
except Exception:
traceback.print_exc()
print "expected error, exiting cleanly"
time.sleep(1)

View File

@@ -1,510 +0,0 @@
// **** supporting defines ****
typedef struct
{
__IO uint32_t HPRT;
}
USB_OTG_HostPortTypeDef;
#define USBx_HOST ((USB_OTG_HostTypeDef *)((uint32_t)USBx + USB_OTG_HOST_BASE))
#define USBx_HOST_PORT ((USB_OTG_HostPortTypeDef *)((uint32_t)USBx + USB_OTG_HOST_PORT_BASE))
#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)((uint32_t)USBx + USB_OTG_DEVICE_BASE))
#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)((uint32_t)USBx + USB_OTG_IN_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE))
#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)((uint32_t)USBx + USB_OTG_OUT_ENDPOINT_BASE + (i)*USB_OTG_EP_REG_SIZE))
#define USBx_DFIFO(i) *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_FIFO_BASE + (i) * USB_OTG_FIFO_SIZE)
#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE)
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_DESC_TYPE_DEVICE 1
#define USB_DESC_TYPE_CONFIGURATION 2
#define USB_DESC_TYPE_STRING 3
#define USB_DESC_TYPE_INTERFACE 4
#define USB_DESC_TYPE_ENDPOINT 5
#define USB_DESC_TYPE_DEVICE_QUALIFIER 6
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 7
#define STS_GOUT_NAK 1
#define STS_DATA_UPDT 2
#define STS_XFER_COMP 3
#define STS_SETUP_COMP 4
#define STS_SETUP_UPDT 6
#define USBD_FS_TRDT_VALUE 5
// interfaces
void usb_cb_control_msg();
void usb_cb_ep1_in(int len);
void usb_cb_ep2_out(uint8_t *usbdata, int len);
void usb_cb_ep3_out(uint8_t *usbdata, int len);
uint8_t device_desc[] = {
0x12,0x01,0x00,0x01,
0xFF,0xFF,0xFF,0x40,
(USB_VID>>0)&0xFF,(USB_VID>>8)&0xFF,
(USB_PID>>0)&0xFF,(USB_PID>>8)&0xFF,
0x00,0x22,0x00,0x00,
0x00,0x01};
uint8_t configuration_desc[] = {
0x09, 0x02, 0x27, 0x00,
0x01, 0x01, 0x00, 0xc0,
0x32,
// interface 0
0x09, 0x04, 0x00, 0x00,
0x03, 0xff, 0xFF, 0xFF,
0x00,
// endpoint 1, read CAN
0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00,
// endpoint 2, AES load
0x07, 0x05, 0x02, 0x02, 0x10, 0x00, 0x00,
// endpoint 3, send CAN
0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00,
};
typedef union
{
uint16_t w;
struct BW
{
uint8_t msb;
uint8_t lsb;
}
bw;
}
uint16_t_uint8_t;
typedef union _USB_Setup
{
uint32_t d8[2];
struct _SetupPkt_Struc
{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t_uint8_t wValue;
uint16_t_uint8_t wIndex;
uint16_t_uint8_t wLength;
} b;
}
USB_Setup_TypeDef;
// current packet
USB_Setup_TypeDef setup;
uint8_t usbdata[0x100];
// packet read and write
void *USB_ReadPacket(void *dest, uint16_t len) {
uint32_t i=0;
uint32_t count32b = (len + 3) / 4;
for ( i = 0; i < count32b; i++, dest += 4 ) {
// packed?
*(__attribute__((__packed__)) uint32_t *)dest = USBx_DFIFO(0);
}
return ((void *)dest);
}
void USB_WritePacket(const uint8_t *src, uint16_t len, uint32_t ep) {
#ifdef DEBUG
puts("writing ");
hexdump(src, len);
#endif
uint32_t count32b = 0, i = 0;
count32b = (len + 3) / 4;
// bullshit
USBx_INEP(ep)->DIEPTSIZ = (USB_OTG_DIEPTSIZ_PKTCNT & (1 << 19)) | (len & USB_OTG_DIEPTSIZ_XFRSIZ);
USBx_INEP(ep)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
// load the FIFO
for (i = 0; i < count32b; i++, src += 4) {
USBx_DFIFO(ep) = *((__attribute__((__packed__)) uint32_t *)src);
}
}
void usb_reset() {
// unmask endpoint interrupts, so many sets
USBx_DEVICE->DAINT = 0xFFFFFFFF;
USBx_DEVICE->DAINTMSK = 0xFFFFFFFF;
//USBx_DEVICE->DOEPMSK = (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
//USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM | USB_OTG_DIEPMSK_ITTXFEMSK);
//USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
// all interrupts for debugging
USBx_DEVICE->DIEPMSK = 0xFFFFFFFF;
USBx_DEVICE->DOEPMSK = 0xFFFFFFFF;
// clear interrupts
USBx_INEP(0)->DIEPINT = 0xFF;
USBx_OUTEP(0)->DOEPINT = 0xFF;
// unset the address
USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
// set up USB FIFOs
// RX start address is fixed to 0
USBx->GRXFSIZ = 0x40;
// 0x100 to offset past GRXFSIZ
USBx->DIEPTXF0_HNPTXFSIZ = (0x40 << 16) | 0x40;
// EP1, massive
USBx->DIEPTXF[0] = (0x40 << 16) | 0x80;
// flush TX fifo
USBx->GRSTCTL = USB_OTG_GRSTCTL_TXFFLSH | USB_OTG_GRSTCTL_TXFNUM_4;
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH);
// flush RX FIFO
USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH);
// no global NAK
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK;
// ready to receive setup packets
USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) | (3 * 8);
}
void usb_setup() {
uint8_t resp[0x20];
// setup packet is ready
switch (setup.b.bRequest) {
case USB_REQ_SET_CONFIGURATION:
// enable other endpoints, has to be here?
USBx_INEP(1)->DIEPCTL = (0x40 & USB_OTG_DIEPCTL_MPSIZ) | (2 << 18) | (1 << 22) |
USB_OTG_DIEPCTL_SD0PID_SEVNFRM | USB_OTG_DIEPCTL_USBAEP;
USBx_INEP(1)->DIEPINT = 0xFF;
USBx_OUTEP(2)->DOEPTSIZ = (1 << 19) | 0x10;
USBx_OUTEP(2)->DOEPCTL = (0x10 & USB_OTG_DOEPCTL_MPSIZ) | (2 << 18) |
USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP;
USBx_OUTEP(2)->DOEPINT = 0xFF;
USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40;
USBx_OUTEP(3)->DOEPCTL = (0x40 & USB_OTG_DOEPCTL_MPSIZ) | (2 << 18) |
USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP;
USBx_OUTEP(3)->DOEPINT = 0xFF;
// mark ready to receive
USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
USB_WritePacket(0, 0, 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
case USB_REQ_SET_ADDRESS:
// set now?
USBx_DEVICE->DCFG |= ((setup.b.wValue.w & 0x7f) << 4);
#ifdef DEBUG
puts(" set address\n");
#endif
USB_WritePacket(0, 0, 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
case USB_REQ_GET_DESCRIPTOR:
switch (setup.b.wValue.bw.lsb) {
case USB_DESC_TYPE_DEVICE:
//puts(" writing device descriptor\n");
// setup transfer
USB_WritePacket(device_desc, min(sizeof(device_desc), setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
//puts("D");
break;
case USB_DESC_TYPE_CONFIGURATION:
USB_WritePacket(configuration_desc, min(sizeof(configuration_desc), setup.b.wLength.w), 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
default:
// nothing here?
USB_WritePacket(0, 0, 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
}
break;
case USB_REQ_GET_STATUS:
// empty resp?
resp[0] = 0;
resp[1] = 0;
USB_WritePacket((void*)&resp, 2, 0);
USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
break;
default:
usb_cb_control_msg();
}
}
void usb_init() {
// internal PHY set before reset
USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
// full speed PHY, do reset and remove power down
puth(USBx->GRSTCTL);
puts(" resetting PHY\n");
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
puts("AHB idle\n");
// reset PHY here?
USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
puts("reset done\n");
// power up the PHY
USBx->GCCFG = USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS;
// be a device, slowest timings
//USBx->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
USBx->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL;
USBx->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
//USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
// **** for debugging, doesn't seem to work ****
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_CTXPKT;
// reset PHY clock
USBx_PCGCCTL = 0;
// enable the fancy OTG things
USBx->GUSBCFG |= USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP;
USBx_DEVICE->DCFG = USB_OTG_DCFG_NZLSOHSK | USB_OTG_DCFG_DSPD;
//USBx_DEVICE->DCFG = USB_OTG_DCFG_DSPD;
// setup USB interrupts
// all interrupts except TXFIFO EMPTY
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM);
USBx->GAHBCFG = USB_OTG_GAHBCFG_GINT;
USBx->GINTSTS = 0;
}
// ***************************** USB port *****************************
void usb_irqhandler(void) {
USBx->GINTMSK = 0;
unsigned int gintsts = USBx->GINTSTS;
// gintsts SUSPEND? 04008428
#ifdef DEBUG
unsigned int daint = USBx_DEVICE->DAINT;
puth(gintsts);
puts(" ep ");
puth(daint);
puts(" USB interrupt!\n");
#endif
if (gintsts & USB_OTG_GINTSTS_ESUSP) {
puts("ESUSP detected\n");
}
if (gintsts & USB_OTG_GINTSTS_USBRST) {
puts("USB reset\n");
usb_reset();
}
if (gintsts & USB_OTG_GINTSTS_ENUMDNE) {
puts("enumeration done ");
// Full speed, ENUMSPD
puth(USBx_DEVICE->DSTS);
puts("\n");
}
if (gintsts & USB_OTG_GINTSTS_OTGINT) {
puts("OTG int:");
puth(USBx->GOTGINT);
puts("\n");
// getting ADTOCHG
USBx->GOTGINT = USBx->GOTGINT;
}
// RX FIFO first
if (gintsts & USB_OTG_GINTSTS_RXFLVL) {
// 1. Read the Receive status pop register
volatile unsigned int rxst = USBx->GRXSTSP;
#ifdef DEBUG
puts(" RX FIFO:");
puth(rxst);
puts(" status: ");
puth((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17);
puts(" len: ");
puth((rxst & USB_OTG_GRXSTSP_BCNT) >> 4);
puts("\n");
#endif
if (((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT) {
int endpoint = (rxst & USB_OTG_GRXSTSP_EPNUM);
int len = (rxst & USB_OTG_GRXSTSP_BCNT) >> 4;
USB_ReadPacket(&usbdata, len);
#ifdef DEBUG
puts(" data ");
puth(len);
puts("\n");
hexdump(&usbdata, len);
#endif
if (endpoint == 2) {
usb_cb_ep2_out(usbdata, len);
}
if (endpoint == 3) {
usb_cb_ep3_out(usbdata, len);
}
} else if (((rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT) {
USB_ReadPacket(&setup, 8);
#ifdef DEBUG
puts(" setup ");
hexdump(&setup, 8);
puts("\n");
#endif
}
}
if (gintsts & USB_OTG_GINTSTS_HPRTINT) {
// host
puts("HPRT:");
puth(USBx_HOST_PORT->HPRT);
puts("\n");
if (USBx_HOST_PORT->HPRT & USB_OTG_HPRT_PCDET) {
USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PRST;
USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PCDET;
}
}
if (gintsts & USB_OTG_GINTSTS_BOUTNAKEFF) {
// no global NAK, why is this getting set?
#ifdef DEBUG
puts("GLOBAL NAK\n");
#endif
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK | USB_OTG_DCTL_CGINAK;
}
if (gintsts & USB_OTG_GINTSTS_SRQINT) {
// we want to do "A-device host negotiation protocol" since we are the A-device
puts("start request\n");
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
//USBx_HOST_PORT->HPRT = USB_OTG_HPRT_PPWR | USB_OTG_HPRT_PENA;
}
// out endpoint hit
if (gintsts & USB_OTG_GINTSTS_OEPINT) {
#ifdef DEBUG
puts(" 0:");
puth(USBx_OUTEP(0)->DOEPINT);
puts(" 2:");
puth(USBx_OUTEP(2)->DOEPINT);
puts(" 3:");
puth(USBx_OUTEP(3)->DOEPINT);
puts(" ");
puth(USBx_OUTEP(3)->DOEPCTL);
puts(" 4:");
puth(USBx_OUTEP(4)->DOEPINT);
puts(" OUT ENDPOINT\n");
#endif
if (USBx_OUTEP(2)->DOEPINT & USB_OTG_DOEPINT_XFRC) {
#ifdef DEBUG
puts(" OUT2 PACKET XFRC\n");
#endif
USBx_OUTEP(2)->DOEPTSIZ = (1 << 19) | 0x10;
USBx_OUTEP(2)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
}
if (USBx_OUTEP(3)->DOEPINT & USB_OTG_DOEPINT_XFRC) {
#ifdef DEBUG
puts(" OUT3 PACKET XFRC\n");
#endif
USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40;
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
} else if (USBx_OUTEP(3)->DOEPINT & 0x2000) {
#ifdef DEBUG
puts(" OUT3 PACKET WTF\n");
#endif
// if NAK was set trigger this, unknown interrupt
USBx_OUTEP(3)->DOEPTSIZ = (1 << 19) | 0x40;
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
} else if (USBx_OUTEP(3)->DOEPINT) {
puts("OUTEP3 error ");
puth(USBx_OUTEP(3)->DOEPINT);
puts("\n");
}
if (USBx_OUTEP(0)->DOEPINT & USB_OTG_DIEPINT_XFRC) {
// ready for next packet
USBx_OUTEP(0)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1 << 19)) | (1 * 8);
}
// respond to setup packets
if (USBx_OUTEP(0)->DOEPINT & USB_OTG_DOEPINT_STUP) {
usb_setup();
}
USBx_OUTEP(0)->DOEPINT = USBx_OUTEP(0)->DOEPINT;
USBx_OUTEP(2)->DOEPINT = USBx_OUTEP(2)->DOEPINT;
USBx_OUTEP(3)->DOEPINT = USBx_OUTEP(3)->DOEPINT;
}
// in endpoint hit
if (gintsts & USB_OTG_GINTSTS_IEPINT) {
#ifdef DEBUG
puts(" ");
puth(USBx_INEP(0)->DIEPINT);
puts(" ");
puth(USBx_INEP(1)->DIEPINT);
puts(" IN ENDPOINT\n");
#endif
// this happens first
if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPINT_XFRC) {
#ifdef DEBUG
puts(" IN PACKET SEND\n");
#endif
//USBx_DEVICE->DIEPEMPMSK = ~(1 << 1);
}
// *** IN token received when TxFIFO is empty
if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) {
#ifdef DEBUG
puts(" IN PACKET QUEUE\n");
#endif
// TODO: always assuming max len, can we get the length?
usb_cb_ep1_in(0x40);
}
// clear interrupts
USBx_INEP(0)->DIEPINT = USBx_INEP(0)->DIEPINT;
USBx_INEP(1)->DIEPINT = USBx_INEP(1)->DIEPINT;
}
// clear all interrupts
USBx_DEVICE->DAINT = USBx_DEVICE->DAINT;
USBx->GINTSTS = USBx->GINTSTS;
USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
}

1
cereal/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
gen

4
cereal/Makefile Normal file
View File

@@ -0,0 +1,4 @@
-include build_from_src.mk
release:
@echo "cereal: this is a release"

View File

@@ -1,7 +1,20 @@
import os
import capnp
capnp.remove_import_hook()
CEREAL_PATH = os.path.dirname(os.path.abspath(__file__))
log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp"))
capnp.remove_import_hook()
if os.getenv("NEWCAPNP"):
import tempfile
import pyximport
importers = pyximport.install(build_dir=os.path.join(tempfile.gettempdir(), ".pyxbld"))
try:
import cereal.gen.cython.log_capnp_cython as log
import cereal.gen.cython.car_capnp_cython as car
finally:
pyximport.uninstall(*importers)
del importers
else:
log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp"))
car = capnp.load(os.path.join(CEREAL_PATH, "car.capnp"))

45
cereal/build_from_src.mk Normal file
View File

@@ -0,0 +1,45 @@
SRCS := log.capnp car.capnp
GENS := gen/cpp/car.capnp.c++ gen/cpp/log.capnp.c++
UNAME_M := $(shell uname -m)
# only generate C++ for docker tests
ifneq ($(OPTEST),1)
GENS += gen/c/car.capnp.c gen/c/log.capnp.c gen/c/c++.capnp.h gen/c/java.capnp.h
# Dont build java on the phone...
ifeq ($(UNAME_M),x86_64)
GENS += gen/java/Car.java gen/java/Log.java
endif
endif
.PHONY: all
all: $(GENS)
.PHONY: clean
clean:
rm -rf gen
gen/c/%.capnp.c: %.capnp
@echo "[ CAPNPC C ] $@"
mkdir -p gen/c/
capnpc '$<' -o c:gen/c/
gen/cpp/%.capnp.c++: %.capnp
@echo "[ CAPNPC C++ ] $@"
mkdir -p gen/cpp/
capnpc '$<' -o c++:gen/cpp/
gen/java/Car.java gen/java/Log.java: $(SRCS)
@echo "[ CAPNPC java ] $@"
mkdir -p gen/java/
capnpc $^ -o java:gen/java
# c-capnproto needs some empty headers
gen/c/c++.capnp.h gen/c/java.capnp.h:
mkdir -p gen/c/
touch '$@'

203
cereal/car.capnp Normal file
View File

@@ -0,0 +1,203 @@
using Cxx = import "c++.capnp";
$Cxx.namespace("cereal");
using Java = import "java.capnp";
$Java.package("ai.comma.openpilot.cereal");
$Java.outerClassname("Car");
@0x8e2af1e708af8b8d;
# ******* main car state @ 100hz *******
# all speeds in m/s
struct CarState {
errors @0: List(Error);
# car speed
vEgo @1 :Float32; # best estimate of speed
wheelSpeeds @2 :WheelSpeeds;
# gas pedal, 0.0-1.0
gas @3 :Float32; # this is user + computer
gasPressed @4 :Bool; # this is user pedal only
# brake pedal, 0.0-1.0
brake @5 :Float32; # this is user pedal only
brakePressed @6 :Bool; # this is user pedal only
# steering wheel
steeringAngle @7 :Float32; # deg
steeringTorque @8 :Float32; # TODO: standardize units
steeringPressed @9 :Bool; # if the user is using the steering wheel
# cruise state
cruiseState @10 :CruiseState;
# button presses
buttonEvents @11 :List(ButtonEvent);
# which packets this state came from
canMonoTimes @12: List(UInt64);
struct WheelSpeeds {
# optional wheel speeds
fl @0 :Float32;
fr @1 :Float32;
rl @2 :Float32;
rr @3 :Float32;
}
struct CruiseState {
enabled @0: Bool;
speed @1: Float32;
available @2: Bool;
}
enum Error {
# TODO: copy from error list
commIssue @0;
steerUnavailable @1;
brakeUnavailable @2;
gasUnavailable @3;
wrongGear @4;
doorOpen @5;
seatbeltNotLatched @6;
espDisabled @7;
wrongCarMode @8;
steerTempUnavailable @9;
reverseGear @10;
# ...
}
# send on change
struct ButtonEvent {
pressed @0: Bool;
type @1: Type;
enum Type {
unknown @0;
leftBlinker @1;
rightBlinker @2;
accelCruise @3;
decelCruise @4;
cancel @5;
altButton1 @6;
altButton2 @7;
altButton3 @8;
}
}
}
# ******* radar state @ 20hz *******
struct RadarState {
errors @0: List(Error);
points @1: List(RadarPoint);
# which packets this state came from
canMonoTimes @2: List(UInt64);
enum Error {
notValid @0;
}
# similar to LiveTracks
# is one timestamp valid for all? I think so
struct RadarPoint {
trackId @0: UInt64; # no trackId reuse
# these 3 are the minimum required
dRel @1: Float32; # m from the front bumper of the car
yRel @2: Float32; # m
vRel @3: Float32; # m/s
# these are optional and valid if they are not NaN
aRel @4: Float32; # m/s^2
yvRel @5: Float32; # m/s
}
}
# ******* car controls @ 100hz *******
struct CarControl {
# must be true for any actuator commands to work
enabled @0: Bool;
# range from 0.0 - 1.0
gas @1: Float32;
brake @2: Float32;
# range from -1.0 - 1.0
steeringTorque @3 :Float32;
cruiseControl @4: CruiseControl;
hudControl @5: HUDControl;
struct CruiseControl {
cancel @0: Bool;
override @1: Bool;
speedOverride @2: Float32;
accelOverride @3: Float32;
}
struct HUDControl {
speedVisible @0: Bool;
setSpeed @1: Float32;
lanesVisible @2: Bool;
leadVisible @3: Bool;
visualAlert @4: VisualAlert;
audibleAlert @5: AudibleAlert;
enum VisualAlert {
# these are the choices from the Honda
# map as good as you can for your car
none @0;
fcw @1;
steerRequired @2;
brakePressed @3;
wrongGear @4;
seatbeltUnbuckled @5;
speedTooHigh @6;
}
enum AudibleAlert {
# these are the choices from the Honda
# map as good as you can for your car
none @0;
beepSingle @1;
beepTriple @2;
beepRepeated @3;
chimeSingle @4;
chimeDouble @5;
chimeRepeated @6;
chimeContinuous @7;
}
}
}
# ****** car param ******
struct CarParams {
carName @0: Text;
radarName @1: Text;
carFingerprint @11: Text;
enableSteer @2: Bool;
enableGas @3: Bool;
enableBrake @4: Bool;
enableCruise @5: Bool;
# things about the car in the manual
wheelBase @6: Float32; # in meters
steerRatio @7: Float32;
# things we can derive
slipFactor @8: Float32;
# Kp and Ki for the lateral control
steerKp @9: Float32;
steerKi @10: Float32;
# TODO: Kp and Ki for long control, perhaps not needed?
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,667 +0,0 @@
#ifndef CAPN_F3B1F17E25A4285B
#define CAPN_F3B1F17E25A4285B
/* AUTO GENERATED - DO NOT EDIT */
#include <capnp_c.h>
#if CAPN_VERSION != 1
#error "version mismatch between capnp_c.h and generated code"
#endif
#include "c++.capnp.h"
#ifdef __cplusplus
extern "C" {
#endif
struct cereal_InitData;
struct cereal_FrameData;
struct cereal_GPSNMEAData;
struct cereal_SensorEventData;
struct cereal_SensorEventData_SensorVec;
struct cereal_CanData;
struct cereal_ThermalData;
struct cereal_HealthData;
struct cereal_LiveUI;
struct cereal_Live20Data;
struct cereal_Live20Data_LeadData;
struct cereal_LiveCalibrationData;
struct cereal_LiveTracks;
struct cereal_Live100Data;
struct cereal_LiveEventData;
struct cereal_ModelData;
struct cereal_ModelData_PathData;
struct cereal_ModelData_LeadData;
struct cereal_ModelData_ModelSettings;
struct cereal_CalibrationFeatures;
struct cereal_EncodeIndex;
struct cereal_AndroidLogEntry;
struct cereal_LogRotate;
struct cereal_Event;
typedef struct {capn_ptr p;} cereal_InitData_ptr;
typedef struct {capn_ptr p;} cereal_FrameData_ptr;
typedef struct {capn_ptr p;} cereal_GPSNMEAData_ptr;
typedef struct {capn_ptr p;} cereal_SensorEventData_ptr;
typedef struct {capn_ptr p;} cereal_SensorEventData_SensorVec_ptr;
typedef struct {capn_ptr p;} cereal_CanData_ptr;
typedef struct {capn_ptr p;} cereal_ThermalData_ptr;
typedef struct {capn_ptr p;} cereal_HealthData_ptr;
typedef struct {capn_ptr p;} cereal_LiveUI_ptr;
typedef struct {capn_ptr p;} cereal_Live20Data_ptr;
typedef struct {capn_ptr p;} cereal_Live20Data_LeadData_ptr;
typedef struct {capn_ptr p;} cereal_LiveCalibrationData_ptr;
typedef struct {capn_ptr p;} cereal_LiveTracks_ptr;
typedef struct {capn_ptr p;} cereal_Live100Data_ptr;
typedef struct {capn_ptr p;} cereal_LiveEventData_ptr;
typedef struct {capn_ptr p;} cereal_ModelData_ptr;
typedef struct {capn_ptr p;} cereal_ModelData_PathData_ptr;
typedef struct {capn_ptr p;} cereal_ModelData_LeadData_ptr;
typedef struct {capn_ptr p;} cereal_ModelData_ModelSettings_ptr;
typedef struct {capn_ptr p;} cereal_CalibrationFeatures_ptr;
typedef struct {capn_ptr p;} cereal_EncodeIndex_ptr;
typedef struct {capn_ptr p;} cereal_AndroidLogEntry_ptr;
typedef struct {capn_ptr p;} cereal_LogRotate_ptr;
typedef struct {capn_ptr p;} cereal_Event_ptr;
typedef struct {capn_ptr p;} cereal_InitData_list;
typedef struct {capn_ptr p;} cereal_FrameData_list;
typedef struct {capn_ptr p;} cereal_GPSNMEAData_list;
typedef struct {capn_ptr p;} cereal_SensorEventData_list;
typedef struct {capn_ptr p;} cereal_SensorEventData_SensorVec_list;
typedef struct {capn_ptr p;} cereal_CanData_list;
typedef struct {capn_ptr p;} cereal_ThermalData_list;
typedef struct {capn_ptr p;} cereal_HealthData_list;
typedef struct {capn_ptr p;} cereal_LiveUI_list;
typedef struct {capn_ptr p;} cereal_Live20Data_list;
typedef struct {capn_ptr p;} cereal_Live20Data_LeadData_list;
typedef struct {capn_ptr p;} cereal_LiveCalibrationData_list;
typedef struct {capn_ptr p;} cereal_LiveTracks_list;
typedef struct {capn_ptr p;} cereal_Live100Data_list;
typedef struct {capn_ptr p;} cereal_LiveEventData_list;
typedef struct {capn_ptr p;} cereal_ModelData_list;
typedef struct {capn_ptr p;} cereal_ModelData_PathData_list;
typedef struct {capn_ptr p;} cereal_ModelData_LeadData_list;
typedef struct {capn_ptr p;} cereal_ModelData_ModelSettings_list;
typedef struct {capn_ptr p;} cereal_CalibrationFeatures_list;
typedef struct {capn_ptr p;} cereal_EncodeIndex_list;
typedef struct {capn_ptr p;} cereal_AndroidLogEntry_list;
typedef struct {capn_ptr p;} cereal_LogRotate_list;
typedef struct {capn_ptr p;} cereal_Event_list;
enum cereal_EncodeIndex_Type {
cereal_EncodeIndex_Type_bigBoxLossless = 0,
cereal_EncodeIndex_Type_fullHEVC = 1,
cereal_EncodeIndex_Type_bigBoxHEVC = 2
};
extern int32_t cereal_logVersion;
struct cereal_InitData {
capn_ptr kernelArgs;
capn_text gctx;
capn_text dongleId;
};
static const size_t cereal_InitData_word_count = 0;
static const size_t cereal_InitData_pointer_count = 3;
static const size_t cereal_InitData_struct_bytes_count = 24;
struct cereal_FrameData {
uint32_t frameId;
uint32_t encodeId;
uint64_t timestampEof;
int32_t frameLength;
int32_t integLines;
int32_t globalGain;
capn_data image;
};
static const size_t cereal_FrameData_word_count = 4;
static const size_t cereal_FrameData_pointer_count = 1;
static const size_t cereal_FrameData_struct_bytes_count = 40;
struct cereal_GPSNMEAData {
int64_t timestamp;
uint64_t localWallTime;
capn_text nmea;
};
static const size_t cereal_GPSNMEAData_word_count = 2;
static const size_t cereal_GPSNMEAData_pointer_count = 1;
static const size_t cereal_GPSNMEAData_struct_bytes_count = 24;
enum cereal_SensorEventData_which {
cereal_SensorEventData_acceleration = 0,
cereal_SensorEventData_magnetic = 1,
cereal_SensorEventData_orientation = 2,
cereal_SensorEventData_gyro = 3
};
struct cereal_SensorEventData {
int32_t version;
int32_t sensor;
int32_t type;
int64_t timestamp;
enum cereal_SensorEventData_which which;
union {
cereal_SensorEventData_SensorVec_ptr acceleration;
cereal_SensorEventData_SensorVec_ptr magnetic;
cereal_SensorEventData_SensorVec_ptr orientation;
cereal_SensorEventData_SensorVec_ptr gyro;
};
};
static const size_t cereal_SensorEventData_word_count = 3;
static const size_t cereal_SensorEventData_pointer_count = 1;
static const size_t cereal_SensorEventData_struct_bytes_count = 32;
struct cereal_SensorEventData_SensorVec {
capn_list32 v;
int8_t status;
};
static const size_t cereal_SensorEventData_SensorVec_word_count = 1;
static const size_t cereal_SensorEventData_SensorVec_pointer_count = 1;
static const size_t cereal_SensorEventData_SensorVec_struct_bytes_count = 16;
struct cereal_CanData {
uint32_t address;
uint16_t busTime;
capn_data dat;
int8_t src;
};
static const size_t cereal_CanData_word_count = 1;
static const size_t cereal_CanData_pointer_count = 1;
static const size_t cereal_CanData_struct_bytes_count = 16;
struct cereal_ThermalData {
uint16_t cpu0;
uint16_t cpu1;
uint16_t cpu2;
uint16_t cpu3;
uint16_t mem;
uint16_t gpu;
uint32_t bat;
};
static const size_t cereal_ThermalData_word_count = 2;
static const size_t cereal_ThermalData_pointer_count = 0;
static const size_t cereal_ThermalData_struct_bytes_count = 16;
struct cereal_HealthData {
uint32_t voltage;
uint32_t current;
unsigned started : 1;
unsigned controlsAllowed : 1;
unsigned gasInterceptorDetected : 1;
};
static const size_t cereal_HealthData_word_count = 2;
static const size_t cereal_HealthData_pointer_count = 0;
static const size_t cereal_HealthData_struct_bytes_count = 16;
struct cereal_LiveUI {
unsigned rearViewCam : 1;
capn_text alertText1;
capn_text alertText2;
float awarenessStatus;
};
static const size_t cereal_LiveUI_word_count = 1;
static const size_t cereal_LiveUI_pointer_count = 2;
static const size_t cereal_LiveUI_struct_bytes_count = 24;
struct cereal_Live20Data {
capn_list64 canMonoTimes;
uint64_t mdMonoTime;
uint64_t ftMonoTime;
capn_list32 warpMatrix;
float angleOffset;
int8_t calStatus;
int32_t calCycle;
int8_t calPerc;
cereal_Live20Data_LeadData_ptr leadOne;
cereal_Live20Data_LeadData_ptr leadTwo;
float cumLagMs;
};
static const size_t cereal_Live20Data_word_count = 4;
static const size_t cereal_Live20Data_pointer_count = 4;
static const size_t cereal_Live20Data_struct_bytes_count = 64;
struct cereal_Live20Data_LeadData {
float dRel;
float yRel;
float vRel;
float aRel;
float vLead;
float aLead;
float dPath;
float vLat;
float vLeadK;
float aLeadK;
unsigned fcw : 1;
unsigned status : 1;
};
static const size_t cereal_Live20Data_LeadData_word_count = 6;
static const size_t cereal_Live20Data_LeadData_pointer_count = 0;
static const size_t cereal_Live20Data_LeadData_struct_bytes_count = 48;
struct cereal_LiveCalibrationData {
capn_list32 warpMatrix;
int8_t calStatus;
int32_t calCycle;
int8_t calPerc;
};
static const size_t cereal_LiveCalibrationData_word_count = 1;
static const size_t cereal_LiveCalibrationData_pointer_count = 1;
static const size_t cereal_LiveCalibrationData_struct_bytes_count = 16;
struct cereal_LiveTracks {
int32_t trackId;
float dRel;
float yRel;
float vRel;
float aRel;
float timeStamp;
float status;
float currentTime;
unsigned stationary : 1;
unsigned oncoming : 1;
};
static const size_t cereal_LiveTracks_word_count = 5;
static const size_t cereal_LiveTracks_pointer_count = 0;
static const size_t cereal_LiveTracks_struct_bytes_count = 40;
struct cereal_Live100Data {
uint64_t canMonoTime;
capn_list64 canMonoTimes;
uint64_t l20MonoTime;
uint64_t mdMonoTime;
float vEgo;
float aEgo;
float vPid;
float vTargetLead;
float upAccelCmd;
float uiAccelCmd;
float yActual;
float yDes;
float upSteer;
float uiSteer;
float aTargetMin;
float aTargetMax;
float jerkFactor;
float angleSteers;
int32_t hudLead;
float cumLagMs;
unsigned enabled : 1;
unsigned steerOverride : 1;
float vCruise;
unsigned rearViewCam : 1;
capn_text alertText1;
capn_text alertText2;
float awarenessStatus;
};
static const size_t cereal_Live100Data_word_count = 13;
static const size_t cereal_Live100Data_pointer_count = 3;
static const size_t cereal_Live100Data_struct_bytes_count = 128;
struct cereal_LiveEventData {
capn_text name;
int32_t value;
};
static const size_t cereal_LiveEventData_word_count = 1;
static const size_t cereal_LiveEventData_pointer_count = 1;
static const size_t cereal_LiveEventData_struct_bytes_count = 16;
struct cereal_ModelData {
uint32_t frameId;
cereal_ModelData_PathData_ptr path;
cereal_ModelData_PathData_ptr leftLane;
cereal_ModelData_PathData_ptr rightLane;
cereal_ModelData_LeadData_ptr lead;
cereal_ModelData_ModelSettings_ptr settings;
};
static const size_t cereal_ModelData_word_count = 1;
static const size_t cereal_ModelData_pointer_count = 5;
static const size_t cereal_ModelData_struct_bytes_count = 48;
struct cereal_ModelData_PathData {
capn_list32 points;
float prob;
float std;
};
static const size_t cereal_ModelData_PathData_word_count = 1;
static const size_t cereal_ModelData_PathData_pointer_count = 1;
static const size_t cereal_ModelData_PathData_struct_bytes_count = 16;
struct cereal_ModelData_LeadData {
float dist;
float prob;
float std;
};
static const size_t cereal_ModelData_LeadData_word_count = 2;
static const size_t cereal_ModelData_LeadData_pointer_count = 0;
static const size_t cereal_ModelData_LeadData_struct_bytes_count = 16;
struct cereal_ModelData_ModelSettings {
uint16_t bigBoxX;
uint16_t bigBoxY;
uint16_t bigBoxWidth;
uint16_t bigBoxHeight;
capn_list32 boxProjection;
capn_list32 yuvCorrection;
};
static const size_t cereal_ModelData_ModelSettings_word_count = 1;
static const size_t cereal_ModelData_ModelSettings_pointer_count = 2;
static const size_t cereal_ModelData_ModelSettings_struct_bytes_count = 24;
struct cereal_CalibrationFeatures {
uint32_t frameId;
capn_list32 p0;
capn_list32 p1;
capn_list8 status;
};
static const size_t cereal_CalibrationFeatures_word_count = 1;
static const size_t cereal_CalibrationFeatures_pointer_count = 3;
static const size_t cereal_CalibrationFeatures_struct_bytes_count = 32;
struct cereal_EncodeIndex {
uint32_t frameId;
enum cereal_EncodeIndex_Type type;
uint32_t encodeId;
int32_t segmentNum;
uint32_t segmentId;
};
static const size_t cereal_EncodeIndex_word_count = 3;
static const size_t cereal_EncodeIndex_pointer_count = 0;
static const size_t cereal_EncodeIndex_struct_bytes_count = 24;
struct cereal_AndroidLogEntry {
uint8_t id;
uint64_t ts;
uint8_t priority;
int32_t pid;
int32_t tid;
capn_text tag;
capn_text message;
};
static const size_t cereal_AndroidLogEntry_word_count = 3;
static const size_t cereal_AndroidLogEntry_pointer_count = 2;
static const size_t cereal_AndroidLogEntry_struct_bytes_count = 40;
struct cereal_LogRotate {
int32_t segmentNum;
capn_text path;
};
static const size_t cereal_LogRotate_word_count = 1;
static const size_t cereal_LogRotate_pointer_count = 1;
static const size_t cereal_LogRotate_struct_bytes_count = 16;
enum cereal_Event_which {
cereal_Event_initData = 0,
cereal_Event_frame = 1,
cereal_Event_gpsNMEA = 2,
cereal_Event_sensorEventDEPRECATED = 3,
cereal_Event_can = 4,
cereal_Event_thermal = 5,
cereal_Event_live100 = 6,
cereal_Event_liveEventDEPRECATED = 7,
cereal_Event_model = 8,
cereal_Event_features = 9,
cereal_Event_sensorEvents = 10,
cereal_Event_health = 11,
cereal_Event_live20 = 12,
cereal_Event_liveUIDEPRECATED = 13,
cereal_Event_encodeIdx = 14,
cereal_Event_liveTracks = 15,
cereal_Event_sendcan = 16,
cereal_Event_logMessage = 17,
cereal_Event_liveCalibration = 18,
cereal_Event_androidLogEntry = 19
};
struct cereal_Event {
uint64_t logMonoTime;
enum cereal_Event_which which;
union {
cereal_InitData_ptr initData;
cereal_FrameData_ptr frame;
cereal_GPSNMEAData_ptr gpsNMEA;
cereal_SensorEventData_ptr sensorEventDEPRECATED;
cereal_CanData_list can;
cereal_ThermalData_ptr thermal;
cereal_Live100Data_ptr live100;
cereal_LiveEventData_list liveEventDEPRECATED;
cereal_ModelData_ptr model;
cereal_CalibrationFeatures_ptr features;
cereal_SensorEventData_list sensorEvents;
cereal_HealthData_ptr health;
cereal_Live20Data_ptr live20;
cereal_LiveUI_ptr liveUIDEPRECATED;
cereal_EncodeIndex_ptr encodeIdx;
cereal_LiveTracks_list liveTracks;
cereal_CanData_list sendcan;
capn_text logMessage;
cereal_LiveCalibrationData_ptr liveCalibration;
cereal_AndroidLogEntry_ptr androidLogEntry;
};
};
static const size_t cereal_Event_word_count = 2;
static const size_t cereal_Event_pointer_count = 1;
static const size_t cereal_Event_struct_bytes_count = 24;
cereal_InitData_ptr cereal_new_InitData(struct capn_segment*);
cereal_FrameData_ptr cereal_new_FrameData(struct capn_segment*);
cereal_GPSNMEAData_ptr cereal_new_GPSNMEAData(struct capn_segment*);
cereal_SensorEventData_ptr cereal_new_SensorEventData(struct capn_segment*);
cereal_SensorEventData_SensorVec_ptr cereal_new_SensorEventData_SensorVec(struct capn_segment*);
cereal_CanData_ptr cereal_new_CanData(struct capn_segment*);
cereal_ThermalData_ptr cereal_new_ThermalData(struct capn_segment*);
cereal_HealthData_ptr cereal_new_HealthData(struct capn_segment*);
cereal_LiveUI_ptr cereal_new_LiveUI(struct capn_segment*);
cereal_Live20Data_ptr cereal_new_Live20Data(struct capn_segment*);
cereal_Live20Data_LeadData_ptr cereal_new_Live20Data_LeadData(struct capn_segment*);
cereal_LiveCalibrationData_ptr cereal_new_LiveCalibrationData(struct capn_segment*);
cereal_LiveTracks_ptr cereal_new_LiveTracks(struct capn_segment*);
cereal_Live100Data_ptr cereal_new_Live100Data(struct capn_segment*);
cereal_LiveEventData_ptr cereal_new_LiveEventData(struct capn_segment*);
cereal_ModelData_ptr cereal_new_ModelData(struct capn_segment*);
cereal_ModelData_PathData_ptr cereal_new_ModelData_PathData(struct capn_segment*);
cereal_ModelData_LeadData_ptr cereal_new_ModelData_LeadData(struct capn_segment*);
cereal_ModelData_ModelSettings_ptr cereal_new_ModelData_ModelSettings(struct capn_segment*);
cereal_CalibrationFeatures_ptr cereal_new_CalibrationFeatures(struct capn_segment*);
cereal_EncodeIndex_ptr cereal_new_EncodeIndex(struct capn_segment*);
cereal_AndroidLogEntry_ptr cereal_new_AndroidLogEntry(struct capn_segment*);
cereal_LogRotate_ptr cereal_new_LogRotate(struct capn_segment*);
cereal_Event_ptr cereal_new_Event(struct capn_segment*);
cereal_InitData_list cereal_new_InitData_list(struct capn_segment*, int len);
cereal_FrameData_list cereal_new_FrameData_list(struct capn_segment*, int len);
cereal_GPSNMEAData_list cereal_new_GPSNMEAData_list(struct capn_segment*, int len);
cereal_SensorEventData_list cereal_new_SensorEventData_list(struct capn_segment*, int len);
cereal_SensorEventData_SensorVec_list cereal_new_SensorEventData_SensorVec_list(struct capn_segment*, int len);
cereal_CanData_list cereal_new_CanData_list(struct capn_segment*, int len);
cereal_ThermalData_list cereal_new_ThermalData_list(struct capn_segment*, int len);
cereal_HealthData_list cereal_new_HealthData_list(struct capn_segment*, int len);
cereal_LiveUI_list cereal_new_LiveUI_list(struct capn_segment*, int len);
cereal_Live20Data_list cereal_new_Live20Data_list(struct capn_segment*, int len);
cereal_Live20Data_LeadData_list cereal_new_Live20Data_LeadData_list(struct capn_segment*, int len);
cereal_LiveCalibrationData_list cereal_new_LiveCalibrationData_list(struct capn_segment*, int len);
cereal_LiveTracks_list cereal_new_LiveTracks_list(struct capn_segment*, int len);
cereal_Live100Data_list cereal_new_Live100Data_list(struct capn_segment*, int len);
cereal_LiveEventData_list cereal_new_LiveEventData_list(struct capn_segment*, int len);
cereal_ModelData_list cereal_new_ModelData_list(struct capn_segment*, int len);
cereal_ModelData_PathData_list cereal_new_ModelData_PathData_list(struct capn_segment*, int len);
cereal_ModelData_LeadData_list cereal_new_ModelData_LeadData_list(struct capn_segment*, int len);
cereal_ModelData_ModelSettings_list cereal_new_ModelData_ModelSettings_list(struct capn_segment*, int len);
cereal_CalibrationFeatures_list cereal_new_CalibrationFeatures_list(struct capn_segment*, int len);
cereal_EncodeIndex_list cereal_new_EncodeIndex_list(struct capn_segment*, int len);
cereal_AndroidLogEntry_list cereal_new_AndroidLogEntry_list(struct capn_segment*, int len);
cereal_LogRotate_list cereal_new_LogRotate_list(struct capn_segment*, int len);
cereal_Event_list cereal_new_Event_list(struct capn_segment*, int len);
void cereal_read_InitData(struct cereal_InitData*, cereal_InitData_ptr);
void cereal_read_FrameData(struct cereal_FrameData*, cereal_FrameData_ptr);
void cereal_read_GPSNMEAData(struct cereal_GPSNMEAData*, cereal_GPSNMEAData_ptr);
void cereal_read_SensorEventData(struct cereal_SensorEventData*, cereal_SensorEventData_ptr);
void cereal_read_SensorEventData_SensorVec(struct cereal_SensorEventData_SensorVec*, cereal_SensorEventData_SensorVec_ptr);
void cereal_read_CanData(struct cereal_CanData*, cereal_CanData_ptr);
void cereal_read_ThermalData(struct cereal_ThermalData*, cereal_ThermalData_ptr);
void cereal_read_HealthData(struct cereal_HealthData*, cereal_HealthData_ptr);
void cereal_read_LiveUI(struct cereal_LiveUI*, cereal_LiveUI_ptr);
void cereal_read_Live20Data(struct cereal_Live20Data*, cereal_Live20Data_ptr);
void cereal_read_Live20Data_LeadData(struct cereal_Live20Data_LeadData*, cereal_Live20Data_LeadData_ptr);
void cereal_read_LiveCalibrationData(struct cereal_LiveCalibrationData*, cereal_LiveCalibrationData_ptr);
void cereal_read_LiveTracks(struct cereal_LiveTracks*, cereal_LiveTracks_ptr);
void cereal_read_Live100Data(struct cereal_Live100Data*, cereal_Live100Data_ptr);
void cereal_read_LiveEventData(struct cereal_LiveEventData*, cereal_LiveEventData_ptr);
void cereal_read_ModelData(struct cereal_ModelData*, cereal_ModelData_ptr);
void cereal_read_ModelData_PathData(struct cereal_ModelData_PathData*, cereal_ModelData_PathData_ptr);
void cereal_read_ModelData_LeadData(struct cereal_ModelData_LeadData*, cereal_ModelData_LeadData_ptr);
void cereal_read_ModelData_ModelSettings(struct cereal_ModelData_ModelSettings*, cereal_ModelData_ModelSettings_ptr);
void cereal_read_CalibrationFeatures(struct cereal_CalibrationFeatures*, cereal_CalibrationFeatures_ptr);
void cereal_read_EncodeIndex(struct cereal_EncodeIndex*, cereal_EncodeIndex_ptr);
void cereal_read_AndroidLogEntry(struct cereal_AndroidLogEntry*, cereal_AndroidLogEntry_ptr);
void cereal_read_LogRotate(struct cereal_LogRotate*, cereal_LogRotate_ptr);
void cereal_read_Event(struct cereal_Event*, cereal_Event_ptr);
void cereal_write_InitData(const struct cereal_InitData*, cereal_InitData_ptr);
void cereal_write_FrameData(const struct cereal_FrameData*, cereal_FrameData_ptr);
void cereal_write_GPSNMEAData(const struct cereal_GPSNMEAData*, cereal_GPSNMEAData_ptr);
void cereal_write_SensorEventData(const struct cereal_SensorEventData*, cereal_SensorEventData_ptr);
void cereal_write_SensorEventData_SensorVec(const struct cereal_SensorEventData_SensorVec*, cereal_SensorEventData_SensorVec_ptr);
void cereal_write_CanData(const struct cereal_CanData*, cereal_CanData_ptr);
void cereal_write_ThermalData(const struct cereal_ThermalData*, cereal_ThermalData_ptr);
void cereal_write_HealthData(const struct cereal_HealthData*, cereal_HealthData_ptr);
void cereal_write_LiveUI(const struct cereal_LiveUI*, cereal_LiveUI_ptr);
void cereal_write_Live20Data(const struct cereal_Live20Data*, cereal_Live20Data_ptr);
void cereal_write_Live20Data_LeadData(const struct cereal_Live20Data_LeadData*, cereal_Live20Data_LeadData_ptr);
void cereal_write_LiveCalibrationData(const struct cereal_LiveCalibrationData*, cereal_LiveCalibrationData_ptr);
void cereal_write_LiveTracks(const struct cereal_LiveTracks*, cereal_LiveTracks_ptr);
void cereal_write_Live100Data(const struct cereal_Live100Data*, cereal_Live100Data_ptr);
void cereal_write_LiveEventData(const struct cereal_LiveEventData*, cereal_LiveEventData_ptr);
void cereal_write_ModelData(const struct cereal_ModelData*, cereal_ModelData_ptr);
void cereal_write_ModelData_PathData(const struct cereal_ModelData_PathData*, cereal_ModelData_PathData_ptr);
void cereal_write_ModelData_LeadData(const struct cereal_ModelData_LeadData*, cereal_ModelData_LeadData_ptr);
void cereal_write_ModelData_ModelSettings(const struct cereal_ModelData_ModelSettings*, cereal_ModelData_ModelSettings_ptr);
void cereal_write_CalibrationFeatures(const struct cereal_CalibrationFeatures*, cereal_CalibrationFeatures_ptr);
void cereal_write_EncodeIndex(const struct cereal_EncodeIndex*, cereal_EncodeIndex_ptr);
void cereal_write_AndroidLogEntry(const struct cereal_AndroidLogEntry*, cereal_AndroidLogEntry_ptr);
void cereal_write_LogRotate(const struct cereal_LogRotate*, cereal_LogRotate_ptr);
void cereal_write_Event(const struct cereal_Event*, cereal_Event_ptr);
void cereal_get_InitData(struct cereal_InitData*, cereal_InitData_list, int i);
void cereal_get_FrameData(struct cereal_FrameData*, cereal_FrameData_list, int i);
void cereal_get_GPSNMEAData(struct cereal_GPSNMEAData*, cereal_GPSNMEAData_list, int i);
void cereal_get_SensorEventData(struct cereal_SensorEventData*, cereal_SensorEventData_list, int i);
void cereal_get_SensorEventData_SensorVec(struct cereal_SensorEventData_SensorVec*, cereal_SensorEventData_SensorVec_list, int i);
void cereal_get_CanData(struct cereal_CanData*, cereal_CanData_list, int i);
void cereal_get_ThermalData(struct cereal_ThermalData*, cereal_ThermalData_list, int i);
void cereal_get_HealthData(struct cereal_HealthData*, cereal_HealthData_list, int i);
void cereal_get_LiveUI(struct cereal_LiveUI*, cereal_LiveUI_list, int i);
void cereal_get_Live20Data(struct cereal_Live20Data*, cereal_Live20Data_list, int i);
void cereal_get_Live20Data_LeadData(struct cereal_Live20Data_LeadData*, cereal_Live20Data_LeadData_list, int i);
void cereal_get_LiveCalibrationData(struct cereal_LiveCalibrationData*, cereal_LiveCalibrationData_list, int i);
void cereal_get_LiveTracks(struct cereal_LiveTracks*, cereal_LiveTracks_list, int i);
void cereal_get_Live100Data(struct cereal_Live100Data*, cereal_Live100Data_list, int i);
void cereal_get_LiveEventData(struct cereal_LiveEventData*, cereal_LiveEventData_list, int i);
void cereal_get_ModelData(struct cereal_ModelData*, cereal_ModelData_list, int i);
void cereal_get_ModelData_PathData(struct cereal_ModelData_PathData*, cereal_ModelData_PathData_list, int i);
void cereal_get_ModelData_LeadData(struct cereal_ModelData_LeadData*, cereal_ModelData_LeadData_list, int i);
void cereal_get_ModelData_ModelSettings(struct cereal_ModelData_ModelSettings*, cereal_ModelData_ModelSettings_list, int i);
void cereal_get_CalibrationFeatures(struct cereal_CalibrationFeatures*, cereal_CalibrationFeatures_list, int i);
void cereal_get_EncodeIndex(struct cereal_EncodeIndex*, cereal_EncodeIndex_list, int i);
void cereal_get_AndroidLogEntry(struct cereal_AndroidLogEntry*, cereal_AndroidLogEntry_list, int i);
void cereal_get_LogRotate(struct cereal_LogRotate*, cereal_LogRotate_list, int i);
void cereal_get_Event(struct cereal_Event*, cereal_Event_list, int i);
void cereal_set_InitData(const struct cereal_InitData*, cereal_InitData_list, int i);
void cereal_set_FrameData(const struct cereal_FrameData*, cereal_FrameData_list, int i);
void cereal_set_GPSNMEAData(const struct cereal_GPSNMEAData*, cereal_GPSNMEAData_list, int i);
void cereal_set_SensorEventData(const struct cereal_SensorEventData*, cereal_SensorEventData_list, int i);
void cereal_set_SensorEventData_SensorVec(const struct cereal_SensorEventData_SensorVec*, cereal_SensorEventData_SensorVec_list, int i);
void cereal_set_CanData(const struct cereal_CanData*, cereal_CanData_list, int i);
void cereal_set_ThermalData(const struct cereal_ThermalData*, cereal_ThermalData_list, int i);
void cereal_set_HealthData(const struct cereal_HealthData*, cereal_HealthData_list, int i);
void cereal_set_LiveUI(const struct cereal_LiveUI*, cereal_LiveUI_list, int i);
void cereal_set_Live20Data(const struct cereal_Live20Data*, cereal_Live20Data_list, int i);
void cereal_set_Live20Data_LeadData(const struct cereal_Live20Data_LeadData*, cereal_Live20Data_LeadData_list, int i);
void cereal_set_LiveCalibrationData(const struct cereal_LiveCalibrationData*, cereal_LiveCalibrationData_list, int i);
void cereal_set_LiveTracks(const struct cereal_LiveTracks*, cereal_LiveTracks_list, int i);
void cereal_set_Live100Data(const struct cereal_Live100Data*, cereal_Live100Data_list, int i);
void cereal_set_LiveEventData(const struct cereal_LiveEventData*, cereal_LiveEventData_list, int i);
void cereal_set_ModelData(const struct cereal_ModelData*, cereal_ModelData_list, int i);
void cereal_set_ModelData_PathData(const struct cereal_ModelData_PathData*, cereal_ModelData_PathData_list, int i);
void cereal_set_ModelData_LeadData(const struct cereal_ModelData_LeadData*, cereal_ModelData_LeadData_list, int i);
void cereal_set_ModelData_ModelSettings(const struct cereal_ModelData_ModelSettings*, cereal_ModelData_ModelSettings_list, int i);
void cereal_set_CalibrationFeatures(const struct cereal_CalibrationFeatures*, cereal_CalibrationFeatures_list, int i);
void cereal_set_EncodeIndex(const struct cereal_EncodeIndex*, cereal_EncodeIndex_list, int i);
void cereal_set_AndroidLogEntry(const struct cereal_AndroidLogEntry*, cereal_AndroidLogEntry_list, int i);
void cereal_set_LogRotate(const struct cereal_LogRotate*, cereal_LogRotate_list, int i);
void cereal_set_Event(const struct cereal_Event*, cereal_Event_list, int i);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

28
cereal/java.capnp Normal file
View File

@@ -0,0 +1,28 @@
# Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
# Licensed under the MIT License:
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
@0xc5f1af96651f70ea;
annotation package @0x9ee4c8f803b3b596 (file) : Text;
# Name of the package, such as "org.example.foo", in which the generated code will reside.
annotation outerClassname @0x9b066bb4881f7cd3 (file) : Text;
# Name of the outer class that will wrap the generated code.

View File

@@ -1,14 +1,100 @@
using Cxx = import "c++.capnp";
$Cxx.namespace("cereal");
using Java = import "java.capnp";
$Java.package("ai.comma.openpilot.cereal");
$Java.outerClassname("Log");
using Car = import "car.capnp";
@0xf3b1f17e25a4285b;
const logVersion :Int32 = 1;
struct Map(Key, Value) {
entries @0 :List(Entry);
struct Entry {
key @0 :Key;
value @1 :Value;
}
}
struct InitData {
kernelArgs @0 :List(Text);
gctx @1 :Text;
dongleId @2 :Text;
deviceType @3 :DeviceType;
version @4 :Text;
androidBuildInfo @5 :AndroidBuildInfo;
androidSensors @6 :List(AndroidSensor);
chffrAndroidExtra @7 :ChffrAndroidExtra;
pandaInfo @8 :PandaInfo;
dirty @9 :Bool;
enum DeviceType {
unknown @0;
neo @1;
chffrAndroid @2;
}
struct AndroidBuildInfo {
board @0 :Text;
bootloader @1 :Text;
brand @2 :Text;
device @3 :Text;
display @4 :Text;
fingerprint @5 :Text;
hardware @6 :Text;
host @7 :Text;
id @8 :Text;
manufacturer @9 :Text;
model @10 :Text;
product @11 :Text;
radioVersion @12 :Text;
serial @13 :Text;
supportedAbis @14 :List(Text);
tags @15 :Text;
time @16 :Int64;
type @17 :Text;
user @18 :Text;
versionCodename @19 :Text;
versionRelease @20 :Text;
versionSdk @21 :Int32;
versionSecurityPatch @22 :Text;
}
struct AndroidSensor {
id @0 :Int32;
name @1 :Text;
vendor @2 :Text;
version @3 :Int32;
handle @4 :Int32;
type @5 :Int32;
maxRange @6 :Float32;
resolution @7 :Float32;
power @8 :Float32;
minDelay @9 :Int32;
fifoReservedEventCount @10 :UInt32;
fifoMaxEventCount @11 :UInt32;
stringType @12 :Text;
maxDelay @13 :Int32;
}
struct ChffrAndroidExtra {
allCameraCharacteristics @0 :Map(Text, Text);
}
struct PandaInfo {
hasPanda @0: Bool;
dongleId @1: Text;
stVersion @2: Text;
espVersion @3: Text;
}
}
struct FrameData {
@@ -19,6 +105,27 @@ struct FrameData {
integLines @4 :Int32;
globalGain @5 :Int32;
image @6 :Data;
frameType @7 :FrameType;
timestampSof @8 :UInt64;
androidCaptureResult @9 :AndroidCaptureResult;
enum FrameType {
unknown @0;
neo @1;
chffrAndroid @2;
}
struct AndroidCaptureResult {
sensitivity @0 :Int32;
frameDuration @1 :Int64;
exposureTime @2 :Int64;
rollingShutterSkew @3 :UInt64;
colorCorrectionTransform @4 :List(Int32);
colorCorrectionGains @5 :List(Float32);
displayRotation @6 :Int8;
}
}
struct GPSNMEAData {
@@ -33,24 +140,89 @@ struct SensorEventData {
sensor @1 :Int32;
type @2 :Int32;
timestamp @3 :Int64;
uncalibratedDEPRECATED @10 :Bool;
union {
acceleration @4 :SensorVec;
magnetic @5 :SensorVec;
orientation @6 :SensorVec;
gyro @7 :SensorVec;
pressure @9 :SensorVec;
magneticUncalibrated @11 :SensorVec;
gyroUncalibrated @12 :SensorVec;
}
source @8 :SensorSource;
struct SensorVec {
v @0 :List(Float32);
status @1 :Int8;
}
enum SensorSource {
android @0;
iOS @1;
fiber @2;
velodyne @3; # Velodyne IMU
}
}
# android struct GpsLocation
struct GpsLocationData {
# Contains GpsLocationFlags bits.
flags @0 :UInt16;
# Represents latitude in degrees.
latitude @1 :Float64;
# Represents longitude in degrees.
longitude @2 :Float64;
# Represents altitude in meters above the WGS 84 reference ellipsoid.
altitude @3 :Float64;
# Represents speed in meters per second.
speed @4 :Float32;
# Represents heading in degrees.
bearing @5 :Float32;
# Represents expected accuracy in meters. (presumably 1 sigma?)
accuracy @6 :Float32;
# Timestamp for the location fix.
# Milliseconds since January 1, 1970.
timestamp @7 :Int64;
source @8 :SensorSource;
# Represents NED velocity in m/s.
vNED @9 :List(Float32);
# Represents expected vertical accuracy in meters. (presumably 1 sigma?)
verticalAccuracy @10 :Float32;
# Represents bearing accuracy in degrees. (presumably 1 sigma?)
bearingAccuracy @11 :Float32;
# Represents velocity accuracy in m/s. (presumably 1 sigma?)
speedAccuracy @12 :Float32;
enum SensorSource {
android @0;
iOS @1;
car @2;
velodyne @3; # Velodyne IMU
fusion @4;
external @5;
ublox @6;
}
}
struct CanData {
address @0 :UInt32;
busTime @1 :UInt16;
dat @2 :Data;
src @3 :Int8;
src @3 :UInt8;
}
struct ThermalData {
@@ -61,6 +233,11 @@ struct ThermalData {
mem @4 :UInt16;
gpu @5 :UInt16;
bat @6 :UInt32;
# not thermal
freeSpace @7 :Float32;
batteryPercent @8 :Int16;
batteryStatus @9: Text;
}
struct HealthData {
@@ -70,6 +247,7 @@ struct HealthData {
started @2 :Bool;
controlsAllowed @3 :Bool;
gasInterceptorDetected @4 :Bool;
startedSignalDetected @5 :Bool;
}
struct LiveUI {
@@ -82,14 +260,15 @@ struct LiveUI {
struct Live20Data {
canMonoTimes @10 :List(UInt64);
mdMonoTime @6 :UInt64;
ftMonoTime @7 :UInt64;
ftMonoTimeDEPRECATED @7 :UInt64;
l100MonoTime @11 :UInt64;
# all deprecated
warpMatrix @0 :List(Float32);
angleOffset @1 :Float32;
calStatus @2 :Int8;
calCycle @8 :Int32;
calPerc @9 :Int8;
warpMatrixDEPRECATED @0 :List(Float32);
angleOffsetDEPRECATED @1 :Float32;
calStatusDEPRECATED @2 :Int8;
calCycleDEPRECATED @8 :Int32;
calPercDEPRECATED @9 :Int8;
leadOne @3 :LeadData;
leadTwo @4 :LeadData;
@@ -116,6 +295,9 @@ struct LiveCalibrationData {
calStatus @1 :Int8;
calCycle @2 :Int32;
calPerc @3 :Int8;
# Maps car space to normalized image space.
extrinsicMatrix @4 :List(Float32);
}
struct LiveTracks {
@@ -132,13 +314,14 @@ struct LiveTracks {
}
struct Live100Data {
canMonoTime @16 :UInt64;
canMonoTimeDEPRECATED @16 :UInt64;
canMonoTimes @21 :List(UInt64);
l20MonoTime @17 :UInt64;
mdMonoTime @18 :UInt64;
l20MonoTimeDEPRECATED @17 :UInt64;
mdMonoTimeDEPRECATED @18 :UInt64;
planMonoTime @28 :UInt64;
vEgo @0 :Float32;
aEgo @1 :Float32;
aEgoDEPRECATED @1 :Float32;
vPid @2 :Float32;
vTargetLead @3 :Float32;
upAccelCmd @4 :Float32;
@@ -150,8 +333,8 @@ struct Live100Data {
aTargetMin @10 :Float32;
aTargetMax @11 :Float32;
jerkFactor @12 :Float32;
angleSteers @13 :Float32;
hudLead @14 :Int32;
angleSteers @13 :Float32; # Steering angle in degrees.
hudLeadDEPRECATED @14 :Int32;
cumLagMs @15 :Float32;
enabled @19: Bool;
@@ -163,6 +346,8 @@ struct Live100Data {
alertText1 @24 :Text;
alertText2 @25 :Text;
awarenessStatus @26 :Float32;
angleOffset @27 :Float32;
}
struct LiveEventData {
@@ -218,13 +403,17 @@ struct EncodeIndex {
encodeId @2 :UInt32;
# minute long segment this frame is in
segmentNum @3 :Int32;
# index into camera file in segment from 0
# index into camera file in segment in presentation order
segmentId @4 :UInt32;
# index into camera file in segment in encode order
segmentIdEncode @5 :UInt32;
enum Type {
bigBoxLossless @0; # rcamera.mkv
fullHEVC @1; # fcamera.hevc
bigBoxHEVC @2; # bcamera.hevc
chffrAndroidH264 @3; # acamera
fullLosslessClip @4; # prcamera.mkv
}
}
@@ -243,8 +432,617 @@ struct LogRotate {
path @1 :Text;
}
struct Plan {
mdMonoTime @9 :UInt64;
l20MonoTime @10 :UInt64;
# lateral, 3rd order polynomial
lateralValid @0: Bool;
dPoly @1 :List(Float32);
# longitudinal
longitudinalValid @2: Bool;
vTarget @3 :Float32;
aTargetMin @4 :Float32;
aTargetMax @5 :Float32;
jerkFactor @6 :Float32;
hasLead @7 :Bool;
fcw @8 :Bool;
}
struct LiveLocationData {
status @0: UInt8;
# 3D fix
lat @1: Float64;
lon @2: Float64;
alt @3: Float32; # m
# speed
speed @4: Float32; # m/s
# NED velocity components
vNED @5: List(Float32);
# roll, pitch, heading (x,y,z)
roll @6: Float32; # WRT to center of earth?
pitch @7: Float32; # WRT to center of earth?
heading @8: Float32; # WRT to north?
# what are these?
wanderAngle @9: Float32;
trackAngle @10: Float32;
# car frame -- https://upload.wikimedia.org/wikipedia/commons/f/f5/RPY_angles_of_cars.png
# gyro, in car frame, deg/s
gyro @11: List(Float32);
# accel, in car frame, m/s^2
accel @12: List(Float32);
accuracy @13: Accuracy;
struct Accuracy {
pNEDError @0: List(Float32);
vNEDError @1: List(Float32);
rollError @2: Float32;
pitchError @3: Float32;
headingError @4: Float32;
ellipsoidSemiMajorError @5: Float32;
ellipsoidSemiMinorError @6: Float32;
ellipsoidOrientationError @7: Float32;
}
}
struct EthernetPacket {
pkt @0 :Data;
ts @1: Float32;
}
struct NavUpdate {
isNavigating @0 :Bool;
curSegment @1 :Int32;
segments @2 :List(Segment);
struct LatLng {
lat @0 :Float64;
lng @1 :Float64;
}
struct Segment {
from @0 :LatLng;
to @1 :LatLng;
updateTime @2 :Int32;
distance @3 :Int32;
crossTime @4 :Int32;
exitNo @5 :Int32;
instruction @6 :Instruction;
parts @7 :List(LatLng);
enum Instruction {
turnLeft @0;
turnRight @1;
keepLeft @2;
keepRight @3;
straight @4;
roundaboutExitNumber @5;
roundaboutExit @6;
roundaboutTurnLeft @7;
unkn8 @8;
roundaboutStraight @9;
unkn10 @10;
roundaboutTurnRight @11;
unkn12 @12;
roundaboutUturn @13;
unkn14 @14;
arrive @15;
exitLeft @16;
exitRight @17;
unkn18 @18;
uturn @19;
# ...
}
}
}
struct CellInfo {
timestamp @0 :UInt64;
repr @1 :Text; # android toString() for now
}
struct WifiScan {
bssid @0 :Text;
ssid @1 :Text;
capabilities @2 :Text;
frequency @3 :Int32;
level @4 :Int32;
timestamp @5 :Int64;
centerFreq0 @6 :Int32;
centerFreq1 @7 :Int32;
channelWidth @8 :ChannelWidth;
operatorFriendlyName @9 :Text;
venueName @10 :Text;
is80211mcResponder @11 :Bool;
passpoint @12 :Bool;
distanceCm @13 :Int32;
distanceSdCm @14 :Int32;
enum ChannelWidth {
w20Mhz @0;
w40Mhz @1;
w80Mhz @2;
w160Mhz @3;
w80Plus80Mhz @4;
}
}
struct AndroidGnss {
union {
measurements @0 :Measurements;
navigationMessage @1 :NavigationMessage;
}
struct Measurements {
clock @0 :Clock;
measurements @1 :List(Measurement);
struct Clock {
timeNanos @0 :Int64;
hardwareClockDiscontinuityCount @1 :Int32;
hasTimeUncertaintyNanos @2 :Bool;
timeUncertaintyNanos @3 :Float64;
hasLeapSecond @4 :Bool;
leapSecond @5 :Int32;
hasFullBiasNanos @6 :Bool;
fullBiasNanos @7 :Int64;
hasBiasNanos @8 :Bool;
biasNanos @9 :Float64;
hasBiasUncertaintyNanos @10 :Bool;
biasUncertaintyNanos @11 :Float64;
hasDriftNanosPerSecond @12 :Bool;
driftNanosPerSecond @13 :Float64;
hasDriftUncertaintyNanosPerSecond @14 :Bool;
driftUncertaintyNanosPerSecond @15 :Float64;
}
struct Measurement {
svId @0 :Int32;
constellation @1 :Constellation;
timeOffsetNanos @2 :Float64;
state @3 :Int32;
receivedSvTimeNanos @4 :Int64;
receivedSvTimeUncertaintyNanos @5 :Int64;
cn0DbHz @6 :Float64;
pseudorangeRateMetersPerSecond @7 :Float64;
pseudorangeRateUncertaintyMetersPerSecond @8 :Float64;
accumulatedDeltaRangeState @9 :Int32;
accumulatedDeltaRangeMeters @10 :Float64;
accumulatedDeltaRangeUncertaintyMeters @11 :Float64;
hasCarrierFrequencyHz @12 :Bool;
carrierFrequencyHz @13 :Float32;
hasCarrierCycles @14 :Bool;
carrierCycles @15 :Int64;
hasCarrierPhase @16 :Bool;
carrierPhase @17 :Float64;
hasCarrierPhaseUncertainty @18 :Bool;
carrierPhaseUncertainty @19 :Float64;
hasSnrInDb @20 :Bool;
snrInDb @21 :Float64;
multipathIndicator @22 :MultipathIndicator;
enum Constellation {
unknown @0;
gps @1;
sbas @2;
glonass @3;
qzss @4;
beidou @5;
galileo @6;
}
enum State {
unknown @0;
codeLock @1;
bitSync @2;
subframeSync @3;
towDecoded @4;
msecAmbiguous @5;
symbolSync @6;
gloStringSync @7;
gloTodDecoded @8;
bdsD2BitSync @9;
bdsD2SubframeSync @10;
galE1bcCodeLock @11;
galE1c2ndCodeLock @12;
galE1bPageSync @13;
sbasSync @14;
}
enum MultipathIndicator {
unknown @0;
detected @1;
notDetected @2;
}
}
}
struct NavigationMessage {
type @0 :Int32;
svId @1 :Int32;
messageId @2 :Int32;
submessageId @3 :Int32;
data @4 :Data;
status @5 :Status;
enum Status {
unknown @0;
parityPassed @1;
parityRebuilt @2;
}
}
}
struct QcomGnss {
logTs @0 :UInt64;
union {
measurementReport @1 :MeasurementReport;
clockReport @2 :ClockReport;
}
struct MeasurementReport {
source @0 :Source;
fCount @1 :UInt32;
gpsWeek @2 :UInt16;
glonassCycleNumber @3 :UInt8;
glonassNumberOfDays @4 :UInt16;
milliseconds @5 :UInt32;
timeBias @6 :Float32;
clockTimeUncertainty @7 :Float32;
clockFrequencyBias @8 :Float32;
clockFrequencyUncertainty @9 :Float32;
sv @10 :List(SV);
enum Source {
gps @0;
glonass @1;
}
struct SV {
svId @0 :UInt8;
observationState @2 :SVObservationState;
observations @3 :UInt8;
goodObservations @4 :UInt8;
gpsParityErrorCount @5 :UInt16;
glonassFrequencyIndex @1 :Int8;
glonassHemmingErrorCount @6 :UInt8;
filterStages @7 :UInt8;
carrierNoise @8 :UInt16;
latency @9 :Int16;
predetectIntegration @10 :UInt8;
postdetections @11 :UInt16;
unfilteredMeasurementIntegral @12 :UInt32;
unfilteredMeasurementFraction @13 :Float32;
unfilteredTimeUncertainty @14 :Float32;
unfilteredSpeed @15 :Float32;
unfilteredSpeedUncertainty @16 :Float32;
measurementStatus @17 :MeasurementStatus;
multipathEstimate @18 :UInt32;
azimuth @19 :Float32;
elevation @20 :Float32;
carrierPhaseCyclesIntegral @21 :Int32;
carrierPhaseCyclesFraction @22 :UInt16;
fineSpeed @23 :Float32;
fineSpeedUncertainty @24 :Float32;
cycleSlipCount @25 :UInt8;
struct MeasurementStatus {
subMillisecondIsValid @0 :Bool;
subBitTimeIsKnown @1 :Bool;
satelliteTimeIsKnown @2 :Bool;
bitEdgeConfirmedFromSignal @3 :Bool;
measuredVelocity @4 :Bool;
fineOrCoarseVelocity @5 :Bool;
lockPointValid @6 :Bool;
lockPointPositive @7 :Bool;
lastUpdateFromDifference @8 :Bool;
lastUpdateFromVelocityDifference @9 :Bool;
strongIndicationOfCrossCorelation @10 :Bool;
tentativeMeasurement @11 :Bool;
measurementNotUsable @12 :Bool;
sirCheckIsNeeded @13 :Bool;
probationMode @14 :Bool;
glonassMeanderBitEdgeValid @15 :Bool;
glonassTimeMarkValid @16 :Bool;
gpsRoundRobinRxDiversity @17 :Bool;
gpsRxDiversity @18 :Bool;
gpsLowBandwidthRxDiversityCombined @19 :Bool;
gpsHighBandwidthNu4 @20 :Bool;
gpsHighBandwidthNu8 @21 :Bool;
gpsHighBandwidthUniform @22 :Bool;
gpsMultipathIndicator @23 :Bool;
imdJammingIndicator @24 :Bool;
lteB13TxJammingIndicator @25 :Bool;
freshMeasurementIndicator @26 :Bool;
multipathEstimateIsValid @27 :Bool;
directionIsValid @28 :Bool;
}
enum SVObservationState {
idle @0;
search @1;
searchVerify @2;
bitEdge @3;
trackVerify @4;
track @5;
restart @6;
dpo @7;
glo10msBe @8;
glo10msAt @9;
}
}
}
struct ClockReport {
hasFCount @0 :Bool;
fCount @1 :UInt32;
hasGpsWeekNumber @2 :Bool;
gpsWeekNumber @3 :UInt16;
hasGpsMilliseconds @4 :Bool;
gpsMilliseconds @5 :UInt32;
gpsTimeBias @6 :Float32;
gpsClockTimeUncertainty @7 :Float32;
gpsClockSource @8 :UInt8;
hasGlonassYear @9 :Bool;
glonassYear @10 :UInt8;
hasGlonassDay @11 :Bool;
glonassDay @12 :UInt16;
hasGlonassMilliseconds @13 :Bool;
glonassMilliseconds @14 :UInt32;
glonassTimeBias @15 :Float32;
glonassClockTimeUncertainty @16 :Float32;
glonassClockSource @17 :UInt8;
bdsWeek @18 :UInt16;
bdsMilliseconds @19 :UInt32;
bdsTimeBias @20 :Float32;
bdsClockTimeUncertainty @21 :Float32;
bdsClockSource @22 :UInt8;
galWeek @23 :UInt16;
galMilliseconds @24 :UInt32;
galTimeBias @25 :Float32;
galClockTimeUncertainty @26 :Float32;
galClockSource @27 :UInt8;
clockFrequencyBias @28 :Float32;
clockFrequencyUncertainty @29 :Float32;
frequencySource @30 :UInt8;
gpsLeapSeconds @31 :UInt8;
gpsLeapSecondsUncertainty @32 :UInt8;
gpsLeapSecondsSource @33 :UInt8;
gpsToGlonassTimeBiasMilliseconds @34 :Float32;
gpsToGlonassTimeBiasMillisecondsUncertainty @35 :Float32;
gpsToBdsTimeBiasMilliseconds @36 :Float32;
gpsToBdsTimeBiasMillisecondsUncertainty @37 :Float32;
bdsToGloTimeBiasMilliseconds @38 :Float32;
bdsToGloTimeBiasMillisecondsUncertainty @39 :Float32;
gpsToGalTimeBiasMilliseconds @40 :Float32;
gpsToGalTimeBiasMillisecondsUncertainty @41 :Float32;
galToGloTimeBiasMilliseconds @42 :Float32;
galToGloTimeBiasMillisecondsUncertainty @43 :Float32;
galToBdsTimeBiasMilliseconds @44 :Float32;
galToBdsTimeBiasMillisecondsUncertainty @45 :Float32;
hasRtcTime @46 :Bool;
systemRtcTime @47 :UInt32;
fCountOffset @48 :UInt32;
lpmRtcCount @49 :UInt32;
clockResets @50 :UInt32;
}
}
struct LidarPts {
r @0 :List(UInt16); # uint16 m*500.0
theta @1 :List(UInt16); # uint16 deg*100.0
reflect @2 :List(UInt8); # uint8 0-255
# For storing out of file.
idx @3 :UInt64;
# For storing in file
pkt @4 :Data;
}
struct ProcLog {
cpuTimes @0 :List(CPUTimes);
mem @1 :Mem;
procs @2 :List(Process);
struct Process {
pid @0 :Int32;
name @1 :Text;
state @2 :UInt8;
ppid @3 :Int32;
cpuUser @4 :Float32;
cpuSystem @5 :Float32;
cpuChildrenUser @6 :Float32;
cpuChildrenSystem @7 :Float32;
priority @8 :Int64;
nice @9 :Int32;
numThreads @10 :Int32;
startTime @11 :Float64;
memVms @12 :UInt64;
memRss @13 :UInt64;
processor @14 :Int32;
cmdline @15 :List(Text);
exe @16 :Text;
}
struct CPUTimes {
cpuNum @0 :Int64;
user @1 :Float32;
nice @2 :Float32;
system @3 :Float32;
idle @4 :Float32;
iowait @5 :Float32;
irq @6 :Float32;
softirq @7 :Float32;
}
struct Mem {
total @0 :UInt64;
free @1 :UInt64;
available @2 :UInt64;
buffers @3 :UInt64;
cached @4 :UInt64;
active @5 :UInt64;
inactive @6 :UInt64;
shared @7 :UInt64;
}
}
struct UbloxGnss {
union {
measurementReport @0 :MeasurementReport;
ephemeris @1 :Ephemeris;
}
struct MeasurementReport {
#received time of week in gps time in seconds and gps week
rcvTow @0 :Float64;
gpsWeek @1 :UInt16;
# leap seconds in seconds
leapSeconds @2 :UInt16;
# receiver status
receiverStatus @3 :ReceiverStatus;
# num of measurements to follow
numMeas @4 :UInt8;
measurements @5 :List(Measurement);
struct ReceiverStatus {
# leap seconds have been determined
leapSecValid @0 :Bool;
# Clock reset applied
clkReset @1 : Bool;
}
struct Measurement {
svId @0 :UInt8;
trackingStatus @1 :TrackingStatus;
# pseudorange in meters
pseudorange @2 :Float64;
# carrier phase measurement in cycles
carrierCycles @3 :Float64;
# doppler measurement in Hz
doppler @4 :Float32;
# GNSS id, 0 is gps
gnssId @5 :UInt8;
glonassFrequencyIndex @6 :UInt8;
# carrier phase locktime counter in ms
locktime @7 :UInt16;
# Carrier-to-noise density ratio (signal strength) in dBHz
cno @8 : UInt8;
# pseudorange standard deviation in meters
pseudorangeStdev @9 :Float32;
# carrier phase standard deviation in cycles
carrierPhaseStdev @10 :Float32;
# doppler standard deviation in Hz
dopplerStdev @11 :Float32;
struct TrackingStatus {
# pseudorange valid
pseudorangeValid @0 :Bool;
# carrier phase valid
carrierPhaseValid @1 :Bool;
# half cycle valid
halfCycleValid @2 :Bool;
# half sycle subtracted from phase
halfCycleSubtracted @3 :Bool;
}
}
}
struct Ephemeris {
# This is according to the rinex (2?) format
svId @0 :UInt16;
year @1 :UInt16;
month @2 :UInt16;
day @3 :UInt16;
hour @4 :UInt16;
minute @5 :UInt16;
second @6 :Float32;
af0 @7 :Float64;
af1 @8 :Float64;
af2 @9 :Float64;
iode @10 :Float64;
crs @11 :Float64;
deltaN @12 :Float64;
m0 @13 :Float64;
cuc @14 :Float64;
ecc @15 :Float64;
cus @16 :Float64;
a @17 :Float64; # note that this is not the root!!
toe @18 :Float64;
cic @19 :Float64;
omega0 @20 :Float64;
cis @21 :Float64;
i0 @22 :Float64;
crc @23 :Float64;
omega @24 :Float64;
omegaDot @25 :Float64;
iDot @26 :Float64;
codesL2 @27 :Float64;
gpsWeek @28 :Float64;
l2 @29 :Float64;
svAcc @30 :Float64;
svHealth @31 :Float64;
tgd @32 :Float64;
iodc @33 :Float64;
transmissionTime @34 :Float64;
fitInterval @35 :Float64;
}
}
struct Event {
# in nanoseconds?
logMonoTime @0 :UInt64;
union {
@@ -268,5 +1066,19 @@ struct Event {
logMessage @18 :Text;
liveCalibration @19 :LiveCalibrationData;
androidLogEntry @20 :AndroidLogEntry;
gpsLocation @21 :GpsLocationData;
carState @22 :Car.CarState;
carControl @23 :Car.CarControl;
plan @24 :Plan;
liveLocation @25 :LiveLocationData;
ethernetData @26 :List(EthernetPacket);
navUpdate @27 :NavUpdate;
cellInfo @28 :List(CellInfo);
wifiScan @29 :List(WifiScan);
androidGnss @30 :AndroidGnss;
qcomGnss @31 :QcomGnss;
lidarPts @32 :LidarPts;
procLog @33 :ProcLog;
ubloxGnss @34 :UbloxGnss;
}
}

View File

@@ -1,8 +1,15 @@
import requests
def api_get(endpoint, method='GET', timeout=None, **params):
from selfdrive.version import version
def api_get(endpoint, method='GET', timeout=None, access_token=None, **params):
backend = "https://api.commadotai.com/"
params['_version'] = "OPENPILOTv0.0"
headers = {}
if access_token is not None:
headers['Authorization'] = "JWT "+access_token
headers['User-Agent'] = "openpilot-" + version
return requests.request(method, backend+endpoint, timeout=timeout, headers = headers, params=params)
return requests.request(method, backend+endpoint, timeout=timeout, params=params)

View File

@@ -5,6 +5,10 @@ import sys
if os.getenv("NOLOG"):
def capture_exception(*exc_info):
pass
def bind_user(**kwargs):
pass
def bind_extra(**kwargs):
pass
def install():
pass
else:
@@ -16,6 +20,12 @@ else:
capture_exception = client.captureException
def bind_user(**kwargs):
client.user_context(kwargs)
def bind_extra(**kwargs):
client.extra_context(kwargs)
def install():
# installs a sys.excepthook
__excepthook__ = sys.excepthook

View File

@@ -1,6 +1,8 @@
import re
from collections import namedtuple
import os
import struct
import bitstring
from collections import namedtuple
def int_or_float(s):
# return number, trying to maintain int format
@@ -15,7 +17,9 @@ DBCSignal = namedtuple(
class dbc(object):
def __init__(self, fn):
self.txt = open(fn).read().split("\n")
self.name, _ = os.path.splitext(os.path.basename(fn))
with open(fn) as f:
self.txt = f.read().split("\n")
self._warned_addresses = set()
# regexps from https://github.com/ebroecker/canmatrix/blob/master/canmatrix/importdbc.py
@@ -30,10 +34,8 @@ class dbc(object):
# signals is a list of DBCSignal in order of increasing start_bit.
self.msgs = {}
self.bits = []
for i in range(0, 64, 8):
for j in range(7, -1, -1):
self.bits.append(i+j)
# lookup to bit reverse each byte
self.bits_index = [(i & ~0b111) + ((-i-1) & 0b111) for i in xrange(64)]
for l in self.txt:
l = l.strip()
@@ -100,7 +102,7 @@ class dbc(object):
if s.is_little_endian:
ss = s.start_bit
else:
ss = self.bits.index(s.start_bit)
ss = self.bits_index[s.start_bit]
if s.is_signed:
@@ -132,6 +134,7 @@ class dbc(object):
Returns (None, None) if the message could not be decoded.
"""
if arr is None:
out = {}
else:
@@ -148,8 +151,10 @@ class dbc(object):
if debug:
print name
blen = (len(x[2])/2)*8
x2_int = int(x[2], 16)
blen = 8*len(x[2])
st = x[2].rjust(8, '\x00')
le, be = None, None
for s in msg[1]:
if arr is not None and s[0] not in arr:
@@ -158,11 +163,18 @@ class dbc(object):
# big or little endian?
# see http://vi-firmware.openxcplatform.com/en/master/config/bit-numbering.html
if s[3] is False:
ss = self.bits.index(s[1])
ss = self.bits_index[s[1]]
if be is None:
be = struct.unpack(">Q", st)[0]
x2_int = be
data_bit_pos = (blen - (ss + s[2]))
else:
if le is None:
le = struct.unpack("<Q", st)[0]
x2_int = le
ss = s[1]
data_bit_pos = ss
data_bit_pos = (blen - (ss + s[2]))
if data_bit_pos < 0:
continue
ival = (x2_int >> data_bit_pos) & ((1 << (s[2])) - 1)
@@ -171,12 +183,13 @@ class dbc(object):
ival -= (1<<s[2])
# control the offset
ival = (ival + s[6])*s[5]
if debug:
print "%40s %2d %2d %7.2f %s" % (s[0], s[1], s[2], ival, s[-1])
ival = (ival * s[5]) + s[6]
#if debug:
# print "%40s %2d %2d %7.2f %s" % (s[0], s[1], s[2], ival, s[-1])
if arr is None:
out[s[0]] = ival
else:
out[arr.index(s[0])] = ival
return name, out

View File

@@ -1,17 +0,0 @@
"""Classes for filtering discrete time signals."""
import numpy as np
class FirstOrderLowpassFilter(object):
def __init__(self, fc, dt, x1=0):
self.kf = 2 * np.pi * fc * dt / (1 + 2 * np.pi * fc * dt)
self.x1 = x1
def __call__(self, x):
self.x1 = (1 - self.kf) * self.x1 + self.kf * x
# If previous or current is NaN, reset filter.
if np.isnan(self.x1):
self.x1 = x
return self.x1

82
common/fingerprints.py Normal file
View File

@@ -0,0 +1,82 @@
import os
_FINGERPRINTS = {
"ACURA ILX 2016 ACURAWATCH PLUS": {
1024L: 5, 513L: 5, 1027L: 5, 1029L: 8, 929L: 4, 1057L: 5, 777L: 8, 1034L: 5, 1036L: 8, 398L: 3, 399L: 7, 145L: 8, 660L: 8, 985L: 3, 923L: 2, 542L: 7, 773L: 7, 800L: 8, 432L: 7, 419L: 8, 420L: 8, 1030L: 5, 422L: 8, 808L: 8, 428L: 8, 304L: 8, 819L: 7, 821L: 5, 57L: 3, 316L: 8, 545L: 4, 464L: 8, 1108L: 8, 597L: 8, 342L: 6, 983L: 8, 344L: 8, 804L: 8, 1039L: 8, 476L: 4, 892L: 8, 490L: 8, 1064L: 7, 882L: 2, 884L: 7, 887L: 8, 888L: 8, 380L: 8, 1365L: 5,
# sent messages
0xe4: 5, 0x1fa: 8, 0x200: 3, 0x30c: 8, 0x33d: 5,
},
"HONDA CIVIC 2016 TOURING": {
1024L: 5, 513L: 5, 1027L: 5, 1029L: 8, 777L: 8, 1036L: 8, 1039L: 8, 1424L: 5, 401L: 8, 148L: 8, 662L: 4, 985L: 3, 795L: 8, 773L: 7, 800L: 8, 545L: 6, 420L: 8, 806L: 8, 808L: 8, 1322L: 5, 427L: 3, 428L: 8, 304L: 8, 432L: 7, 57L: 3, 450L: 8, 929L: 8, 330L: 8, 1302L: 8, 464L: 8, 1361L: 5, 1108L: 8, 597L: 8, 470L: 2, 344L: 8, 804L: 8, 399L: 7, 476L: 7, 1633L: 8, 487L: 4, 892L: 8, 490L: 8, 493L: 5, 884L: 8, 891L: 8, 380L: 8, 1365L: 5,
# sent messages
0xe4: 5, 0x1fa: 8, 0x200: 3, 0x30c: 8, 0x33d: 5, 0x35e: 8, 0x39f: 8,
},
"HONDA ACCORD 2016 TOURING": {
1024L: 5, 929L: 8, 1027L: 5, 773L: 7, 1601L: 8, 777L: 8, 1036L: 8, 398L: 3, 1039L: 8, 401L: 8, 145L: 8, 1424L: 5, 660L: 8, 661L: 4, 918L: 7, 985L: 3, 923L: 2, 542L: 7, 927L: 8, 800L: 8, 545L: 4, 420L: 8, 422L: 8, 808L: 8, 426L: 8, 1029L: 8, 432L: 7, 57L: 3, 316L: 8, 829L: 5, 1600L: 5, 1089L: 8, 1057L: 5, 780L: 8, 1088L: 8, 464L: 8, 1108L: 8, 597L: 8, 342L: 6, 983L: 8, 344L: 8, 804L: 8, 476L: 4, 1296L: 3, 891L: 8, 1125L: 8, 487L: 4, 892L: 8, 490L: 8, 871L: 8, 1064L: 7, 882L: 2, 884L: 8, 506L: 8, 507L: 1, 380L: 8, 1365L: 5
},
"HONDA CR-V 2016 TOURING": {
57L: 3, 145L: 8, 316L: 8, 340L: 8, 342L: 6, 344L: 8, 380L: 8, 398L: 3, 399L: 6, 401L: 8, 420L: 8, 422L: 8, 426L: 8, 432L: 7, 464L: 8, 474L: 5, 476L: 4, 487L: 4, 490L: 8, 493L: 3, 507L: 1, 542L: 7, 545L: 4, 597L: 8, 660L: 8, 661L: 4, 773L: 7, 777L: 8, 800L: 8, 804L: 8, 808L: 8, 882L: 2, 884L: 7, 888L: 8, 891L: 8, 892L: 8, 923L: 2, 929L: 8, 983L: 8, 985L: 3, 1024L: 5, 1027L: 5, 1029L: 8, 1033L: 5, 1036L: 8, 1039L: 8, 1057L: 5, 1064L: 7, 1108L: 8, 1125L: 8, 1296L: 8, 1365L: 5, 1424L: 5, 1600L: 5, 1601L: 8,
# sent messages
0x194: 4, 0x1fa: 8, 0x30c: 8, 0x33d: 5,
}
}
def eliminate_incompatible_cars(msg, candidate_cars):
"""Removes cars that could not have sent msg.
Inputs:
msg: A cereal/log CanData message from the car.
candidate_cars: A list of cars to consider.
Returns:
A list containing the subset of candidate_cars that could have sent msg.
"""
compatible_cars = []
for car_name in candidate_cars:
adr = msg.address
if msg.src != 0 or (adr in _FINGERPRINTS[car_name] and
_FINGERPRINTS[car_name][adr] == len(msg.dat)):
compatible_cars.append(car_name)
else:
pass
#isin = adr in _FINGERPRINTS[car_name]
#print "eliminate", car_name, hex(adr), isin, len(msg.dat), msg.dat.encode("hex")
return compatible_cars
def all_known_cars():
"""Returns a list of all known car strings."""
return _FINGERPRINTS.keys()
# **** for use live only ****
def fingerprint(logcan):
import selfdrive.messaging as messaging
from cereal import car
from common.realtime import sec_since_boot
if os.getenv("SIMULATOR") is not None or logcan is None:
return ("simulator", None)
elif os.getenv("SIMULATOR2") is not None:
return ("simulator2", None)
print "waiting for fingerprint..."
candidate_cars = all_known_cars()
finger = {}
st = None
while 1:
for a in messaging.drain_sock(logcan, wait_for_one=True):
if st is None:
st = sec_since_boot()
for can in a.can:
if can.src == 0:
finger[can.address] = len(can.dat)
candidate_cars = eliminate_incompatible_cars(can, candidate_cars)
# if we only have one car choice and it's been 100ms since we got our first message, exit
if len(candidate_cars) == 1 and st is not None and (sec_since_boot()-st) > 0.1:
break
elif len(candidate_cars) == 0:
print map(hex, finger.keys())
raise Exception("car doesn't match any fingerprints")
print "fingerprinted", candidate_cars[0]
return (candidate_cars[0], finger)

View File

@@ -1,7 +1,6 @@
import abc
import numpy as np
import numpy.matlib
# The EKF class contains the framework for an Extended Kalman Filter, but must be subclassed to use.
# A subclass must implement:
# 1) calc_transfer_fun(); see bottom of file for more info.
@@ -68,55 +67,6 @@ class SimpleSensor:
self.covar = covar
return SensorReading(data, self.covar, self.obs_model)
class GPS:
earth_r = 6371e3 # m, average earth radius
def __init__(self, xy_idx=(0, 1), dims=2, var=1e4):
self.obs_model = np.matlib.zeros((2, dims))
self.obs_model[:, tuple(xy_idx)] = np.matlib.identity(2)
self.covar = np.matlib.identity(2) * var
# [lat, lon] in decimal degrees
def init_pos(self, latlon):
self.init_lat, self.init_lon = np.radians(np.asarray(latlon[:2]))
# Compute straight-line distance, in meters, between two lat/long coordinates
# Input in radians
def haversine(self, lat1, lon1, lat2, lon2):
lat_diff = lat2 - lat1
lon_diff = lon2 - lon1
d = np.sin(lat_diff * 0.5)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(
lon_diff * 0.5)**2
h = 2 * GPS.earth_r * np.arcsin(np.sqrt(d))
return h
# Convert decimal degrees into meters
def convert_deg2m(self, lat, lon):
lat, lon = np.radians([lat, lon])
xs = (lon - self.init_lon) * np.cos(self.init_lat) * GPS.earth_r
ys = (lat - self.init_lat) * GPS.earth_r
return xs, ys
# Convert meters into decimal degrees
def convert_m2deg(self, xs, ys):
lat = ys / GPS.earth_r + self.init_lat
lon = xs / (GPS.earth_r * np.cos(self.init_lat)) + self.init_lon
return np.degrees(lat), np.degrees(lon)
# latlon is [lat, long,] as decimal degrees
# accuracy is as given by Android location service: radius of 68% confidence
def read(self, latlon, accuracy=None):
x_dist, y_dist = self.convert_deg2m(latlon[0], latlon[1])
if not accuracy:
covar = self.covar
else:
covar = np.matlib.identity(2) * accuracy**2
return SensorReading(
np.asmatrix([x_dist, y_dist]).T, covar, self.obs_model)
class EKF:
__metaclass__ = abc.ABCMeta
@@ -224,7 +174,7 @@ class EKF:
#! Clip covariance to avoid explosions
self.covar = np.clip(self.covar,-1e10,1e10)
@abc.abstractmethod
def calc_transfer_fun(self, dt):
"""Return a tuple with the transfer function and transfer function jacobian

View File

@@ -8,6 +8,18 @@ from threading import local
from collections import OrderedDict
from contextlib import contextmanager
def json_handler(obj):
# if isinstance(obj, (datetime.date, datetime.time)):
# return obj.isoformat()
return repr(obj)
def json_robust_dumps(obj):
return json.dumps(obj, default=json_handler)
class NiceOrderedDict(OrderedDict):
def __str__(self):
return '{'+', '.join("%r: %r" % p for p in self.iteritems())+'}'
class SwagFormatter(logging.Formatter):
def __init__(self, swaglogger):
logging.Formatter.__init__(self, None, '%a %b %d %H:%M:%S %Z %Y')
@@ -15,13 +27,8 @@ class SwagFormatter(logging.Formatter):
self.swaglogger = swaglogger
self.host = socket.gethostname()
def json_handler(self, obj):
# if isinstance(obj, (datetime.date, datetime.time)):
# return obj.isoformat()
return repr(obj)
def format(self, record):
record_dict = OrderedDict()
def format_dict(self, record):
record_dict = NiceOrderedDict()
if isinstance(record.msg, dict):
record_dict['msg'] = record.msg
@@ -50,9 +57,10 @@ class SwagFormatter(logging.Formatter):
record_dict['threadName'] = record.threadName
record_dict['created'] = record.created
# asctime = self.formatTime(record, self.datefmt)
return record_dict
return json.dumps(record_dict, default=self.json_handler)
def format(self, record):
return json_robust_dumps(self.format_dict(record))
_tmpfunc = lambda: 0
_srcfile = os.path.normcase(_tmpfunc.__code__.co_filename)
@@ -115,7 +123,7 @@ class SwagLogger(logging.Logger):
self.global_ctx.update(kwargs)
def event(self, event_name, *args, **kwargs):
evt = OrderedDict()
evt = NiceOrderedDict()
evt['event'] = event_name
if args:
evt['args'] = args

View File

@@ -1,2 +1,25 @@
def clip(x, lo, hi):
return max(lo, min(hi, x))
def interp(x, xp, fp):
N = len(xp)
if not hasattr(x, '__iter__'):
hi = 0
while hi < N and x > xp[hi]:
hi += 1
low = hi - 1
return fp[-1] if hi == N and x > xp[low] else (
fp[0] if hi == 0 else
(x - xp[low]) * (fp[hi] - fp[low]) / (xp[hi] - xp[low]) + fp[low])
result = []
for v in x:
hi = 0
while hi < N and v > xp[hi]:
hi += 1
low = hi - 1
result.append(fp[-1] if hi == N and v > xp[low] else (fp[
0] if hi == 0 else (v - xp[low]) * (fp[hi] - fp[low]) / (xp[hi] - xp[low]
) + fp[low]))
return result

289
common/params.py Executable file
View File

@@ -0,0 +1,289 @@
#!/usr/bin/env python
"""ROS has a parameter server, we have files.
The parameter store is a persistent key value store, implemented as a directory with a writer lock.
On Android, we store params under params_dir = /data/params. The writer lock is a file
"<params_dir>/.lock" taken using flock(), and data is stored in a directory symlinked to by
"<params_dir>/d".
Each key, value pair is stored as a file with named <key> with contents <value>, located in
<params_dir>/d/<key>
Readers of a single key can just open("<params_dir>/d/<key>") and read the file contents.
Readers who want a consistent snapshot of multiple keys should take the lock.
Writers should take the lock before modifying anything. Writers should also leave the DB in a
consistent state after a crash. The implementation below does this by copying all params to a temp
directory <params_dir>/<tmp>, then atomically symlinking <params_dir>/<d> to <params_dir>/<tmp>
before deleting the old <params_dir>/<d> directory.
Writers that only modify a single key can simply take the lock, then swap the corresponding value
file in place without messing with <params_dir>/d.
"""
import time
import os
import errno
import sys
import shutil
import fcntl
import tempfile
from enum import Enum
def mkdirs_exists_ok(path):
try:
os.makedirs(path)
except OSError:
if not os.path.isdir(path):
raise
class TxType(Enum):
PERSISTANT = 1
CLEAR_ON_MANAGER_START = 2
CLEAR_ON_CAR_START = 3
class UnknownKeyName(Exception):
pass
keys = {
# written: manager
# read: loggerd, uploaderd, baseui
"DongleId": TxType.PERSISTANT,
"AccessToken": TxType.PERSISTANT,
"Version": TxType.PERSISTANT,
"GitCommit": TxType.PERSISTANT,
"GitBranch": TxType.PERSISTANT,
# written: baseui
# read: ui, controls
"IsMetric": TxType.PERSISTANT,
"IsRearViewMirror": TxType.PERSISTANT,
# written: visiond
# read: visiond
"CalibrationParams": TxType.PERSISTANT,
# written: visiond
# read: visiond, ui
"CloudCalibration": TxType.PERSISTANT,
# written: controlsd
# read: radard
"CarParams": TxType.CLEAR_ON_CAR_START}
class FileLock(object):
def __init__(self, path, create):
self._path = path
self._create = create
self._fd = None
def acquire(self):
self._fd = os.open(self._path, os.O_CREAT if self._create else 0)
fcntl.flock(self._fd, fcntl.LOCK_EX)
def release(self):
if self._fd is not None:
os.close(self._fd)
self._fd = None
class DBAccessor(object):
def __init__(self, path):
self._path = path
self._vals = None
def keys(self):
self._check_entered()
return self._vals.keys()
def get(self, key):
self._check_entered()
try:
return self._vals[key]
except KeyError:
return None
def _get_lock(self, create):
lock = FileLock(os.path.join(self._path, ".lock"), create)
lock.acquire()
return lock
def _read_values_locked(self):
"""Callers should hold a lock while calling this method."""
vals = {}
try:
data_path = self._data_path()
keys = os.listdir(data_path)
for key in keys:
with open(os.path.join(data_path, key), "rb") as f:
vals[key] = f.read()
except (OSError, IOError) as e:
# Either the DB hasn't been created yet, or somebody wrote a bug and left the DB in an
# inconsistent state. Either way, return empty.
if e.errno == errno.ENOENT:
return {}
return vals
def _data_path(self):
return os.path.join(self._path, "d")
def _check_entered(self):
if self._vals is None:
raise Exception("Must call __enter__ before using DB")
class DBReader(DBAccessor):
def __enter__(self):
try:
lock = self._get_lock(False)
except OSError as e:
# Do not create lock if it does not exist.
if e.errno == errno.ENOENT:
self._vals = {}
return self
try:
# Read everything.
self._vals = self._read_values_locked()
return self
finally:
lock.release()
def __exit__(self, type, value, traceback): pass
class DBWriter(DBAccessor):
def __init__(self, path):
super(DBWriter, self).__init__(path)
self._lock = None
self._prev_umask = None
def put(self, key, value):
self._vals[key] = value
def delete(self, key):
self._vals.pop(key, None)
def __enter__(self):
mkdirs_exists_ok(self._path)
# Make sure we can write and that permissions are correct.
self._prev_umask = os.umask(0)
try:
os.chmod(self._path, 0o777)
self._lock = self._get_lock(True)
self._vals = self._read_values_locked()
except:
os.umask(self._prev_umask)
self._prev_umask = None
raise
return self
def __exit__(self, type, value, traceback):
self._check_entered()
try:
old_data_path = None
new_data_path = None
tempdir_path = tempfile.mkdtemp(prefix=".tmp", dir=self._path)
try:
# Write back all keys.
os.chmod(tempdir_path, 0o777)
for k, v in self._vals.items():
with open(os.path.join(tempdir_path, k), "wb") as f:
f.write(v)
data_path = self._data_path()
try:
old_data_path = os.path.join(self._path, os.readlink(data_path))
except (OSError, IOError) as e:
# NOTE(mgraczyk): If other DB implementations have bugs, this could cause
# copies to be left behind, but we still want to overwrite.
pass
new_data_path = "{}.link".format(tempdir_path)
os.symlink(os.path.basename(tempdir_path), new_data_path)
os.rename(new_data_path, data_path)
# TODO(mgraczyk): raise useful error when values are bad.
except:
shutil.rmtree(tempdir_path)
if new_data_path is not None:
os.remove(new_data_path)
raise
# Keep holding the lock while we clean up the old data.
if old_data_path is not None:
shutil.rmtree(old_data_path)
finally:
os.umask(self._prev_umask)
self._prev_umask = None
# Always release the lock.
self._lock.release()
self._lock = None
class JSDB(object):
def __init__(self, fn):
self._fn = fn
def begin(self, write=False):
if write:
return DBWriter(self._fn)
else:
return DBReader(self._fn)
class Params(object):
def __init__(self, db='/data/params'):
self.env = JSDB(db)
def _clear_keys_with_type(self, tx_type):
with self.env.begin(write=True) as txn:
for key in keys:
if keys[key] == tx_type:
txn.delete(key)
def manager_start(self):
self._clear_keys_with_type(TxType.CLEAR_ON_MANAGER_START)
def car_start(self):
self._clear_keys_with_type(TxType.CLEAR_ON_CAR_START)
def get(self, key, block=False):
if key not in keys:
raise UnknownKeyName(key)
while 1:
with self.env.begin() as txn:
ret = txn.get(key)
if not block or ret is not None:
break
# is polling really the best we can do?
time.sleep(0.05)
return ret
def put(self, key, dat):
if key not in keys:
raise UnknownKeyName(key)
with self.env.begin(write=True) as txn:
txn.put(key, dat)
print "set", key
if __name__ == "__main__":
params = Params()
if len(sys.argv) > 2:
params.put(sys.argv[1], sys.argv[2])
else:
for k in keys:
pp = params.get(k)
if pp is None:
print k, "is None"
elif all(ord(c) < 128 and ord(c) >= 32 for c in pp):
print k, pp
else:
print k, pp.encode("hex")
# Test multiprocess:
# seq 0 100000 | xargs -P20 -I{} python common/params.py DongleId {} && sleep 0.05
# while python common/params.py DongleId; do sleep 0.05; done

26
common/profiler.py Normal file
View File

@@ -0,0 +1,26 @@
from common.realtime import sec_since_boot
class Profiler(object):
def __init__(self, enabled=False):
self.enabled = enabled
self.cp = []
self.start_time = sec_since_boot()
self.last_time = self.start_time
def checkpoint(self, name):
if not self.enabled:
return
tt = sec_since_boot()
self.cp.append((name, tt - self.last_time))
self.last_time = tt
def display(self):
if not self.enabled:
return
print "******* Profiling *******"
tot = 0.0
for n, ms in self.cp:
print "%30s: %7.2f" % (n, ms*1000.0)
tot += ms
print " TOTAL: %7.2f" % (tot*1000.0)

View File

@@ -1,42 +1,52 @@
"""Utilities for reading real time clocks and keeping soft real time constraints."""
import os
import time
import ctypes
import platform
import threading
import subprocess
import multiprocessing
import os
CLOCK_MONOTONIC_RAW = 4 # see <linux/time.h>
from cffi import FFI
ffi = FFI()
ffi.cdef("""
typedef int clockid_t;
struct timespec {
long tv_sec; /* Seconds. */
long tv_nsec; /* Nanoseconds. */
};
int clock_gettime (clockid_t clk_id, struct timespec *tp);
long syscall(long number, ...);
"""
)
libc = ffi.dlopen(None)
# see <linux/time.h>
CLOCK_MONOTONIC_RAW = 4
CLOCK_BOOTTIME = 7
class timespec(ctypes.Structure):
_fields_ = [
('tv_sec', ctypes.c_long),
('tv_nsec', ctypes.c_long),
]
if platform.system() != 'Darwin' and hasattr(libc, 'clock_gettime'):
c_clock_gettime = libc.clock_gettime
tlocal = threading.local()
def clock_gettime(clk_id):
if not hasattr(tlocal, 'ts'):
tlocal.ts = ffi.new('struct timespec *')
try:
libc = ctypes.CDLL('libc.so', use_errno=True)
except OSError:
try:
libc = ctypes.CDLL('libc.so.6', use_errno=True)
except OSError:
libc = None
ts = tlocal.ts
if libc is not None:
libc.clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
def clock_gettime(clk_id):
if platform.system() == "darwin":
# TODO: fix this
r = c_clock_gettime(clk_id, ts)
if r != 0:
raise OSError("clock_gettime")
return ts.tv_sec + ts.tv_nsec * 1e-9
else:
# hack. only for OS X < 10.12
def clock_gettime(clk_id):
return time.time()
else:
t = timespec()
if libc.clock_gettime(clk_id, ctypes.pointer(t)) != 0:
errno_ = ctypes.get_errno()
raise OSError(errno_, os.strerror(errno_))
return t.tv_sec + t.tv_nsec * 1e-9
def monotonic_time():
return clock_gettime(CLOCK_MONOTONIC_RAW)
@@ -47,7 +57,7 @@ def sec_since_boot():
def set_realtime_priority(level):
if os.getuid() != 0:
print "not setting priority, not root"
print("not setting priority, not root")
return
if platform.machine() == "x86_64":
NR_gettid = 186
@@ -57,7 +67,7 @@ def set_realtime_priority(level):
raise NotImplementedError
tid = libc.syscall(NR_gettid)
subprocess.check_call(['chrt', '-f', '-p', str(level), str(tid)])
return subprocess.call(['chrt', '-f', '-p', str(level), str(tid)])
class Ratekeeper(object):
@@ -80,15 +90,22 @@ class Ratekeeper(object):
# Maintain loop rate by calling this at the end of each loop
def keep_time(self):
self.monitor_time()
lagged = self.monitor_time()
if self._remaining > 0:
time.sleep(self._remaining)
return lagged
# this only monitor the cumulative lag, but does not enforce a rate
def monitor_time(self):
lagged = False
remaining = self._next_frame_time - sec_since_boot()
self._next_frame_time += self._interval
if remaining < -self._print_delay_threshold:
print self._process_name, "lagging by", round(-remaining * 1000, 2), "ms"
print("%s lagging by %.2f ms" % (self._process_name, -remaining * 1000))
lagged = True
self._frame += 1
self._remaining = remaining
return lagged
if __name__ == "__main__":
print sec_since_boot()

View File

@@ -1,82 +0,0 @@
# TODO: these port numbers are hardcoded in c, fix this
# LogRotate: 8001 is a PUSH PULL socket between loggerd and visiond
class Service(object):
def __init__(self, port, should_log):
self.port = port
self.should_log = should_log
# all ZMQ pub sub
service_list = {
# frame syncing packet
"frame": Service(8002, True),
# accel, gyro, and compass
"sensorEvents": Service(8003, True),
# GPS data, also global timestamp
"gpsNMEA": Service(8004, True),
# CPU+MEM+GPU+BAT temps
"thermal": Service(8005, True),
# List(CanData), list of can messages
"can": Service(8006, True),
"live100": Service(8007, True),
# random events we want to log
#"liveEvent": Service(8008, True),
"model": Service(8009, True),
"features": Service(8010, True),
"health": Service(8011, True),
"live20": Service(8012, True),
#"liveUI": Service(8014, True),
"encodeIdx": Service(8015, True),
"liveTracks": Service(8016, True),
"sendcan": Service(8017, True),
"logMessage": Service(8018, True),
"liveCalibration": Service(8019, True),
"androidLog": Service(8020, True),
}
# manager -- base process to manage starting and stopping of all others
# subscribes: health
# publishes: thermal
# boardd -- communicates with the car
# subscribes: sendcan
# publishes: can, health
# visiond -- talks to the cameras, runs the model, saves the videos
# subscribes: liveCalibration, sensorEvents
# publishes: frame, encodeIdx, model, features
# controlsd -- actually drives the car
# subscribes: can, thermal, model, live20
# publishes: sendcan, live100
# radard -- processes the radar data
# subscribes: can, live100, model
# publishes: live20, liveTracks
# sensord -- publishes the IMU and GPS
# publishes: sensorEvents, gpsNMEA
# calibrationd -- places the camera box
# subscribes: features, live100
# publishes: liveCalibration
# **** LOGGING SERVICE ****
# loggerd
# subscribes: EVERYTHING
# **** NON VITAL SERVICES ****
# ui
# subscribes: live100, live20, liveCalibration, model, (raw frames)
# uploader
# communicates through file system with loggerd
# logmessaged -- central logging service, can log to cloud
# publishes: logMessage
# logcatd -- fetches logcat info from android
# publishes: androidLog

9
common/testing.py Normal file
View File

@@ -0,0 +1,9 @@
import os
from nose.tools import nottest
def phone_only(x):
if os.path.isfile("/init.qcom.rc"):
return x
else:
return nottest(x)

View File

@@ -1,2 +0,0 @@
import os
DBC_PATH = os.path.dirname(os.path.abspath(__file__))

View File

@@ -1,295 +0,0 @@
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BO_ 0x039 XXX: 3 XXX
BO_ 0x091 XXX: 8 XXX
SG_ LAT_ACCEL : 0|10@1+ (0.02,-512) [-20|20] "m/s2" Vector__XXX
BO_ 0x0E4 STEERING_CONTROL: 5 ADAS
SG_ STEER_TORQUE : 0|16@1- (1,0) [-3840|3840] "" Vector__XXX
SG_ STEER_TORQUE_REQUEST : 16|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SET_ME_X00 : 17|7@1+ (1,0) [0|127] "" Vector__XXX
SG_ SET_ME_X00 : 24|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ COUNTER : 34|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 36|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x130 GAS_PEDAL2: 8 PCM
SG_ ENGINE_TORQUE_ESTIMATE : 0|16@1- (1,0) [-1000|1000] "Nm" Vector__XXX
SG_ ENGINE_TORQUE_REQUEST : 16|16@1- (1,0) [-1000|1000] "Nm" Vector__XXX
SG_ CAR_GAS : 32|8@1+ (1,0) [0|255] "" Vector__XXX
BO_ 0x13C GAS_PEDAL: 8 PCM
SG_ CAR_GAS : 32|8@1+ (1,0) [0|255] "" Vector__XXX
BO_ 0x156 STEERING_SENSORS: 6 EPS
SG_ STEER_ANGLE : 0|16@1- (-0.1,0) [-500|500] "deg" Vector__XXX
SG_ STEER_ANGLE_RATE : 16|16@1- (1,0) [-3000|3000] "deg/s" Vector__XXX
SG_ COUNTER : 42|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 44|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x158 POWERTRAIN_DATA: 8 PCM
SG_ XMISSION_SPEED : 0|16@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ ENGINE_RPM : 16|16@1+ (1,0) [0|15000] "rpm" Vector__XXX
SG_ XMISSION_SPEED2 : 32|16@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x17C POWERTRAIN_DATA2: 8 PCM
SG_ PEDAL_GAS : 0|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ ENGINE_RPM : 16|16@1+ (1,0) [0|15000] "rpm" Vector__XXX
SG_ GAS_PRESSED : 32|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ ACC_STATUS : 33|1@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ BOH_17C : 34|5@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ BRAKE_LIGHTS_ON : 39|1@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ BOH2_17C : 40|10@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ BRAKE_PRESSED : 50|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BOH3_17C : 51|5@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x18E XXX: 3 XXX
BO_ 0x18F STEER_STATUS: 7 EPS
SG_ STEER_TORQUE_SENSOR : 0|16@1- (1,0) [-31000|31000] "tbd" Vector__XXX
SG_ STEER_TORQUE_MOTOR : 16|16@1- (1,0) [-31000|31000] "tbd" Vector__XXX
SG_ STEER_STATUS : 32|4@1+ (1,0) [0|15] "" Vector__XXX
SG_ STEER_CONTROL_ACTIVE : 36|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 50|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 52|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1A3 GEARBOX: 8 PCM
SG_ GEAR : 0|8@1+ (1,0) [0|256] "" Vector__XXX
SG_ GEAR_SHIFTER : 36|4@1+ (1,0) [0|15] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1A4 VSA_STATUS: 8 VSA
SG_ USER_BRAKE : 0|16@1+ (0.015625,-103) [0|1000] "" Vector__XXX
SG_ ESP_DISABLED : 27|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1A6 SCM_BUTTONS: 8 SCM
SG_ CRUISE_BUTTONS : 0|3@1+ (1,0) [0|7] "" Vector__XXX
SG_ LIGHTS_SETTING : 6|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ MAIN_ON : 40|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_SETTING : 44|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1AC XXX: 8 XXX
BO_ 0x1B0 STANDSTILL: 7 VSA
SG_ WHEELS_MOVING : 11|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BRAKE_ERROR_1 : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BRAKE_ERROR_2 : 14|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 50|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 52|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1D0 WHEEL_SPEEDS: 8 VSA
SG_ WHEEL_SPEED_FL : 0|15@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ WHEEL_SPEED_FR : 15|15@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ WHEEL_SPEED_RL : 30|15@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ WHEEL_SPEED_RR : 45|15@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1DC XXX: 4 XXX
BO_ 0x1EA VEHICLE_DYNAMICS: 8 VSA
SG_ LONG_ACCEL : 16|16@1- (0.0015384,0) [-20|20] "m/s2" Vector__XXX
BO_ 0x1FA BRAKE_COMMAND: 8 ADAS
SG_ COMPUTER_BRAKE : 0|10@1+ (0.003906248,0) [0|1] "" Vector__XXX
SG_ ZEROS_BOH : 10|5@1+ (1,0) [0|1] "" Vector__XXX
SG_ COMPUTER_BRAKE_REQUEST : 15|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_BOH2 : 16|3@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_OVERRIDE : 19|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_BOH3 : 20|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_FAULT_CMD : 21|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_CANCEL_CMD : 22|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COMPUTER_BRAKE_REQUEST_2 : 23|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_BOH4 : 24|8@1+ (1,0) [0|1] "" Vector__XXX
SG_ BRAKE_LIGHTS : 32|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_BOH5 : 33|7@1+ (1,0) [0|1] "" Vector__XXX
SG_ CHIME : 40|3@1+ (1,0) [0|7] "" Vector__XXX
SG_ CRUISE_BOH6 : 43|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ FCW : 44|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CRUISE_BOH7 : 46|10@1+ (1,0) [0|0] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x200 GAS_COMMAND: 3 ADAS
SG_ GAS_COMMAND : 0|16@1+ (0.253984064,-328) [0|1] "" Vector__XXX
SG_ COUNTER : 18|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 20|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x201 GAS_SENSOR: 5 ADAS
SG_ INTERCEPTOR_GAS : 0|16@1+ (0.253984064,-328) [0|1] "" Vector__XXX
SG_ INTERCEPTOR_GAS2 : 16|16@1+ (0.126992032,-656) [0|1] "" Vector__XXX
SG_ COUNTER : 34|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 36|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x21E XXX: 7 XXX
BO_ 0x221 XXX: 4 XXX
BO_ 0x255 ROUGH_WHEEL_SPEED: 8 VSA
SG_ WHEEL_SPEED_FL : 0|8@1+ (1,0) [0|255] "mph" Vector__XXX
SG_ WHEEL_SPEED_FR : 8|8@1+ (1,0) [0|255] "mph" Vector__XXX
SG_ WHEEL_SPEED_RL : 16|8@1+ (1,0) [0|255] "mph" Vector__XXX
SG_ WHEEL_SPEED_RR : 24|8@1+ (1,0) [0|255] "mph" Vector__XXX
SG_ SET_TO_X55 : 32|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ SET_TO_X55 : 40|8@1+ (1,0) [0|255] "" Vector__XXX
BO_ 0x294 SCM_COMMANDS: 8 SCM
SG_ RIGHT_BLINKER : 1|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LEFT_BLINKER : 2|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ WIPERS_SPEED : 3|2@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x305 SEATBELT_STATUS: 7 BDY
SG_ SEATBELT_DRIVER_LAMP : 0|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SEATBELT_DRIVER_LATCHED : 10|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 50|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 52|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x309 XXX: 8 XXX
BO_ 0x30C ACC_HUD: 8 ADAS
SG_ PCM_SPEED : 0|16@1+ (0.002763889,0) [0|100] "m/s" Vector__XXX
SG_ PCM_GAS : 16|7@1+ (1,0) [0|127] "" Vector__XXX
SG_ ZEROS_BOH : 23|1@1+ (1,0) [0|255] "" Vector__XXX
SG_ CRUISE_SPEED : 24|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ DTC_MODE : 32|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BOH : 33|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ ACC_PROBLEM : 34|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ FCM_OFF : 35|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BOH_2 : 36|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ FCM_PROBLEM : 37|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ RADAR_OBSTRUCTED : 38|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ ENABLE_MINI_CAR : 39|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SET_ME_X03 : 40|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ HUD_LEAD : 42|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ BOH_3 : 44|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ BOH_4 : 45|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ BOH_5 : 46|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ CRUISE_CONTROL_LABEL : 47|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ HUD_DISTANCE_3 : 51|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x320 XXX: 8 XXX
BO_ 0x324 CRUISE: 8 PCM
SG_ ENGINE_TEMPERATURE : 0|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ BOH : 8|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ TRIP_FUEL_CONSUMED : 16|16@1+ (1,0) [0|255] "" Vector__XXX
SG_ CRUISE_SPEED_PCM : 32|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ BOH2 : 40|8@1- (1,0) [0|255] "" Vector__XXX
SG_ BOH3 : 48|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x328 XXX: 8 XXX
BO_ 0x333 XXX: 7 XXX
BO_ 0x335 XXX: 5 XXX
BO_ 0x33D LKAS_HUD_2: 5 ADAS
SG_ CAM_TEMP_HIGH : 0|1@1+ (1,0) [0|255] "" Vector__XXX
SG_ BOH : 1|7@1+ (1,0) [0|127] "" Vector__XXX
SG_ DASHED_LANES : 9|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ DTC : 10|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LKAS_PROBLEM : 11|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LKAS_OFF : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SOLID_LANES : 13|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LDW_RIGHT : 14|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ STEERING_REQUIRED : 15|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BOH : 16|2@1+ (1,0) [0|4] "" Vector__XXX
SG_ LDW_PROBLEM : 18|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BEEP : 22|2@1+ (1,0) [0|1] "" Vector__XXX
SG_ LDW_ON : 27|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LDW_OFF : 28|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CLEAN_WINDSHIELD : 29|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SET_ME_X48 : 24|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ COUNTER : 34|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 36|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x372 XXX: 2 XXX
BO_ 0x374 XXX: 7 XXX
BO_ 0x377 XXX: 8 XXX
BO_ 0x378 XXX: 8 XXX
BO_ 0x37C XXX: 8 XXX
BO_ 0x39B XXX: 2 XXX
BO_ 0x3A1 XXX: 4 XXX
BO_ 0x3D7 XXX: 8 XXX
BO_ 0x3D9 XXX: 3 XXX
BO_ 0x400 XXX: 5 XXX
BO_ 0x403 XXX: 5 XXX
BO_ 0x405 DOORS_STATUS: 8 BDY
SG_ DOOR_OPEN_FL : 34|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ DOOR_OPEN_FR : 33|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ DOOR_OPEN_RL : 32|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ DOOR_OPEN_RR : 47|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x406 XXX: 5 VSA
BO_ 0x40A XXX: 5 XXX
BO_ 0x40C XXX: 8 XXX
BO_ 0x40F XXX: 8 XXX
BO_ 0x421 XXX: 5 EPS
BO_ 0x428 XXX: 7 XXX
BO_ 0x454 XXX: 8 XXX
BO_ 0x555 XXX: 5 XXX
BO_ 0x640 XXX: 5 XXX
BO_ 0x641 XXX: 8 XXX
VAL_ 0x1A6 CRUISE_BUTTONS 7 "tbd" 6 "tbd" 5 "tbd" 4 "accel_res" 3 "decel_set" 2 "cancel" 1 "main" 0 "none";
VAL_ 0x1A6 CRUISE_SETTING 3 "distance_adj" 2 "tbd" 1 "lkas_button" 0 "none";
VAL_ 0x30C HUD_LEAD 3 "no_car" 2 "solid_car" 1 "dashed_car" 0 "no_car";
VAL_ 0x1A6 LIGHTS_SETTING 3 "high_beam" 2 "low_beam" 1 "position" 0 "no_lights";
VAL_ 0x18F STEER_STATUS 5 "fault" 4 "no_torque_alert_2" 2 "no_torque_alert_1" 0 "normal";
VAL_ 0x1A3 GEAR_SHIFTER 10 "S" 4 "D" 3 "N" 2 "R" 1 "P";
VAL_ 0x33D BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep";
VAL_ 0x1FA CHIME 4 "double_chime" 3 "single_chime" 2 "continuous_chime" 1 "repeating_chime" 0 "no_chime";
VAL_ 0x1FA FCW 3 "fcw" 2 "fcw" 1 "fcw" 0 "no_fcw";
CM_ SG_ 0x1A3 GEAR "10 = reverse, 11 = transition";
CM_ SG_ 0x324 CRUISE_SPEED_ECHO "255 = no speed";
CM_ SG_ 0x33D CRUISE_SPEED "255 = no speed";
CM_ SG_ 0x1EA LONG_ACCEL "wheel speed derivative, noisy and zero snapping";
CM_ SG_ 0x33D BEEP "beeps are pleasant, chimes are for warnngs etc...";

View File

@@ -1,175 +0,0 @@
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BO_ 0x300 VEHICLE_STATE: 8 ADAS
SG_ SET_ME_XF9 : 0|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ VEHICLE_SPEED : 8|8@1+ (1,0) [0|255] "kph" Vector__XXX
BO_ 0x301 VEHICLE_STATE2: 8 ADAS
SG_ SET_ME_0F18510 : 0|28@1+ (1,0) [0|268435455] "" Vector__XXX
SG_ SET_ME_25A0000 : 28|28@1+ (1,0) [0|268435455] "" Vector__XXX
BO_ 0x400 XXX: 8 RADAR
BO_ 0x410 XXX: 8 RADAR
BO_ 0x411 XXX: 8 RADAR
BO_ 0x412 XXX: 8 RADAR
BO_ 0x413 XXX: 8 RADAR
BO_ 0x414 XXX: 8 RADAR
BO_ 0x415 XXX: 8 RADAR
BO_ 0x416 XXX: 8 RADAR
BO_ 0x417 XXX: 8 RADAR
BO_ 0x420 XXX: 8 RADAR
BO_ 0x421 XXX: 8 RADAR
BO_ 0x422 XXX: 8 RADAR
BO_ 0x423 XXX: 8 RADAR
BO_ 0x424 XXX: 8 RADAR
BO_ 0x430 TRACK_0: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x431 TRACK_1: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x432 TRACK_2: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x433 TRACK_3: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x434 TRACK_4: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x435 TRACK_5: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x436 TRACK_6: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x437 TRACK_7: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x438 TRACK_8: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x439 TRACK_9: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x440 TRACK_10: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x441 TRACK_11: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x442 TRACK_12: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x443 TRACK_13: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x444 TRACK_14: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x445 TRACK_15: 8 RADAR
SG_ LONG_DIST : 0|12@1+ (0.0625,0) [0|255.5] "m" Vector__XXX
SG_ NEW_TRACK : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LAT_DIST : 14|10@1- (0.0625,0) [0|63.5] "m" Vector__XXX
SG_ REL_SPEED : 24|12@1- (0.03125,0) [0|127.5] "m/s" Vector__XXX
BO_ 0x4FF XXX: 8 RADAR
BO_ 0x500 XXX: 8 RADAR
BO_ 0x510 XXX: 8 RADAR
BO_ 0x511 XXX: 8 RADAR

View File

@@ -1,319 +0,0 @@
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BO_ 0x039 XXX: 3 XXX
BO_ 0x94 XXX: 8 XXX
SG_ LAT_ACCEL : 0|10@1+ (0.02,-512) [-20|20] "m/s2" Vector__XXX
SG_ LONG_ACCEL : 31|9@1- (-0.02,0) [-20|20] "m/s2" Vector__XXX
BO_ 0x0E4 STEERING_CONTROL: 5 ADAS
SG_ STEER_TORQUE : 0|16@1- (1,0) [-3840|3840] "" Vector__XXX
SG_ STEER_TORQUE_REQUEST : 16|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SET_ME_X00 : 17|7@1+ (1,0) [0|127] "" Vector__XXX
SG_ SET_ME_X00_2 : 24|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ CHECKSUM : 32|4@1+ (1,0) [0|15] "" Vector__XXX
SG_ COUNTER : 38|2@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x130 GAS_PEDAL2: 8 PCM
SG_ ENGINE_TORQUE_ESTIMATE : 0|16@1- (1,0) [-1000|1000] "Nm" Vector__XXX
SG_ ENGINE_TORQUE_REQUEST : 16|16@1- (1,0) [-1000|1000] "Nm" Vector__XXX
SG_ CAR_GAS : 32|8@1+ (1,0) [0|255] "" Vector__XXX
BO_ 0x14A STEERING_SENSORS: 8 EPS
SG_ STEER_ANGLE : 0|16@1- (-0.1,0) [-500|500] "deg" Vector__XXX
SG_ STEER_ANGLE_RATE : 16|16@1- (-1,0) [-3000|3000] "deg/s" Vector__XXX
SG_ STEER_ANGLE_OFFSET : 32|8@1- (-0.1,0) [-128|127] "deg" Vector__XXX
SG_ STEER_WHEEL_ANGLE : 40|16@1- (-0.1,0) [-500|500] "deg" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x158 POWERTRAIN_DATA: 8 PCM
SG_ XMISSION_SPEED : 0|16@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ ENGINE_RPM : 16|16@1+ (1,0) [0|15000] "rpm" Vector__XXX
SG_ XMISSION_SPEED2 : 32|16@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x17C POWERTRAIN_DATA2: 8 PCM
SG_ PEDAL_GAS : 0|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ ENGINE_RPM : 16|16@1+ (1,0) [0|15000] "rpm" Vector__XXX
SG_ GAS_PRESSED : 32|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ ACC_STATUS : 33|1@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ BOH_17C : 34|5@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ BRAKE_LIGHTS_ON : 39|1@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ BOH2_17C : 40|10@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ BRAKE_PRESSED : 50|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BOH3_17C : 51|5@1+ (1,0) [0|1] "rpm" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x18F STEER_STATUS: 7 EPS
SG_ STEER_TORQUE_SENSOR : 0|16@1- (1,0) [-31000|31000] "tbd" Vector__XXX
SG_ STEER_TORQUE_MOTOR : 16|16@1- (1,0) [-31000|31000] "tbd" Vector__XXX
SG_ STEER_STATUS : 32|4@1+ (1,0) [0|15] "" Vector__XXX
SG_ STEER_CONTROL_ACTIVE : 36|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 50|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 52|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x191 GEARBOX: 8 PCM
SG_ GEAR_SHIFTER : 2|6@1+ (1,0) [0|63] "" Vector__XXX
SG_ GEAR : 36|4@1+ (1,0) [0|15] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1A4 VSA_STATUS: 8 VSA
SG_ USER_BRAKE : 0|16@1+ (0.015625,-103) [0|1000] "" Vector__XXX
SG_ ESP_DISABLED : 27|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1AB XXX: 3 VSA
BO_ 0x1AC XXX: 8 XXX
BO_ 0x1B0 STANDSTILL: 7 VSA
SG_ WHEELS_MOVING : 11|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BRAKE_ERROR_1 : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BRAKE_ERROR_2 : 14|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 50|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 52|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1C2 XXX: 8 EPB
SG_ EPB_ACTIVE : 4|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ EPB_STATE : 26|2@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1D0 WHEEL_SPEEDS: 8 VSA
SG_ WHEEL_SPEED_FL : 0|15@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ WHEEL_SPEED_FR : 15|15@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ WHEEL_SPEED_RL : 30|15@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ WHEEL_SPEED_RR : 45|15@1+ (0.002759506,0) [0|70] "m/s" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x1D6 XXX: 2 VSA
BO_ 0x1DC XXX: 7 XXX
BO_ 0x1E7 XXX: 4 VSA
SG_ BRAKE_PRESSURE1 : 0|10@1+ (0.015625,-103) [0|1000] "" Vector__XXX
SG_ BRAKE_PRESSURE2 : 14|10@1+ (0.015625,-103) [0|1000] "" Vector__XXX
BO_ 0x1EA VEHICLE_DYNAMICS: 8 VSA
SG_ LONG_ACCEL : 16|16@1- (0.0015384,0) [-20|20] "m/s2" Vector__XXX
BO_ 0x1ED XXX: 5 VSA
BO_ 0x1FA BRAKE_COMMAND: 8 ADAS
SG_ COMPUTER_BRAKE : 0|10@1+ (0.003906248,0) [0|1.0] "" Vector__XXX
SG_ ZEROS_BOH : 10|5@1+ (1,0) [0|1] "" Vector__XXX
SG_ COMPUTER_BRAKE_REQUEST : 15|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_BOH2 : 16|3@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_OVERRIDE : 19|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_BOH3 : 20|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_FAULT_CMD : 21|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_CANCEL_CMD : 22|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COMPUTER_BRAKE_REQUEST_2 : 23|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SET_ME_0X80 : 24|8@1+ (1,0) [0|1] "" Vector__XXX
SG_ BRAKE_LIGHTS : 32|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CRUISE_STATES : 33|7@1+ (1,0) [0|1] "" Vector__XXX
SG_ CHIME : 40|3@1+ (1,0) [0|7] "" Vector__XXX
SG_ ZEROS_BOH6 : 43|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ FCW : 44|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ ZEROS_BOH3 : 45|2@1+ (1,0) [0|0] "" Vector__XXX
SG_ FCW2 : 47|1@1+ (1,0) [0|0] "" Vector__XXX
SG_ ZEROS_BOH4 : 48|8@1+ (1,0) [0|0] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x200 GAS_COMMAND: 3 ADAS
SG_ GAS_COMMAND : 0|16@1+ (0.253984064,-328) [0|1] "" Vector__XXX
SG_ COUNTER : 18|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 20|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x201 GAS_SENSOR: 5 ADAS
SG_ INTERCEPTOR_GAS : 0|16@1+ (0.253984064,-328) [0|1] "" Vector__XXX
SG_ INTERCEPTOR_GAS2 : 16|16@1+ (0.126992032,-656) [0|1] "" Vector__XXX
SG_ COUNTER : 34|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 36|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x221 XXX: 6 XXX
BO_ 0x255 ROUGH_WHEEL_SPEED: 8 VSA
SG_ WHEEL_SPEED_FL : 0|8@1+ (1,0) [0|255] "mph" Vector__XXX
SG_ WHEEL_SPEED_FR : 8|8@1+ (1,0) [0|255] "mph" Vector__XXX
SG_ WHEEL_SPEED_RL : 16|8@1+ (1,0) [0|255] "mph" Vector__XXX
SG_ WHEEL_SPEED_RR : 24|8@1+ (1,0) [0|255] "mph" Vector__XXX
SG_ SET_TO_X55 : 32|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ SET_TO_X55 : 40|8@1+ (1,0) [0|255] "" Vector__XXX
BO_ 0x296 CRUISE_BUTTONS: 4 SCM
SG_ CRUISE_BUTTONS : 0|3@1+ (1,0) [0|7] "" Vector__XXX
SG_ CRUISE_SETTING : 4|2@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x305 SEATBELT_STATUS: 7 BDY
SG_ SEATBELT_DRIVER_LAMP : 0|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SEATBELT_DRIVER_LATCHED : 10|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 50|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 52|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x309 XXX: 8 XXX
BO_ 0x30C ACC_HUD: 8 ADAS
SG_ PCM_SPEED : 0|16@1+ (0.002763889,0) [0|100] "m/s" Vector__XXX
SG_ PCM_GAS : 16|7@1+ (1,0) [0|127] "" Vector__XXX
SG_ ZEROS_BOH : 23|1@1+ (1,0) [0|255] "" Vector__XXX
SG_ CRUISE_SPEED : 24|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ DTC_MODE : 32|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BOH : 33|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ ACC_PROBLEM : 34|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ FCM_OFF : 35|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BOH_2 : 36|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ FCM_PROBLEM : 37|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ RADAR_OBSTRUCTED : 38|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ ENABLE_MINI_CAR : 39|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ HUD_DISTANCE : 40|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ HUD_LEAD : 42|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ BOH_3 : 44|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ BOH_4 : 45|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ BOH_5 : 46|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ CRUISE_CONTROL_LABEL : 47|1@1+ (1,0) [0|3] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x31B XXX: 8 XXX
BO_ 0x320 XXX: 8 XXX
BO_ 0x324 CRUISE: 8 PCM
SG_ ENGINE_TEMPERATURE : 0|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ BOH : 8|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ TRIP_FUEL_CONSUMED : 16|16@1+ (1,0) [0|255] "" Vector__XXX
SG_ CRUISE_SPEED_PCM : 32|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ BOH2 : 40|8@1- (1,0) [0|255] "" Vector__XXX
SG_ BOH3 : 48|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x326 SCM_FEEDBACK: 8 SCM
SG_ CMBS_BUTTON : 17|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ MAIN_ON : 27|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ RIGHT_BLINKER : 28|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LEFT_BLINKER : 29|1@1+ (1,0) [0|1] "" Vector__XXX
BO_ 0x328 XXX: 8 XXX
BO_ 0x33D LKAS_HUD_2: 5 ADAS
SG_ CAM_TEMP_HIGH : 0|1@1+ (1,0) [0|255] "" Vector__XXX
SG_ BOH : 1|7@1+ (1,0) [0|127] "" Vector__XXX
SG_ DASHED_LANES : 9|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ DTC : 10|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LKAS_PROBLEM : 11|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LKAS_OFF : 12|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SOLID_LANES : 13|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LDW_RIGHT : 14|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ STEERING_REQUIRED : 15|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BOH : 16|2@1+ (1,0) [0|4] "" Vector__XXX
SG_ LDW_PROBLEM : 18|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ BEEP : 22|2@1+ (1,0) [0|1] "" Vector__XXX
SG_ LDW_ON : 27|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ LDW_OFF : 28|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ CLEAN_WINDSHIELD : 29|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ SET_ME_X48 : 24|8@1+ (1,0) [0|255] "" Vector__XXX
SG_ COUNTER : 34|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 36|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x35E XXX: 8 ADAS
SG_ UI_ALERTS : 0|56@1+ (1,0) [0|127] "" Vector__XXX
BO_ 0x374 XXX: 8 XXX
BO_ 0x37B XXX: 8 XXX
BO_ 0x37C XXX: 8 XXX
BO_ 0x39F XXX: 8 ADAS
SG_ ZEROS_BOH : 0|17@1+ (1,0) [0|127] "" Vector__XXX
SG_ APPLY_BRAKES_FOR_CANC : 16|1@1+ (1,0) [0|15] "" Vector__XXX
SG_ ZEROS_BOH2 : 17|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ RESUME_INSTRUCTION : 18|1@1+ (1,0) [0|15] "" Vector__XXX
SG_ ACC_ALERTS : 19|5@1+ (1,0) [0|15] "" Vector__XXX
SG_ ZEROS_BOH2 : 24|8@1+ (1,0) [0|127] "" Vector__XXX
SG_ LEAD_SPEED : 32|9@1+ (1,0) [0|127] "" Vector__XXX
SG_ LEAD_STATE : 41|3@1+ (1,0) [0|127] "" Vector__XXX
SG_ LEAD_DISTANCE : 44|5@1+ (1,0) [0|31] "" Vector__XXX
SG_ ZEROS_BOH3 : 49|7@1+ (1,0) [0|127] "" Vector__XXX
BO_ 0x3A1 XXX: 8 XXX
BO_ 0x3D9 XXX: 3 XXX
BO_ 0x400 XXX: 5 XXX
BO_ 0x403 XXX: 5 XXX
BO_ 0x405 DOORS_STATUS: 8 BDY
SG_ DOOR_OPEN_FL : 34|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ DOOR_OPEN_FR : 33|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ DOOR_OPEN_RL : 32|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ DOOR_OPEN_RR : 47|1@1+ (1,0) [0|1] "" Vector__XXX
SG_ COUNTER : 58|2@1+ (1,0) [0|3] "" Vector__XXX
SG_ CHECKSUM : 60|4@1+ (1,0) [0|3] "" Vector__XXX
BO_ 0x40C XXX: 8 XXX
BO_ 0x40F XXX: 8 XXX
BO_ 0x454 XXX: 8 XXX
BO_ 0x516 XXX: 8 XXX
BO_ 0x52A XXX: 5 XXX
BO_ 0x551 XXX: 5 XXX
BO_ 0x555 XXX: 5 XXX
BO_ 0x590 XXX: 5 XXX
BO_ 0x640 XXX: 5 XXX
BO_ 0x641 XXX: 8 XXX
BO_ 0x661 XXX: 8 XXX
VAL_ 0x296 CRUISE_BUTTONS 7 "tbd" 6 "tbd" 5 "tbd" 4 "accel_res" 3 "decel_set" 2 "cancel" 1 "main" 0 "none";
VAL_ 0x296 CRUISE_SETTING 3 "distance_adj" 2 "tbd" 1 "lkas_button" 0 "none";
VAL_ 0x33D HUD_LEAD 3 "acc_off" 2 "solid_car" 1 "dashed_car" 0 "no_car";
VAL_ 0x1A6 LIGHTS_SETTING 3 "high_beam" 2 "low_beam" 1 "position" 0 "no_lights";
VAL_ 0x18F STEER_STATUS 5 "fault" 4 "no_torque_alert_2" 2 "no_torque_alert_1" 0 "normal";
VAL_ 0x191 GEAR_SHIFTER 32 "L" 16 "S" 8 "D" 4 "N" 2 "R" 1 "P";
VAL_ 0x33D BEEP 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep";
VAL_ 0x1FA CHIME 4 "double_chime" 3 "single_chime" 2 "continuous_chime" 1 "repeating_chime" 0 "no_chime";
VAL_ 0x1C2 EPB_STATE 3 "engaged" 2 "disengaging" 1 "engaging" 0 "disengaged";
VAL_ 0x326 CMBS_BUTTON 3 "pressed" 0 "released";
VAL_ 0x39F ACC_ALERTS 29 "esp_active_acc_canceled" 10 "b_pedal_applied" 9 "speed_too_low" 8 "speed_too_high" 7 "p_brake_applied" 6 "gear_no_d" 5 "seatbelt" 4 "too_steep_downhill" 3 "too_steep_uphill" 2 "too_close" 1 "no_vehicle_ahead";
VAL_ 0x30C CRUISE_SPEED 255 "no_speed" 252 "stopped";
CM_ SG_ 0x1A3 GEAR "10 = reverse, 11 = transition";
CM_ SG_ 0x324 CRUISE_SPEED_PCM "255 = no speed";
CM_ SG_ 0x30C CRUISE_SPEED "255 = no speed";
CM_ SG_ 0x1EA LONG_ACCEL "wheel speed derivative, noisy and zero snapping";
CM_ SG_ 0x33D BEEP "beeps are pleasant, chimes are for warnngs etc...";

View File

@@ -1,28 +0,0 @@
#!/usr/bin/bash
# enable wifi access point for debugging only!
#service call wifi 37 i32 0 i32 1 # WifiService.setWifiApEnabled(null, true)
# use the openpilot ro key
export GIT_SSH_COMMAND="ssh -i /data/data/com.termux/files/id_rsa_openpilot_ro"
# check out the openpilot repo
# TODO: release branch only
if [ ! -d /data/openpilot ]; then
cd /tmp
git clone git@github.com:commaai/openpilot.git
mv /tmp/openpilot /data/openpilot
fi
# update the openpilot repo
cd /data/openpilot
git pull
# start manager
cd selfdrive
mkdir -p /sdcard/realdata
PYTHONPATH=/data/openpilot ./manager.py
# if broken, keep on screen error
while true; do sleep 1; done

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAy/ZlYE/iHHjhbSvCnBm5Zsq5GPpVugLXFHai/doqyfRxErop
/g1TIRhzK3mkHRYRN7H0L9whogwoIVr5CldoxU49FDnNbVHNimScNrL4LprRWjq6
dRmCVoxMpLHZTyX1jIkcHsMr7klcUnssyeQO2pWvZv0ZC67wM7G20r7+ZLdEa0Ck
MBh8JYhDaZx2xvYtTnt6vKMmFVE5+zW/+wDVma3a4r9pG9s0+r0wCl8CUuJ+yDhR
mzNkPJ5mJCMx99AI6k4Gq9Vsng8/35b6Azh3TucPaXOLK7yPnL3YBKUa0PpR7IRH
+OKkVCH+LL7tcPFSqPPVy/pUTBdEUROjJdSHxwIDAQABAoIBAQCxBgUM56h3T89Q
AoghFg6dkdu/Ox8GmAp231UuAJncuMUfHObvcj8xXVgwZp4zBIEjFte6ZlPmoqh9
8sht2lm7zeEjWdvbQwGjWRlgPEs9n++OYaSNl/tRBOpMk3Ppxydst1/prznE0nVH
vVKtU7w0qXAYchm30zj1lQv5s/12CTGmnpQatbo5X488RfCfv2zFX1h+lEWF8ycL
eZRi8z6l8h2Y+JLyEwPCmR+gR6XtosZ/ECQcTknavqLqdr7NbYYfOo3JfHCUtpJa
8s7m0VFhMuxFFCl1sV0eMzAynJYNVz45DyaKpr2b/2YAGY8fn96FxaWv1xw1xTkK
c5+wStwJAoGBAOjQpLZ1qGa4GwXzeHoDsGFpGgY9ug6af0M23c8O42fJHAwYkk7r
Qeo4SSBddoSfo3jdchFLo59+m3qyTKpjkph7NBBCEwaCvX3heStDIMZEWX0IOV5y
iJD/D6EXSqFmXCUUaudX2OxlaHguA0yOEx9s/5uUJrvaIHbBAOpYyar1AoGBAOBG
MJp+EA3e1Zx/VszD2Tdxn8V0DAwvy9WIEqZuG689S/Sk5GnA4m2L8Txv0xAHFvLv
JpF7Zn9AoFXGpjf9P0FF53cpjEYn9f+uK84j1HOL/6R7Nj9rcS5yL2PCP1ZHymw6
xOXl3oZa1YtYE6jfvXUaOb8Z7y8gaStP763sXmpLAoGBAM1WSBANUcvXES58gIPN
ASHJGwTqKFF8/kV//L4EuZjuDWi1u0UTxX0Yy5ZaGI/8ZKfTWCnc9qFTfzoGTAvz
6nXGJDM6s6EIaqy90qrPd/amje7y8/ZTOhP4ggZojpAvwZGKoocMOey1vCBTJOG+
ZStQbVkAn/EK/5r9uxr12FiJAoGAH9UWlPcLpExamWnhkhLCRAJWoRoFk708+0Pj
EchTGZ5jp4e3++KqwM26Ic/lb0LyWOzk1oVjWPB9UW9urEe/sK4RWnKFPHfzjKTW
Bt5DC1t1n4z1eC7x05vVah1qC/8IljAJPnBQE1XVNX/82l1XcMWWKK+vqUq6YrFn
3ZHNHN0CgYA3uUVWqW37vfJuk0MJBkQSqMo5Y5TPlCt4b1ebkdhlM4v/N+iuiPiC
PBhjP1MLeudkJvzllt4YvNWLerCKpMWuw7Zvy5uzFEsqOrVlzfnyWqqqYbYjHe9f
Ef0/yXKuGJajs54Ts6Xrm0+elVUu//pEuf6NI96Ehctqz8/BqGqAtw==
-----END RSA PRIVATE KEY-----

View File

@@ -1,11 +0,0 @@
#!/bin/bash
set -e
# move files into place
adb push files/id_rsa_openpilot_ro /tmp/id_rsa_openpilot_ro
adb shell mv /tmp/id_rsa_openpilot_ro /data/data/com.termux/files/
# moving continue into place runs the continue script
adb push files/continue.sh /tmp/continue.sh
adb shell mv /tmp/continue.sh /data/data/com.termux/files/

1
opendbc Submodule

Submodule opendbc added at b77861eb00

1
panda Submodule

Submodule panda added at 5409c51041

View File

@@ -0,0 +1,426 @@
/* vim: set sw=8 ts=8 sts=8 noet: */
/* capnp_c.h
*
* Copyright (C) 2013 James McKaskill
* Copyright (C) 2014 Steve Dee
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
#ifndef CAPNP_C_H
#define CAPNP_C_H
#include <stdint.h>
#include <stdio.h>
#if defined(unix) && !defined(__APPLE__)
#include <endian.h>
#endif
// ssize_t is not defined in stdint.h in MSVC.
#ifdef _MSC_VER
typedef intmax_t ssize_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__cplusplus) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
#define CAPN_INLINE static inline
#else
#define CAPN_INLINE static
#endif
#define CAPN_VERSION 1
/* struct capn is a common structure shared between segments in the same
* session/context so that far pointers between segments will be created.
*
* lookup is used to lookup segments by id when derefencing a far pointer
*
* create is used to create or lookup an alternate segment that has at least
* sz available (ie returned seg->len + sz <= seg->cap)
*
* create_local is used to create a segment for the copy tree and should be
* allocated in the local memory space.
*
* Allocated segments must be zero initialized.
*
* create and lookup can be NULL if you don't need multiple segments and don't
* want to support copying
*
* seglist and copylist are linked lists which can be used to free up segments
* on cleanup, but should not be modified by the user.
*
* lookup, create, create_local, and user can be set by the user. Other values
* should be zero initialized.
*/
struct capn {
/* user settable */
struct capn_segment *(*lookup)(void* /*user*/, uint32_t /*id */);
struct capn_segment *(*create)(void* /*user*/, uint32_t /*id */, int /*sz*/);
struct capn_segment *(*create_local)(void* /*user*/, int /*sz*/);
void *user;
/* zero initialized, user should not modify */
uint32_t segnum;
struct capn_tree *copy;
struct capn_tree *segtree;
struct capn_segment *seglist, *lastseg;
struct capn_segment *copylist;
};
/* struct capn_tree is a rb tree header used internally for the segment id
* lookup and copy tree */
struct capn_tree {
struct capn_tree *parent, *link[2];
unsigned int red : 1;
};
struct capn_tree *capn_tree_insert(struct capn_tree *root, struct capn_tree *n);
/* struct capn_segment contains the information about a single segment.
*
* capn points to a struct capn that is shared between segments in the
* same session
*
* id specifies the segment id, used for far pointers
*
* data specifies the segment data. This should not move after creation.
*
* len specifies the current segment length. This is 0 for a blank
* segment.
*
* cap specifies the segment capacity.
*
* When creating new structures len will be incremented until it reaces cap,
* at which point a new segment will be requested via capn->create. The
* create callback can either create a new segment or expand an existing
* one by incrementing cap and returning the expanded segment.
*
* data, len, and cap must all by 8 byte aligned
*
* data, len, cap, and user should all set by the user. Other values
* should be zero initialized.
*/
#ifdef _MSC_VER
__declspec(align(64))
#endif
struct capn_segment {
struct capn_tree hdr;
struct capn_segment *next;
struct capn *capn;
uint32_t id;
/* user settable */
char *data;
size_t len, cap;
void *user;
};
enum CAPN_TYPE {
CAPN_NULL = 0,
CAPN_STRUCT = 1,
CAPN_LIST = 2,
CAPN_PTR_LIST = 3,
CAPN_BIT_LIST = 4,
CAPN_FAR_POINTER = 5,
};
struct capn_ptr {
unsigned int type : 4;
unsigned int has_ptr_tag : 1;
unsigned int is_list_member : 1;
unsigned int is_composite_list : 1;
unsigned int datasz : 19;
unsigned int ptrs : 16;
int len;
char *data;
struct capn_segment *seg;
};
struct capn_text {
int len;
const char *str;
struct capn_segment *seg;
};
typedef struct capn_ptr capn_ptr;
typedef struct capn_text capn_text;
typedef struct {capn_ptr p;} capn_data;
typedef struct {capn_ptr p;} capn_list1;
typedef struct {capn_ptr p;} capn_list8;
typedef struct {capn_ptr p;} capn_list16;
typedef struct {capn_ptr p;} capn_list32;
typedef struct {capn_ptr p;} capn_list64;
struct capn_msg {
struct capn_segment *seg;
uint64_t iface;
uint16_t method;
capn_ptr args;
};
/* capn_append_segment appends a segment to a session */
void capn_append_segment(struct capn*, struct capn_segment*);
capn_ptr capn_root(struct capn *c);
void capn_resolve(capn_ptr *p);
#define capn_len(list) ((list).p.type == CAPN_FAR_POINTER ? (capn_resolve(&(list).p), (list).p.len) : (list).p.len)
/* capn_getp|setp functions get/set ptrs in list/structs
* off is the list index or pointer index in a struct
* capn_setp will copy the data, create far pointers, etc if the target
* is in a different segment/context.
* Both of these will use/return inner pointers for composite lists.
*/
capn_ptr capn_getp(capn_ptr p, int off, int resolve);
int capn_setp(capn_ptr p, int off, capn_ptr tgt);
capn_text capn_get_text(capn_ptr p, int off, capn_text def);
capn_data capn_get_data(capn_ptr p, int off);
int capn_set_text(capn_ptr p, int off, capn_text tgt);
/* capn_get* functions get data from a list
* The length of the list is given by p->size
* off specifies how far into the list to start
* sz indicates the number of elements to get
* The function returns the number of elements read or -1 on an error.
* off must be byte aligned for capn_getv1
*/
int capn_get1(capn_list1 p, int off);
uint8_t capn_get8(capn_list8 p, int off);
uint16_t capn_get16(capn_list16 p, int off);
uint32_t capn_get32(capn_list32 p, int off);
uint64_t capn_get64(capn_list64 p, int off);
int capn_getv1(capn_list1 p, int off, uint8_t *data, int sz);
int capn_getv8(capn_list8 p, int off, uint8_t *data, int sz);
int capn_getv16(capn_list16 p, int off, uint16_t *data, int sz);
int capn_getv32(capn_list32 p, int off, uint32_t *data, int sz);
int capn_getv64(capn_list64 p, int off, uint64_t *data, int sz);
/* capn_set* functions set data in a list
* off specifies how far into the list to start
* sz indicates the number of elements to write
* The function returns the number of elemnts written or -1 on an error.
* off must be byte aligned for capn_setv1
*/
int capn_set1(capn_list1 p, int off, int v);
int capn_set8(capn_list8 p, int off, uint8_t v);
int capn_set16(capn_list16 p, int off, uint16_t v);
int capn_set32(capn_list32 p, int off, uint32_t v);
int capn_set64(capn_list64 p, int off, uint64_t v);
int capn_setv1(capn_list1 p, int off, const uint8_t *data, int sz);
int capn_setv8(capn_list8 p, int off, const uint8_t *data, int sz);
int capn_setv16(capn_list16 p, int off, const uint16_t *data, int sz);
int capn_setv32(capn_list32 p, int off, const uint32_t *data, int sz);
int capn_setv64(capn_list64 p, int off, const uint64_t *data, int sz);
/* capn_new_* functions create a new object
* datasz is in bytes, ptrs is # of pointers, sz is # of elements in the list
* On an error a CAPN_NULL pointer is returned
*/
capn_ptr capn_new_string(struct capn_segment *seg, const char *str, ssize_t sz);
capn_ptr capn_new_struct(struct capn_segment *seg, int datasz, int ptrs);
capn_ptr capn_new_interface(struct capn_segment *seg, int datasz, int ptrs);
capn_ptr capn_new_ptr_list(struct capn_segment *seg, int sz);
capn_ptr capn_new_list(struct capn_segment *seg, int sz, int datasz, int ptrs);
capn_list1 capn_new_list1(struct capn_segment *seg, int sz);
capn_list8 capn_new_list8(struct capn_segment *seg, int sz);
capn_list16 capn_new_list16(struct capn_segment *seg, int sz);
capn_list32 capn_new_list32(struct capn_segment *seg, int sz);
capn_list64 capn_new_list64(struct capn_segment *seg, int sz);
/* capn_read|write* functions read/write struct values
* off is the offset into the structure in bytes
* Rarely should these be called directly, instead use the generated code.
* Data must be xored with the default value
* These are inlined
*/
CAPN_INLINE uint8_t capn_read8(capn_ptr p, int off);
CAPN_INLINE uint16_t capn_read16(capn_ptr p, int off);
CAPN_INLINE uint32_t capn_read32(capn_ptr p, int off);
CAPN_INLINE uint64_t capn_read64(capn_ptr p, int off);
CAPN_INLINE int capn_write1(capn_ptr p, int off, int val);
CAPN_INLINE int capn_write8(capn_ptr p, int off, uint8_t val);
CAPN_INLINE int capn_write16(capn_ptr p, int off, uint16_t val);
CAPN_INLINE int capn_write32(capn_ptr p, int off, uint32_t val);
CAPN_INLINE int capn_write64(capn_ptr p, int off, uint64_t val);
/* capn_init_malloc inits the capn struct with a create function which
* allocates segments on the heap using malloc
*
* capn_init_(fp|mem) inits by reading segments in from the file/memory buffer
* in serialized form (optionally packed). It will then setup the create
* function ala capn_init_malloc so that further segments can be created.
*
* capn_free frees all the segment headers and data created by the create
* function setup by capn_init_*
*/
void capn_init_malloc(struct capn *c);
int capn_init_fp(struct capn *c, FILE *f, int packed);
int capn_init_mem(struct capn *c, const uint8_t *p, size_t sz, int packed);
/* capn_write_(fp|mem) writes segments to the file/memory buffer in
* serialized form and returns the number of bytes written.
*/
/* TODO */
/*int capn_write_fp(struct capn *c, FILE *f, int packed);*/
int capn_write_fd(struct capn *c, ssize_t (*write_fd)(int fd, void *p, size_t count), int fd, int packed);
int capn_write_mem(struct capn *c, uint8_t *p, size_t sz, int packed);
void capn_free(struct capn *c);
void capn_reset_copy(struct capn *c);
/* Inline functions */
CAPN_INLINE uint8_t capn_flip8(uint8_t v) {
return v;
}
CAPN_INLINE uint16_t capn_flip16(uint16_t v) {
#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN)
return v;
#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \
defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8
return __builtin_bswap16(v);
#else
union { uint16_t u; uint8_t v[2]; } s;
s.v[0] = (uint8_t)v;
s.v[1] = (uint8_t)(v>>8);
return s.u;
#endif
}
CAPN_INLINE uint32_t capn_flip32(uint32_t v) {
#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN)
return v;
#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \
defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8
return __builtin_bswap32(v);
#else
union { uint32_t u; uint8_t v[4]; } s;
s.v[0] = (uint8_t)v;
s.v[1] = (uint8_t)(v>>8);
s.v[2] = (uint8_t)(v>>16);
s.v[3] = (uint8_t)(v>>24);
return s.u;
#endif
}
CAPN_INLINE uint64_t capn_flip64(uint64_t v) {
#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN)
return v;
#elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) && \
defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8
return __builtin_bswap64(v);
#else
union { uint64_t u; uint8_t v[8]; } s;
s.v[0] = (uint8_t)v;
s.v[1] = (uint8_t)(v>>8);
s.v[2] = (uint8_t)(v>>16);
s.v[3] = (uint8_t)(v>>24);
s.v[4] = (uint8_t)(v>>32);
s.v[5] = (uint8_t)(v>>40);
s.v[6] = (uint8_t)(v>>48);
s.v[7] = (uint8_t)(v>>56);
return s.u;
#endif
}
CAPN_INLINE int capn_write1(capn_ptr p, int off, int val) {
if (off >= p.datasz*8) {
return -1;
} else if (val) {
uint8_t tmp = (uint8_t)(1 << (off & 7));
((uint8_t*) p.data)[off >> 3] |= tmp;
return 0;
} else {
uint8_t tmp = (uint8_t)(~(1 << (off & 7)));
((uint8_t*) p.data)[off >> 3] &= tmp;
return 0;
}
}
CAPN_INLINE uint8_t capn_read8(capn_ptr p, int off) {
return off+1 <= p.datasz ? capn_flip8(*(uint8_t*) (p.data+off)) : 0;
}
CAPN_INLINE int capn_write8(capn_ptr p, int off, uint8_t val) {
if (off+1 <= p.datasz) {
*(uint8_t*) (p.data+off) = capn_flip8(val);
return 0;
} else {
return -1;
}
}
CAPN_INLINE uint16_t capn_read16(capn_ptr p, int off) {
return off+2 <= p.datasz ? capn_flip16(*(uint16_t*) (p.data+off)) : 0;
}
CAPN_INLINE int capn_write16(capn_ptr p, int off, uint16_t val) {
if (off+2 <= p.datasz) {
*(uint16_t*) (p.data+off) = capn_flip16(val);
return 0;
} else {
return -1;
}
}
CAPN_INLINE uint32_t capn_read32(capn_ptr p, int off) {
return off+4 <= p.datasz ? capn_flip32(*(uint32_t*) (p.data+off)) : 0;
}
CAPN_INLINE int capn_write32(capn_ptr p, int off, uint32_t val) {
if (off+4 <= p.datasz) {
*(uint32_t*) (p.data+off) = capn_flip32(val);
return 0;
} else {
return -1;
}
}
CAPN_INLINE uint64_t capn_read64(capn_ptr p, int off) {
return off+8 <= p.datasz ? capn_flip64(*(uint64_t*) (p.data+off)) : 0;
}
CAPN_INLINE int capn_write64(capn_ptr p, int off, uint64_t val) {
if (off+8 <= p.datasz) {
*(uint64_t*) (p.data+off) = capn_flip64(val);
return 0;
} else {
return -1;
}
}
union capn_conv_f32 {
uint32_t u;
float f;
};
union capn_conv_f64 {
uint64_t u;
double f;
};
CAPN_INLINE float capn_to_f32(uint32_t v) {
union capn_conv_f32 u;
u.u = v;
return u.f;
}
CAPN_INLINE double capn_to_f64(uint64_t v) {
union capn_conv_f64 u;
u.u = v;
return u.f;
}
CAPN_INLINE uint32_t capn_from_f32(float v) {
union capn_conv_f32 u;
u.f = v;
return u.u;
}
CAPN_INLINE uint64_t capn_from_f64(double v) {
union capn_conv_f64 u;
u.f = v;
return u.u;
}
#ifdef __cplusplus
}
#endif
#endif

1381
phonelibs/json/src/json.c Normal file

File diff suppressed because it is too large Load Diff

117
phonelibs/json/src/json.h Normal file
View File

@@ -0,0 +1,117 @@
/*
Copyright (C) 2011 Joseph A. Adams (joeyadams3.14159@gmail.com)
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef CCAN_JSON_H
#define CCAN_JSON_H
#include <stdbool.h>
#include <stddef.h>
typedef enum {
JSON_NULL,
JSON_BOOL,
JSON_STRING,
JSON_NUMBER,
JSON_ARRAY,
JSON_OBJECT,
} JsonTag;
typedef struct JsonNode JsonNode;
struct JsonNode
{
/* only if parent is an object or array (NULL otherwise) */
JsonNode *parent;
JsonNode *prev, *next;
/* only if parent is an object (NULL otherwise) */
char *key; /* Must be valid UTF-8. */
JsonTag tag;
union {
/* JSON_BOOL */
bool bool_;
/* JSON_STRING */
char *string_; /* Must be valid UTF-8. */
/* JSON_NUMBER */
double number_;
/* JSON_ARRAY */
/* JSON_OBJECT */
struct {
JsonNode *head, *tail;
} children;
};
};
/*** Encoding, decoding, and validation ***/
JsonNode *json_decode (const char *json);
char *json_encode (const JsonNode *node);
char *json_encode_string (const char *str);
char *json_stringify (const JsonNode *node, const char *space);
void json_delete (JsonNode *node);
bool json_validate (const char *json);
/*** Lookup and traversal ***/
JsonNode *json_find_element (JsonNode *array, int index);
JsonNode *json_find_member (JsonNode *object, const char *key);
JsonNode *json_first_child (const JsonNode *node);
#define json_foreach(i, object_or_array) \
for ((i) = json_first_child(object_or_array); \
(i) != NULL; \
(i) = (i)->next)
/*** Construction and manipulation ***/
JsonNode *json_mknull(void);
JsonNode *json_mkbool(bool b);
JsonNode *json_mkstring(const char *s);
JsonNode *json_mknumber(double n);
JsonNode *json_mkarray(void);
JsonNode *json_mkobject(void);
void json_append_element(JsonNode *array, JsonNode *element);
void json_prepend_element(JsonNode *array, JsonNode *element);
void json_append_member(JsonNode *object, const char *key, JsonNode *value);
void json_prepend_member(JsonNode *object, const char *key, JsonNode *value);
void json_remove_from_parent(JsonNode *node);
/*** Debugging ***/
/*
* Look for structure and encoding problems in a JsonNode or its descendents.
*
* If a problem is detected, return false, writing a description of the problem
* to errmsg (unless errmsg is NULL).
*/
bool json_check(const JsonNode *node, char errmsg[256]);
#endif

1
pyextra Submodule

Submodule pyextra added at e0738376db

View File

@@ -0,0 +1,14 @@
Cython==0.24.1
bitstring==3.1.5
fastcluster==1.1.21
libusb1==1.5.0
pycapnp==0.5.9
pyzmq==15.4.0
raven==5.23.0
requests==2.10.0
setproctitle==1.1.10
simplejson==3.8.2
pyyaml==3.12
cffi==1.7.0
enum34==1.1.1
-e git+https://github.com/commaai/le_python.git#egg=Logentries

7
run_docker_tests.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
set -e
docker build -t tmppilot -f Dockerfile.openpilot .
docker run --rm \
-v "$(pwd)"/selfdrive/test/plant/out:/tmp/openpilot/selfdrive/test/plant/out \
tmppilot /bin/sh -c 'cd /tmp/openpilot/selfdrive/test/plant && ./runtest.sh'

1
selfdrive/boardd/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
boardd

View File

@@ -2,6 +2,7 @@ CC = clang
CXX = clang++
ARCH := $(shell uname -m)
OS := $(shell uname -o)
PHONELIBS = ../../phonelibs
@@ -19,29 +20,37 @@ ZMQ_LIBS = -L$(PHONELIBS)/zmq/aarch64/lib \
-l:libczmq.a -l:libzmq.a \
-lgnustl_shared
CEREAL_FLAGS = -I$(PHONELIBS)/capnp-cpp/include
CEREAL_LIBS = -L$(PHONELIBS)/capnp-cpp/aarch64/lib/ \
-l:libcapnp.a -l:libkj.a
CEREAL_OBJS = ../../cereal/gen/c/log.capnp.o
JSON_FLAGS = -I$(PHONELIBS)/json/src
EXTRA_LIBS = -lusb
ifeq ($(ARCH),x86_64)
ZMQ_LIBS = -L$(HOME)/drive/external/zmq/lib/ \
-l:libczmq.a -l:libzmq.a
CEREAL_LIBS = -L$(HOME)/drive/external/capnp/lib/ \
-l:libcapnp.a -l:libkj.a
ifeq ($(OS),GNU/Linux)
# for Drive PX2
ZMQ_LIBS = -lczmq -lzmq
CEREAL_LIBS = -lcapnp -lkj -lcapnp_c
EXTRA_LIBS = -lusb-1.0 -lpthread
endif
ifeq ($(ARCH),x86_64)
ZMQ_LIBS = -L$(HOME)/one/external/zmq/lib/ \
-l:libczmq.a -l:libzmq.a
CEREAL_LIBS = -L$(HOME)/one/external/capnp/lib/ \
-l:libcapnp.a -l:libcapnp_c.a -l:libkj.a
EXTRA_LIBS = -lusb-1.0 -lpthread
endif
.PHONY: all
all: boardd
include ../common/cereal.mk
OBJS = boardd.o \
log.capnp.o
../common/swaglog.o \
$(PHONELIBS)/json/src/json.o \
$(CEREAL_OBJS)
DEPS := $(OBJS:.o=.d)
all: boardd
boardd: $(OBJS)
@echo "[ LINK ] $@"
$(CXX) -fPIC -o '$@' $^ \
@@ -53,18 +62,21 @@ boardd.o: boardd.cc
@echo "[ CXX ] $@"
$(CXX) $(CXXFLAGS) \
-I$(PHONELIBS)/android_system_core/include \
$(CEREAL_FLAGS) \
$(CEREAL_CFLAGS) \
$(CEREAL_CXXFLAGS) \
$(ZMQ_FLAGS) \
-I../ \
-I../../ \
-c -o '$@' '$<'
log.capnp.o: ../../cereal/gen/cpp/log.capnp.c++
@echo "[ CXX ] $@"
$(CXX) $(CXXFLAGS) $(CEREAL_FLAGS) \
-c -o '$@' '$<'
%.o: %.c
@echo "[ CC ] $@"
$(CC) $(CFLAGS) -MMD \
-Iinclude -I.. -I../.. \
$(CEREAL_CFLAGS) \
$(ZMQ_FLAGS) \
$(JSON_FLAGS) \
-c -o '$@' '$<'
.PHONY: clean
clean:

View File

@@ -4,6 +4,7 @@
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sched.h>
#include <sys/time.h>
#include <sys/cdefs.h>
#include <sys/types.h>
@@ -19,6 +20,7 @@
#include <capnp/serialize.h>
#include "cereal/gen/cpp/log.capnp.h"
#include "common/swaglog.h"
#include "common/timing.h"
int do_exit = 0;
@@ -27,16 +29,17 @@ libusb_context *ctx = NULL;
libusb_device_handle *dev_handle;
pthread_mutex_t usb_lock;
bool spoofing_started = false;
bool fake_send = false;
bool loopback_can = false;
// double the FIFO size
#define RECV_SIZE (0x1000)
#define TIMEOUT 0
#define DEBUG_BOARDD
#ifdef DEBUG_BOARDD
#define DPRINTF(fmt, ...) printf("boardd: " fmt, ## __VA_ARGS__)
#else
#define DPRINTF(fmt, ...)
#endif
#define SAFETY_NOOUTPUT 0x0000
#define SAFETY_HONDA 0x0001
#define SAFETY_ALLOUTPUT 0x1337
bool usb_connect() {
int err;
@@ -50,14 +53,50 @@ bool usb_connect() {
err = libusb_claim_interface(dev_handle, 0);
if (err != 0) { return false; }
if (loopback_can) {
libusb_control_transfer(dev_handle, 0xc0, 0xe5, 1, 0, NULL, 0, TIMEOUT);
}
// power off ESP
libusb_control_transfer(dev_handle, 0xc0, 0xd9, 0, 0, NULL, 0, TIMEOUT);
// forward CAN1 to CAN3...soon
//libusb_control_transfer(dev_handle, 0xc0, 0xdd, 1, 2, NULL, 0, TIMEOUT);
// set UART modes for Honda Accord
/*for (int uart = 2; uart <= 3; uart++) {
// 9600 baud
libusb_control_transfer(dev_handle, 0x40, 0xe1, uart, 9600, NULL, 0, TIMEOUT);
// even parity
libusb_control_transfer(dev_handle, 0x40, 0xe2, uart, 1, NULL, 0, TIMEOUT);
// callback 1
libusb_control_transfer(dev_handle, 0x40, 0xe3, uart, 1, NULL, 0, TIMEOUT);
}
// TODO: Boardd should be able to set the baud rate
int baud = 500000;
libusb_control_transfer(dev_handle, 0x40, 0xde, 0, 0,
(unsigned char *)&baud, sizeof(baud), TIMEOUT); // CAN1
libusb_control_transfer(dev_handle, 0x40, 0xde, 1, 0,
(unsigned char *)&baud, sizeof(baud), TIMEOUT); // CAN2*/
// TODO: Boardd should be able to be told which safety model to use
libusb_control_transfer(dev_handle, 0x40, 0xdc, SAFETY_HONDA, 0, NULL, 0, TIMEOUT);
return true;
}
void usb_retry_connect() {
LOG("attempting to connect");
while (!usb_connect()) { usleep(100*1000); }
LOGW("connected to board");
}
void handle_usb_issue(int err, const char func[]) {
DPRINTF("usb error %d \"%s\" in %s\n", err, libusb_strerror((enum libusb_error)err), func);
LOGE("usb error %d \"%s\" in %s", err, libusb_strerror((enum libusb_error)err), func);
if (err == -4) {
while (!usb_connect()) { DPRINTF("attempting to connect\n"); usleep(100*1000); }
LOGE("lost connection");
usb_retry_connect();
}
// TODO: check other errors, is simply retrying okay?
}
@@ -70,11 +109,11 @@ void can_recv(void *s) {
// do recv
pthread_mutex_lock(&usb_lock);
do {
err = libusb_bulk_transfer(dev_handle, 0x81, (uint8_t*)data, RECV_SIZE, &recv, TIMEOUT);
if (err != 0) { handle_usb_issue(err, __func__); }
if (err == -8) { DPRINTF("overflow got 0x%x\n", recv); };
if (err == -8) { LOGE("overflow got 0x%x", recv); };
// timeout is okay to exit, recv still happened
if (err == -7) { break; }
@@ -107,25 +146,27 @@ void can_recv(void *s) {
canData[i].setBusTime(data[i*4+1] >> 16);
int len = data[i*4+1]&0xF;
canData[i].setDat(kj::arrayPtr((uint8_t*)&data[i*4+2], len));
canData[i].setSrc((data[i*4+1] >> 4) & 3);
canData[i].setSrc((data[i*4+1] >> 4) & 0xff);
}
// send to can
auto words = capnp::messageToFlatArray(msg);
auto bytes = words.asBytes();
zmq_send(s, bytes.begin(), bytes.size(), 0);
zmq_send(s, bytes.begin(), bytes.size(), 0);
}
void can_health(void *s) {
int cnt;
// copied from board/main.c
struct health {
struct __attribute__((packed)) health {
uint32_t voltage;
uint32_t current;
uint8_t started;
uint8_t controls_allowed;
uint8_t gas_interceptor_detected;
uint8_t started_signal_detected;
uint8_t started_alt;
} health;
// recv from board
@@ -147,14 +188,19 @@ void can_health(void *s) {
// set fields
healthData.setVoltage(health.voltage);
healthData.setCurrent(health.current);
healthData.setStarted(health.started);
if (spoofing_started) {
healthData.setStarted(1);
} else {
healthData.setStarted(health.started);
}
healthData.setControlsAllowed(health.controls_allowed);
healthData.setGasInterceptorDetected(health.gas_interceptor_detected);
healthData.setStartedSignalDetected(health.started_signal_detected);
// send to health
auto words = capnp::messageToFlatArray(msg);
auto bytes = words.asBytes();
zmq_send(s, bytes.begin(), bytes.size(), 0);
zmq_send(s, bytes.begin(), bytes.size(), 0);
}
@@ -167,8 +213,10 @@ void can_send(void *s) {
err = zmq_msg_recv(&msg, s, 0);
assert(err >= 0);
// format for board
auto amsg = kj::arrayPtr((const capnp::word*)zmq_msg_data(&msg), zmq_msg_size(&msg));
// format for board, make copy due to alignment issues, will be freed on out of scope
auto amsg = kj::heapArray<capnp::word>((zmq_msg_size(&msg) / sizeof(capnp::word)) + 1);
memcpy(amsg.begin(), zmq_msg_data(&msg), zmq_msg_size(&msg));
capnp::FlatArrayMessageReader cmsg(amsg);
cereal::Event::Reader event = cmsg.getRoot<cereal::Event>();
int msg_count = event.getCan().size();
@@ -177,7 +225,7 @@ void can_send(void *s) {
memset(send, 0, msg_count*0x10);
for (int i = 0; i < msg_count; i++) {
auto cmsg = event.getCan()[i];
auto cmsg = event.getSendcan()[i];
if (cmsg.getAddress() >= 0x800) {
// extended
send[i*4] = (cmsg.getAddress() << 3) | 5;
@@ -190,8 +238,6 @@ void can_send(void *s) {
memcpy(&send[i*4+2], cmsg.getDat().begin(), cmsg.getDat().size());
}
//DPRINTF("got send message: %d\n", msg_count);
// release msg
zmq_msg_close(&msg);
@@ -199,10 +245,12 @@ void can_send(void *s) {
int sent;
pthread_mutex_lock(&usb_lock);
do {
err = libusb_bulk_transfer(dev_handle, 3, (uint8_t*)send, msg_count*0x10, &sent, TIMEOUT);
if (err != 0 || msg_count*0x10 != sent) { handle_usb_issue(err, __func__); }
} while(err != 0);
if (!fake_send) {
do {
err = libusb_bulk_transfer(dev_handle, 3, (uint8_t*)send, msg_count*0x10, &sent, TIMEOUT);
if (err != 0 || msg_count*0x10 != sent) { handle_usb_issue(err, __func__); }
} while(err != 0);
}
pthread_mutex_unlock(&usb_lock);
@@ -214,7 +262,7 @@ void can_send(void *s) {
// **** threads ****
void *can_send_thread(void *crap) {
DPRINTF("start send thread\n");
LOGD("start send thread");
// sendcan = 8017
void *context = zmq_ctx_new();
@@ -230,7 +278,7 @@ void *can_send_thread(void *crap) {
}
void *can_recv_thread(void *crap) {
DPRINTF("start recv thread\n");
LOGD("start recv thread");
// can = 8006
void *context = zmq_ctx_new();
@@ -247,7 +295,7 @@ void *can_recv_thread(void *crap) {
}
void *can_health_thread(void *crap) {
DPRINTF("start health thread\n");
LOGD("start health thread");
// health = 8011
void *context = zmq_ctx_new();
@@ -262,32 +310,45 @@ void *can_health_thread(void *crap) {
return NULL;
}
int set_realtime_priority(int level) {
// should match python using chrt
struct sched_param sa;
memset(&sa, 0, sizeof(sa));
sa.sched_priority = level;
return sched_setscheduler(getpid(), SCHED_FIFO, &sa);
}
int main() {
int err;
printf("boardd: starting boardd\n");
LOGW("starting boardd");
// set process priority
err = setpriority(PRIO_PROCESS, 0, -4);
printf("boardd: setpriority returns %d\n", err);
err = set_realtime_priority(4);
LOG("setpriority returns %d", err);
// connect to the board
// check the environment
if (getenv("STARTED")) {
spoofing_started = true;
}
if (getenv("FAKESEND")) {
fake_send = true;
}
if(getenv("BOARDD_LOOPBACK")){
loopback_can = true;
}
// init libusb
err = libusb_init(&ctx);
assert(err == 0);
libusb_set_debug(ctx, 3);
// TODO: duplicate code from error handling
while (!usb_connect()) { DPRINTF("attempting to connect\n"); usleep(100*1000); }
// connect to the board
usb_retry_connect();
/*int config;
err = libusb_get_configuration(dev_handle, &config);
assert(err == 0);
DPRINTF("configuration is %d\n", config);*/
/*err = libusb_set_interface_alt_setting(dev_handle, 0, 0);
assert(err == 0);*/
// create threads
pthread_t can_health_thread_handle;
err = pthread_create(&can_health_thread_handle, NULL,
can_health_thread, NULL);
@@ -319,4 +380,3 @@ int main() {
libusb_close(dev_handle);
libusb_exit(ctx);
}

View File

@@ -2,10 +2,11 @@
import os
import struct
import zmq
import time
import selfdrive.messaging as messaging
from common.realtime import Ratekeeper
from common.services import service_list
from selfdrive.services import service_list
from selfdrive.swaglog import cloudlog
# USB is optional
@@ -17,28 +18,30 @@ except Exception:
# TODO: rewrite in C to save CPU
SAFETY_NOOUTPUT = 0
SAFETY_HONDA = 1
SAFETY_ALLOUTPUT = 0x1337
# *** serialization functions ***
def can_list_to_can_capnp(can_msgs):
def can_list_to_can_capnp(can_msgs, msgtype='can'):
dat = messaging.new_message()
dat.init('can', len(can_msgs))
dat.init(msgtype, len(can_msgs))
for i, can_msg in enumerate(can_msgs):
dat.can[i].address = can_msg[0]
dat.can[i].busTime = can_msg[1]
dat.can[i].dat = can_msg[2]
dat.can[i].src = can_msg[3]
if msgtype == 'sendcan':
cc = dat.sendcan[i]
else:
cc = dat.can[i]
cc.address = can_msg[0]
cc.busTime = can_msg[1]
cc.dat = can_msg[2]
cc.src = can_msg[3]
return dat
def can_capnp_to_can_list_old(dat, src_filter=[]):
def can_capnp_to_can_list(can, src_filter=None):
ret = []
for msg in dat.can:
if msg.src in src_filter:
ret.append([msg.address, msg.busTime, msg.dat.encode("hex")])
return ret
def can_capnp_to_can_list(dat):
ret = []
for msg in dat.can:
ret.append([msg.address, msg.busTime, msg.dat, msg.src])
for msg in can:
if src_filter is None or msg.src in src_filter:
ret.append((msg.address, msg.busTime, msg.dat, msg.src))
return ret
# *** can driver ***
@@ -58,7 +61,7 @@ def __parse_can_buffer(dat):
for j in range(0, len(dat), 0x10):
ddat = dat[j:j+0x10]
f1, f2 = struct.unpack("II", ddat[0:8])
ret.append((f1 >> 21, f2>>16, ddat[8:8+(f2&0xF)], (f2>>4)&3))
ret.append((f1 >> 21, f2>>16, ddat[8:8+(f2&0xF)], (f2>>4)&0xF))
return ret
def can_send_many(arr):
@@ -86,6 +89,7 @@ def can_recv():
def can_init():
global handle, context
handle = None
cloudlog.info("attempting can init")
context = usb1.USBContext()
@@ -95,6 +99,7 @@ def can_init():
if device.getVendorID() == 0xbbaa and device.getProductID() == 0xddcc:
handle = device.open()
handle.claimInterface(0)
handle.controlWrite(0x40, 0xdc, SAFETY_HONDA, 0, b'')
if handle is None:
print "CAN NOT FOUND"
@@ -111,7 +116,7 @@ def boardd_mock_loop():
while 1:
tsc = messaging.drain_sock(logcan, wait_for_one=True)
snds = map(can_capnp_to_can_list, tsc)
snds = map(lambda x: can_capnp_to_can_list(x.can), tsc)
snd = []
for s in snds:
snd += s
@@ -124,6 +129,19 @@ def boardd_mock_loop():
#print can_msgs
def boardd_test_loop():
can_init()
cnt = 0
while 1:
can_send_many([[0xbb,0,"\xaa\xaa\xaa\xaa",0], [0xaa,0,"\xaa\xaa\xaa\xaa"+struct.pack("!I", cnt),1]])
#can_send_many([[0xaa,0,"\xaa\xaa\xaa\xaa",0]])
#can_send_many([[0xaa,0,"\xaa\xaa\xaa\xaa",1]])
# recv @ 100hz
can_msgs = can_recv()
print "got %d" % (len(can_msgs))
time.sleep(0.01)
cnt += 1
# *** main loop ***
def boardd_loop(rate=200):
rk = Ratekeeper(rate)
@@ -164,16 +182,17 @@ def boardd_loop(rate=200):
# send can if we have a packet
tsc = messaging.recv_sock(sendcan)
if tsc is not None:
can_send_many(can_capnp_to_can_list(tsc))
can_send_many(can_capnp_to_can_list(tsc.sendcan))
rk.keep_time()
def main(gctx=None):
if os.getenv("MOCK") is not None:
boardd_mock_loop()
elif os.getenv("BOARDTEST") is not None:
boardd_test_loop()
else:
boardd_loop()
if __name__ == "__main__":
main()

View File

@@ -1,208 +0,0 @@
import numpy as np
import common.filters as filters
from selfdrive.controls.lib.latcontrol import calc_curvature
# Calibration Status
class CalibStatus(object):
INCOMPLETE = 0
VALID = 1
INVALID = 2
def line_intersection(line1, line2, no_int_sub = [0,0]):
xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
def det(a, b):
return a[0] * b[1] - a[1] * b[0]
div = det(xdiff, ydiff)
if div == 0:
# since we are in float domain, this should really never happen
return no_int_sub
d = (det(*line1), det(*line2))
x = det(d, xdiff) / div
y = det(d, ydiff) / div
return [x, y]
def points_inside_hit_box(pts, box):
"""Determine which points lie inside a box.
Inputs:
pts: An nx2 array of points to hit test.
box: An array [[x_left, y_top], [x_right, y_bottom]] describing a box to
use for hit testing.
Returns:
A logical array with true for every member of pts inside box.
"""
hits = np.all(np.logical_and(pts > box[0, :], pts < box[1, :]), axis=1)
return hits
def warp_points(pt_s, warp_matrix):
# pt_s are the source points, nx2 array.
pt_d = np.dot(warp_matrix[:, :2], pt_s.T) + warp_matrix[:, 2][:, np.newaxis]
# divide by third dimension for representation in image space.
return (pt_d[:2, :] / pt_d[2, :]).T
class ViewCalibrator(object):
def __init__(self, box_size, big_box_size, vp_r, warp_matrix_start, vp_f=None, cal_cycle=0, cal_status=0):
self.calibration_threshold = 3000
self.box_size = box_size
self.big_box_size = big_box_size
self.warp_matrix_start = warp_matrix_start
self.vp_r = list(vp_r)
if vp_f is None:
self.vp_f = list(vp_r)
else:
self.vp_f = list(vp_f)
# slow filter fot the vanishing point
vp_fr = 0.005 # Hz, slow filter
self.dt = 0.05 # camera runs at 20Hz
self.update_warp_matrix()
self.vp_x_filter = filters.FirstOrderLowpassFilter(vp_fr, self.dt, self.vp_f[0])
self.vp_y_filter = filters.FirstOrderLowpassFilter(vp_fr, self.dt, self.vp_f[1])
self.cal_cycle = cal_cycle
self.cal_status = cal_status
self.cal_perc = int(np.minimum(self.cal_cycle*100./self.calibration_threshold, 100))
def vanishing_point_process(self, old_ps, new_ps, v_ego, steer_angle, VP):
# correct diffs by yaw rate
cam_fov = 23.06*np.pi/180. # deg
curvature = calc_curvature(v_ego, steer_angle, VP)
yaw_rate = curvature * v_ego
hor_angle_shift = yaw_rate * self.dt * self.box_size[0] / cam_fov
old_ps += [hor_angle_shift, 0] # old points have moved in the image due to yaw rate
pos_ps = [None]*len(new_ps)
for ii in range(len(old_ps)):
xo = old_ps[ii][0]
yo = old_ps[ii][1]
yn = new_ps[ii][1]
# don't consider points with low flow in y
if abs(yn - yo) > 1:
if xo > (self.vp_f[0] + 20):
pos_ps[ii] = 'r' # right lane point
elif xo < (self.vp_f[0] - 20):
pos_ps[ii] = 'l' # left lane point
# intersect all the right lines with the left lines
idxs_l = [i for i, x in enumerate(pos_ps) if x == 'l']
idxs_r = [i for i, x in enumerate(pos_ps) if x == 'r']
old_ps_l, new_ps_l = old_ps[idxs_l], new_ps[idxs_l]
old_ps_r, new_ps_r = old_ps[idxs_r], new_ps[idxs_r]
# return None if there is one side with no lines, the speed is low or the steer angle is high
if len(old_ps_l) == 0 or len(old_ps_r) == 0 or v_ego < 20 or abs(steer_angle) > 5:
return None
int_ps = [[None] * len(old_ps_r)] * len(old_ps_l)
for ll in range(len(old_ps_l)):
for rr in range(len(old_ps_r)):
old_p_l, old_p_r, new_p_l, new_p_r = old_ps_l[ll], old_ps_r[
rr], new_ps_l[ll], new_ps_r[rr]
line_l = [[old_p_l[0], old_p_l[1]], [new_p_l[0], new_p_l[1]]]
line_r = [[old_p_r[0], old_p_r[1]], [new_p_r[0], new_p_r[1]]]
int_ps[ll][rr] = line_intersection(
line_l, line_r, no_int_sub=self.vp_f)
# saturate outliers that are too far from the estimated vp
int_ps[ll][rr][0] = np.clip(int_ps[ll][rr][0], self.vp_f[0] - 20, self.vp_f[0] + 20)
int_ps[ll][rr][1] = np.clip(int_ps[ll][rr][1], self.vp_f[1] - 30, self.vp_f[1] + 30)
vp = np.mean(np.mean(np.array(int_ps), axis=0), axis=0)
return vp
def calibration_validity(self):
# this function sanity checks that the small box is contained in the big box.
# otherwise the warp function will generate black spots on the small box
cp = np.asarray([[0, 0],
[self.box_size[0], 0],
[self.box_size[0], self.box_size[1]],
[0, self.box_size[1]]])
cpw = warp_points(cp, self.warp_matrix)
# pixel margin for validity hysteresys:
# - if calibration is good, keep it good until small box is inside the big box
# - if calibration isn't good, then make it good again if small box is in big box with margin
margin_px = 0 if self.cal_status == CalibStatus.VALID else 5
big_hit_box = np.asarray(
[[margin_px, margin_px],
[self.big_box_size[0], self.big_box_size[1] - margin_px]])
cpw_outside_big_box = np.logical_not(points_inside_hit_box(cpw, big_hit_box))
return not np.any(cpw_outside_big_box)
def get_calibration_hit_box(self):
"""Returns an axis-aligned hit box in canonical image space.
Points which do not fall within this box should not be used for
calibration.
Returns:
An array [[x_left, y_top], [x_right, y_bottom]] describing a box inside
which all calibration points should lie.
"""
# We mainly care about feature from lanes, so removed points from sky.
y_filter = 50.
return np.asarray([[0, y_filter], [self.box_size[0], self.box_size[1]]])
def update_warp_matrix(self):
translation_matrix = np.asarray(
[[1, 0, self.vp_f[0] - self.vp_r[0]],
[0, 1, self.vp_f[1] - self.vp_r[1]],
[0, 0, 1]])
self.warp_matrix = np.dot(translation_matrix, self.warp_matrix_start)
self.warp_matrix_inv = np.linalg.inv(self.warp_matrix)
def calibration(self, p0, p1, st, v_ego, steer_angle, VP):
# convert to np array first thing
p0 = np.asarray(p0)
p1 = np.asarray(p1)
st = np.asarray(st)
p0 = p0.reshape((-1,2))
p1 = p1.reshape((-1,2))
# filter out pts with bad status
p0 = p0[st==1]
p1 = p1[st==1]
calib_hit_box = self.get_calibration_hit_box()
# remove all the points outside the small box and above the horizon line
good_idxs = points_inside_hit_box(
warp_points(p0, self.warp_matrix_inv), calib_hit_box)
p0 = p0[good_idxs]
p1 = p1[good_idxs]
# print("unwarped points: {}".format(warp_points(p0, self.warp_matrix_inv)))
# print("good_idxs {}:".format(good_idxs))
# get instantaneous vp
vp = self.vanishing_point_process(p0, p1, v_ego, steer_angle, VP)
if vp is not None:
# filter the vanishing point
self.vp_f = [self.vp_x_filter(vp[0]), self.vp_y_filter(vp[1])]
self.cal_cycle += 1
if not self.calibration_validity():
self.cal_status = CalibStatus.INVALID
else:
# 10 minutes @5Hz TODO: make this threshold function of convergency speed
self.cal_status = CalibStatus.VALID
#self.cal_status = CalibStatus.VALID if self.cal_cycle > self.calibration_threshold else CalibStatus.INCOMPLETE
self.cal_perc = int(np.minimum(self.cal_cycle*100./self.calibration_threshold, 100))
self.update_warp_matrix()

View File

@@ -1,116 +0,0 @@
#!/usr/bin/env python
import os
import numpy as np
import zmq
from common.services import service_list
import selfdrive.messaging as messaging
from selfdrive.config import ImageParams, VehicleParams
from selfdrive.calibrationd.calibration import ViewCalibrator, CalibStatus
CALIBRATION_FILE = "/sdcard/calibration_param"
def load_calibration(gctx):
# calibration initialization
I = ImageParams()
vp_guess = None
if gctx is not None:
warp_matrix_start = np.array(
gctx['calibration']["initial_homography"]).reshape(3, 3)
big_box_size = [560, 304]
else:
warp_matrix_start = np.array([[1., 0., I.SX_R],
[0., 1., I.SY_R],
[0., 0., 1.]])
big_box_size = [640, 480]
# translate the vanishing point into phone image space
vp_box = (I.VPX_R-I.SX_R, I.VPY_R-I.SY_R)
vp_trans = np.dot(warp_matrix_start, vp_box+(1.,))
vp_img = (vp_trans[0]/vp_trans[2], vp_trans[1]/vp_trans[2])
# load calibration data
if os.path.isfile(CALIBRATION_FILE):
# if the calibration file exist, start from the last cal values
with open(CALIBRATION_FILE, "r") as cal_file:
data = [float(l.strip()) for l in cal_file.readlines()]
calib = ViewCalibrator((I.X, I.Y),
big_box_size,
vp_img,
warp_matrix_start,
vp_f=[data[2], data[3]],
cal_cycle=data[0],
cal_status=data[1])
if calib.cal_status == CalibStatus.INCOMPLETE:
print "CALIBRATION IN PROGRESS", calib.cal_cycle
else:
print "NO CALIBRATION FILE"
calib = ViewCalibrator((I.X, I.Y),
big_box_size,
vp_img,
warp_matrix_start,
vp_f=vp_guess)
return calib
def calibrationd_thread(gctx):
context = zmq.Context()
features = messaging.sub_sock(context, service_list['features'].port)
live100 = messaging.sub_sock(context, service_list['live100'].port)
livecalibration = messaging.pub_sock(context, service_list['liveCalibration'].port)
# subscribe to stats about the car
VP = VehicleParams(False)
v_ego = None
calib = load_calibration(gctx)
last_cal_cycle = calib.cal_cycle
while 1:
# calibration at the end so it does not delay radar processing above
ft = messaging.recv_sock(features, wait=True)
# get latest here
l100 = messaging.recv_sock(live100)
if l100 is not None:
v_ego = l100.live100.vEgo
steer_angle = l100.live100.angleSteers
if v_ego is None:
continue
p0 = ft.features.p0
p1 = ft.features.p1
st = ft.features.status
calib.calibration(p0, p1, st, v_ego, steer_angle, VP)
# write a new calibration every 100 cal cycle
if calib.cal_cycle - last_cal_cycle >= 100:
print "writing cal", calib.cal_cycle
with open(CALIBRATION_FILE, "w") as cal_file:
cal_file.write(str(calib.cal_cycle)+'\n')
cal_file.write(str(calib.cal_status)+'\n')
cal_file.write(str(calib.vp_f[0])+'\n')
cal_file.write(str(calib.vp_f[1])+'\n')
last_cal_cycle = calib.cal_cycle
warp_matrix = map(float, calib.warp_matrix.reshape(9).tolist())
dat = messaging.new_message()
dat.init('liveCalibration')
dat.liveCalibration.warpMatrix = warp_matrix
dat.liveCalibration.calStatus = calib.cal_status
dat.liveCalibration.calCycle = calib.cal_cycle
dat.liveCalibration.calPerc = calib.cal_perc
livecalibration.send(dat.to_bytes())
def main(gctx=None):
calibrationd_thread(gctx)
if __name__ == "__main__":
main()

72
selfdrive/can/Makefile Normal file
View File

@@ -0,0 +1,72 @@
CC = clang
CXX = clang++
PHONELIBS := ../../phonelibs
UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m)
WARN_FLAGS = -Werror=implicit-function-declaration \
-Werror=incompatible-pointer-types \
-Werror=int-conversion \
-Werror=return-type \
-Werror=format-extra-args \
-Wno-deprecated-declarations
CFLAGS = -std=gnu11 -g -fPIC -O2 $(WARN_FLAGS)
CXXFLAGS = -std=c++11 -g -fPIC -O2 $(WARN_FLAGS)
ifeq ($(UNAME_S),Darwin)
CEREAL_LIBS := -L /usr/local/lib -lkj -lcapnp
ZMQ_LIBS = -L/usr/local/lib -lzmq
else ifeq ($(OPTEST),1)
ZMQ_LIBS = -lzmq
CEREAL_LIBS = -lcapnp -lkj
else ifeq ($(UNAME_M),x86_64)
EXTERNAL := ../../external
ZMQ_FLAGS = -I$(EXTERNAL)/zmq/include
ZMQ_LIBS = -L$(EXTERNAL)/zmq/lib -l:libzmq.a
CEREAL_CXXFLAGS := -I$(EXTERNAL)/capnp/include
CEREAL_LIBS := -L$(EXTERNAL)/capnp/lib -l:libcapnp.a -l:libkj.a
else ifeq ($(UNAME_M),aarch64)
ZMQ_FLAGS = -I$(PHONELIBS)/zmq/aarch64/include
ZMQ_LIBS = -L$(PHONELIBS)/zmq/aarch64/lib -l:libzmq.a
endif
OPENDBC_PATH := $(shell python -c 'import opendbc; print opendbc.DBC_PATH')
DBC_SOURCES := $(wildcard $(OPENDBC_PATH)/*.dbc)
DBC_CCS := $(patsubst $(OPENDBC_PATH)/%.dbc,dbc_out/%.cc,$(DBC_SOURCES))
CWD := $(shell pwd)
.PHONY: all
all: libdbc.so
ifeq ($(UNAME_M),aarch64)
include ../common/cereal.mk
endif
# make sure cereal is built
libdbc.so:: ../../cereal/gen/cpp/log.capnp.h
../../cereal/gen/cpp/log.capnp.h:
cd ../../cereal && make
libdbc.so:: parser.cc $(DBC_CCS)
$(CXX) -fPIC -shared -o '$@' $^ \
-I. \
-I../.. \
$(CXXFLAGS) \
$(ZMQ_FLAGS) \
$(ZMQ_LIBS) \
$(CEREAL_CXXFLAGS) \
$(CEREAL_LIBS)
dbc_out/%.cc: $(OPENDBC_PATH)/%.dbc
PYTHONPATH=$(PYTHONPATH):$(CWD)/../../pyextra ./process_dbc.py '$<' '$@'
.PHONY: clean
clean:
rm -rf libdbc.so*
rm -f dbc_out/*.cc

2
selfdrive/can/dbc_out/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.cc

View File

@@ -0,0 +1,51 @@
#include <cstdint>
#include "parser_common.h"
namespace {
{% for address, msg_name, sigs in msgs %}
const Signal sigs_{{address}}[] = {
{% for sig in sigs %}
{
{% set b1 = (sig.start_bit//8)*8 + (-sig.start_bit-1) % 8 %}
.name = "{{sig.name}}",
.b1 = {{b1}},
.b2 = {{sig.size}},
.bo = {{64 - (b1 + sig.size)}},
.is_signed = {{"true" if sig.is_signed else "false"}},
.factor = {{sig.factor}},
.offset = {{sig.offset}},
{% if checksum_type == "honda" and sig.name == "CHECKSUM" %}
.type = SignalType::HONDA_CHECKSUM,
{% elif checksum_type == "honda" and sig.name == "COUNTER" %}
.type = SignalType::HONDA_COUNTER,
{% else %}
.type = SignalType::DEFAULT,
{% endif %}
},
{% endfor %}
};
{% endfor %}
const Msg msgs[] = {
{% for address, msg_name, sigs in msgs %}
{% set address_hex = "0x%X" % address %}
{
.name = "{{msg_name}}",
.address = {{address_hex}},
.num_sigs = ARRAYSIZE(sigs_{{address}}),
.sigs = sigs_{{address}},
},
{% endfor %}
};
}
const DBC {{dbc.name}} = {
.name = "{{dbc.name}}",
.num_msgs = ARRAYSIZE(msgs),
.msgs = msgs,
};
dbc_init({{dbc.name}})

441
selfdrive/can/parser.cc Normal file
View File

@@ -0,0 +1,441 @@
#include <cstdio>
#include <cstdint>
#include <cassert>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <zmq.h>
#include <capnp/serialize.h>
#include "cereal/gen/cpp/log.capnp.h"
#include "parser_common.h"
#define DEBUG(...)
// #define DEBUG printf
#define INFO printf
#define MAX_BAD_COUNTER 5
namespace {
uint64_t read_u64_be(const uint8_t* v) {
return (((uint64_t)v[0] << 56)
| ((uint64_t)v[1] << 48)
| ((uint64_t)v[2] << 40)
| ((uint64_t)v[3] << 32)
| ((uint64_t)v[4] << 24)
| ((uint64_t)v[5] << 16)
| ((uint64_t)v[6] << 8)
| (uint64_t)v[7]);
}
std::vector<const DBC*> g_dbc;
bool honda_checksum(int address, uint64_t d, int l) {
int target = (d >> l) & 0xF;
DEBUG("check checksum %16lx %d", d, l);
// remove checksum from calculation
d &= ~(0xFLL << l);
int s = 0;
while (address > 0) { s += (address & 0xF); address >>= 4; }
while (d > 0) { s += (d & 0xF); d >>= 4; }
s = 8-s;
s &= 0xF;
DEBUG(" %d = %d\n", target, s);
return target == s;
}
struct MessageState {
uint32_t address;
std::vector<Signal> parse_sigs;
std::vector<double> vals;
uint64_t seen;
uint64_t check_threshold;
uint8_t counter;
uint8_t counter_fail;
bool parse(uint64_t sec, uint64_t dat) {
for (int i=0; i < parse_sigs.size(); i++) {
auto& sig = parse_sigs[i];
int64_t tmp = (dat >> sig.bo) & ((1 << sig.b2)-1);
if (sig.is_signed) {
tmp -= (tmp >> (sig.b2-1)) ? (1<<sig.b2) : 0; //signed
}
DEBUG("parse %X %s -> %ld\n", address, sig.name, tmp);
if (sig.type == SignalType::HONDA_CHECKSUM) {
if (!honda_checksum(address, dat, sig.bo)) {
INFO("%X CHECKSUM FAIL\n", address);
return false;
}
} else if (sig.type == SignalType::HONDA_COUNTER) {
if (!honda_update_counter(tmp)) {
return false;
}
}
vals[i] = tmp * sig.factor + sig.offset;
}
seen = sec;
return true;
}
bool honda_update_counter(int64_t v) {
uint8_t old_counter = counter;
counter = v;
if (((old_counter+1) & 3) != v) {
counter_fail += 1;
if (counter_fail > 1) {
INFO("%X COUNTER FAIL %d -- %d vs %d\n", address, counter_fail, old_counter, (int)v);
}
if (counter_fail >= MAX_BAD_COUNTER) {
return false;
}
} else if (counter_fail > 0) {
counter_fail--;
}
return true;
}
};
class CANParser {
public:
CANParser(int abus, const std::string& dbc_name,
const std::vector<MessageParseOptions> &options,
const std::vector<SignalParseOptions> &sigoptions)
: bus(abus) {
// connect to can on 8006
context = zmq_ctx_new();
subscriber = zmq_socket(context, ZMQ_SUB);
zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
zmq_connect(subscriber, "tcp://127.0.0.1:8006");
for (auto dbci : g_dbc) {
if (dbci->name == dbc_name) {
dbc = dbci;
break;
}
}
assert(dbc);
for (auto &op : options) {
MessageState state = {
.address = op.address,
// .check_frequency = op.check_frequency,
};
// msg is not valid if a message isn't received for 10 consecutive steps
if (op.check_frequency > 0) {
state.check_threshold = (1000000000ULL / op.check_frequency) * 10;
}
const Msg* msg = NULL;
for (int i=0; i<dbc->num_msgs; i++) {
if (dbc->msgs[i].address == op.address) {
msg = &dbc->msgs[i];
break;
}
}
if (!msg) {
fprintf(stderr, "CANParser: could not find message 0x%X in dnc %s\n", op.address, dbc_name.c_str());
assert(false);
}
// track checksums and for this message
for (int i=0; i<msg->num_sigs; i++) {
const Signal *sig = &msg->sigs[i];
if (sig->type == HONDA_CHECKSUM
|| sig->type == HONDA_COUNTER) {
state.parse_sigs.push_back(*sig);
state.vals.push_back(0);
}
}
// track requested signals for this message
for (auto &sigop : sigoptions) {
if (sigop.address != op.address) continue;
for (int i=0; i<msg->num_sigs; i++) {
const Signal *sig = &msg->sigs[i];
if (strcmp(sig->name, sigop.name) == 0
&& sig->type != HONDA_CHECKSUM
&& sig->type != HONDA_COUNTER) {
state.parse_sigs.push_back(*sig);
state.vals.push_back(sigop.default_value);
break;
}
}
}
message_states[state.address] = state;
}
}
void UpdateCans(uint64_t sec, const capnp::List<cereal::CanData>::Reader& cans) {
int msg_count = cans.size();
DEBUG("got %d messages\n", msg_count);
// parse the messages
for (int i = 0; i < msg_count; i++) {
auto cmsg = cans[i];
if (cmsg.getSrc() != bus) {
// DEBUG("skip %d: wrong bus\n", cmsg.getAddress());
continue;
}
auto state_it = message_states.find(cmsg.getAddress());
if (state_it == message_states.end()) {
// DEBUG("skip %d: not specified\n", cmsg.getAddress());
continue;
}
if (cmsg.getDat().size() > 8) continue; //shouldnt ever happen
uint8_t dat[8] = {0};
memcpy(dat, cmsg.getDat().begin(), cmsg.getDat().size());
uint64_t p = read_u64_be(dat);
DEBUG(" proc %X: %lx\n", cmsg.getAddress(), p);
state_it->second.parse(sec, p);
}
}
void UpdateValid(uint64_t sec) {
can_valid = true;
for (auto &kv : message_states) {
auto &state = kv.second;
if (state.check_threshold > 0 && (sec - state.seen) > state.check_threshold) {
if (state.seen > 0) {
INFO("%X TIMEOUT\n", state.address);
}
can_valid = false;
}
}
}
void update(uint64_t sec, bool wait) {
int err;
// recv from can
zmq_msg_t msg;
zmq_msg_init(&msg);
// multiple recv is fine
bool first = wait;
while (1) {
if (first) {
err = zmq_msg_recv(&msg, subscriber, 0);
first = false;
} else {
err = zmq_msg_recv(&msg, subscriber, ZMQ_DONTWAIT);
}
if (err < 0) break;
// format for board, make copy due to alignment issues, will be freed on out of scope
auto amsg = kj::heapArray<capnp::word>((zmq_msg_size(&msg) / sizeof(capnp::word)) + 1);
memcpy(amsg.begin(), zmq_msg_data(&msg), zmq_msg_size(&msg));
// extract the messages
capnp::FlatArrayMessageReader cmsg(amsg);
cereal::Event::Reader event = cmsg.getRoot<cereal::Event>();
auto cans = event.getCan();
UpdateCans(sec, cans);
}
UpdateValid(sec);
}
std::vector<SignalValue> query(uint64_t sec) {
std::vector<SignalValue> ret;
for (auto &kv : message_states) {
auto &state = kv.second;
if (sec != 0 && state.seen != sec) continue;
for (int i=0; i<state.parse_sigs.size(); i++) {
const Signal &sig = state.parse_sigs[i];
ret.push_back((SignalValue){
.address = state.address,
.name = sig.name,
.value = state.vals[i],
});
}
}
return ret;
}
bool can_valid = false;
private:
const int bus;
// zmq vars
void *context = NULL;
void *subscriber = NULL;
const DBC *dbc = NULL;
std::unordered_map<uint32_t, MessageState> message_states;
};
}
void dbc_register(const DBC* dbc) {
g_dbc.push_back(dbc);
}
extern "C" {
void* can_init(int bus, const char* dbc_name,
size_t num_message_options, const MessageParseOptions* message_options,
size_t num_signal_options, const SignalParseOptions* signal_options) {
CANParser* ret = new CANParser(bus, std::string(dbc_name),
(message_options ? std::vector<MessageParseOptions>(message_options, message_options+num_message_options)
: std::vector<MessageParseOptions>{}),
(signal_options ? std::vector<SignalParseOptions>(signal_options, signal_options+num_signal_options)
: std::vector<SignalParseOptions>{}));
return (void*)ret;
}
void can_update(void* can, uint64_t sec, bool wait) {
CANParser* cp = (CANParser*)can;
cp->update(sec, wait);
}
size_t can_query(void* can, uint64_t sec, bool *out_can_valid, size_t out_values_size, SignalValue* out_values) {
CANParser* cp = (CANParser*)can;
if (out_can_valid) {
*out_can_valid = cp->can_valid;
}
const std::vector<SignalValue> values = cp->query(sec);
if (out_values) {
std::copy(values.begin(), values.begin()+std::min(out_values_size, values.size()), out_values);
}
return values.size();
};
}
#ifdef TEST
int main(int argc, char** argv) {
CANParser cp(0, "honda_civic_touring_2016_can",
std::vector<MessageParseOptions>{
// address, check_frequency
{0x14a, 100},
{0x158, 100},
{0x17c, 100},
{0x191, 100},
{0x1a4, 50},
{0x326, 10},
{0x1b0, 50},
{0x1d0, 50},
{0x305, 10},
{0x324, 10},
{0x405, 3},
{0x18f, 0},
{0x130, 0},
{0x296, 0},
{0x30c, 0},
},
std::vector<SignalParseOptions>{
// sig_name, sig_address, default
{0x158, "XMISSION_SPEED", 0},
{0x1d0, "WHEEL_SPEED_FL", 0},
{0x1d0, "WHEEL_SPEED_FR", 0},
{0x1d0, "WHEEL_SPEED_RL", 0},
{0x14a, "STEER_ANGLE", 0},
{0x18f, "STEER_TORQUE_SENSOR", 0},
{0x191, "GEAR", 0},
{0x1b0, "WHEELS_MOVING", 1},
{0x405, "DOOR_OPEN_FL", 1},
{0x405, "DOOR_OPEN_FR", 1},
{0x405, "DOOR_OPEN_RL", 1},
{0x405, "DOOR_OPEN_RR", 1},
{0x324, "CRUISE_SPEED_PCM", 0},
{0x305, "SEATBELT_DRIVER_LAMP", 1},
{0x305, "SEATBELT_DRIVER_LATCHED", 0},
{0x17c, "BRAKE_PRESSED", 0},
{0x130, "CAR_GAS", 0},
{0x296, "CRUISE_BUTTONS", 0},
{0x1a4, "ESP_DISABLED", 1},
{0x30c, "HUD_LEAD", 0},
{0x1a4, "USER_BRAKE", 0},
{0x18f, "STEER_STATUS", 5},
{0x1d0, "WHEEL_SPEED_RR", 0},
{0x1b0, "BRAKE_ERROR_1", 1},
{0x1b0, "BRAKE_ERROR_2", 1},
{0x191, "GEAR_SHIFTER", 0},
{0x326, "MAIN_ON", 0},
{0x17c, "ACC_STATUS", 0},
{0x17c, "PEDAL_GAS", 0},
{0x296, "CRUISE_SETTING", 0},
{0x326, "LEFT_BLINKER", 0},
{0x326, "RIGHT_BLINKER", 0},
{0x324, "COUNTER", 0},
{0x17c, "ENGINE_RPM", 0},
});
const std::string log_fn = "dats.bin";
int log_fd = open(log_fn.c_str(), O_RDONLY, 0);
assert(log_fd >= 0);
off_t log_size = lseek(log_fd, 0, SEEK_END);
lseek(log_fd, 0, SEEK_SET);
void* log_data = mmap(NULL, log_size, PROT_READ, MAP_PRIVATE, log_fd, 0);
assert(log_data);
auto words = kj::arrayPtr((const capnp::word*)log_data, log_size/sizeof(capnp::word));
while (words.size() > 0) {
capnp::FlatArrayMessageReader reader(words);
auto evt = reader.getRoot<cereal::Event>();
auto cans = evt.getCan();
cp.UpdateCans(0, cans);
words = kj::arrayPtr(reader.getEnd(), words.end());
}
munmap(log_data, log_size);
close(log_fd);
return 0;
}
#endif

166
selfdrive/can/parser.py Normal file
View File

@@ -0,0 +1,166 @@
import os
import time
import subprocess
from collections import defaultdict
from cffi import FFI
can_dir = os.path.dirname(os.path.abspath(__file__))
libdbc_fn = os.path.join(can_dir, "libdbc.so")
subprocess.check_output(["make"], cwd=can_dir)
ffi = FFI()
ffi.cdef("""
typedef struct SignalParseOptions {
uint32_t address;
const char* name;
double default_value;
} SignalParseOptions;
typedef struct MessageParseOptions {
uint32_t address;
int check_frequency;
} MessageParseOptions;
typedef struct SignalValue {
uint32_t address;
const char* name;
double value;
} SignalValue;
void* can_init(int bus, const char* dbc_name,
size_t num_message_options, const MessageParseOptions* message_options,
size_t num_signal_options, const SignalParseOptions* signal_options);
void can_update(void* can, uint64_t sec, bool wait);
size_t can_query(void* can, uint64_t sec, bool *out_can_valid, size_t out_values_size, SignalValue* out_values);
""")
libdbc = ffi.dlopen(libdbc_fn)
class CANParser(object):
def __init__(self, dbc_name, signals, checks=[], bus=0):
self.can_valid = True
self.vl = defaultdict(dict)
sig_names = dict((name, ffi.new("char[]", name)) for name, _, _ in signals)
signal_options_c = ffi.new("SignalParseOptions[]", [
{
'address': sig_address,
'name': sig_names[sig_name],
'default_value': sig_default,
} for sig_name, sig_address, sig_default in signals])
message_options = dict((address, 0) for _, address, _ in signals)
message_options.update(dict(checks))
message_options_c = ffi.new("MessageParseOptions[]", [
{
'address': address,
'check_frequency': freq,
} for address, freq in message_options.iteritems()])
self.can = libdbc.can_init(bus, dbc_name, len(message_options_c), message_options_c,
len(signal_options_c), signal_options_c)
self.p_can_valid = ffi.new("bool*")
value_count = libdbc.can_query(self.can, 0, self.p_can_valid, 0, ffi.NULL)
self.can_values = ffi.new("SignalValue[%d]" % value_count)
self.update_vl(0)
# print "==="
def update_vl(self, sec):
can_values_len = libdbc.can_query(self.can, sec, self.p_can_valid, len(self.can_values), self.can_values)
assert can_values_len <= len(self.can_values)
self.can_valid = self.p_can_valid[0]
# print can_values_len
ret = set()
for i in xrange(can_values_len):
cv = self.can_values[i]
address = cv.address
# print hex(cv.address), ffi.string(cv.name)
self.vl[address][ffi.string(cv.name)] = cv.value
ret.add(address)
return ret
def update(self, sec, wait):
libdbc.can_update(self.can, sec, wait)
return self.update_vl(sec)
if __name__ == "__main__":
from common.realtime import sec_since_boot
radar_messages = range(0x430, 0x43A) + range(0x440, 0x446)
# signals = zip(['LONG_DIST'] * 16 + ['NEW_TRACK'] * 16 + ['LAT_DIST'] * 16 +
# ['REL_SPEED'] * 16, radar_messages * 4,
# [255] * 16 + [1] * 16 + [0] * 16 + [0] * 16)
# checks = zip(radar_messages, [20]*16)
# cp = CANParser("acura_ilx_2016_nidec", signals, checks, 1)
signals = [
("XMISSION_SPEED", 0x158, 0), #sig_name, sig_address, default
("WHEEL_SPEED_FL", 0x1d0, 0),
("WHEEL_SPEED_FR", 0x1d0, 0),
("WHEEL_SPEED_RL", 0x1d0, 0),
("STEER_ANGLE", 0x14a, 0),
("STEER_TORQUE_SENSOR", 0x18f, 0),
("GEAR", 0x191, 0),
("WHEELS_MOVING", 0x1b0, 1),
("DOOR_OPEN_FL", 0x405, 1),
("DOOR_OPEN_FR", 0x405, 1),
("DOOR_OPEN_RL", 0x405, 1),
("DOOR_OPEN_RR", 0x405, 1),
("CRUISE_SPEED_PCM", 0x324, 0),
("SEATBELT_DRIVER_LAMP", 0x305, 1),
("SEATBELT_DRIVER_LATCHED", 0x305, 0),
("BRAKE_PRESSED", 0x17c, 0),
("CAR_GAS", 0x130, 0),
("CRUISE_BUTTONS", 0x296, 0),
("ESP_DISABLED", 0x1a4, 1),
("HUD_LEAD", 0x30c, 0),
("USER_BRAKE", 0x1a4, 0),
("STEER_STATUS", 0x18f, 5),
("WHEEL_SPEED_RR", 0x1d0, 0),
("BRAKE_ERROR_1", 0x1b0, 1),
("BRAKE_ERROR_2", 0x1b0, 1),
("GEAR_SHIFTER", 0x191, 0),
("MAIN_ON", 0x326, 0),
("ACC_STATUS", 0x17c, 0),
("PEDAL_GAS", 0x17c, 0),
("CRUISE_SETTING", 0x296, 0),
("LEFT_BLINKER", 0x326, 0),
("RIGHT_BLINKER", 0x326, 0),
("COUNTER", 0x324, 0),
("ENGINE_RPM", 0x17C, 0)
]
checks = [
(0x14a, 100), # address, frequency
(0x158, 100),
(0x17c, 100),
(0x191, 100),
(0x1a4, 50),
(0x326, 10),
(0x1b0, 50),
(0x1d0, 50),
(0x305, 10),
(0x324, 10),
(0x405, 3),
]
cp = CANParser("honda_civic_touring_2016_can", signals, checks, 0)
print cp.vl
while True:
cp.update(int(sec_since_boot()*1e9), True)
print cp.vl
print cp.can_valid
time.sleep(0.01)

View File

@@ -0,0 +1,63 @@
#ifndef PARSER_COMMON_H
#define PARSER_COMMON_H
#include <cstddef>
#include <cstdint>
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
struct SignalParseOptions {
uint32_t address;
const char* name;
double default_value;
};
struct MessageParseOptions {
uint32_t address;
int check_frequency;
};
struct SignalValue {
uint32_t address;
const char* name;
double value;
};
enum SignalType {
DEFAULT,
HONDA_CHECKSUM,
HONDA_COUNTER,
};
struct Signal {
const char* name;
int b1, b2, bo;
bool is_signed;
double factor, offset;
SignalType type;
};
struct Msg {
const char* name;
uint32_t address;
size_t num_sigs;
const Signal *sigs;
};
struct DBC {
const char* name;
size_t num_msgs;
const Msg *msgs;
};
void dbc_register(const DBC* dbc);
#define dbc_init(dbc) \
static void __attribute__((constructor)) do_dbc_init_ ## dbc(void) { \
dbc_register(&dbc); \
}
#endif

32
selfdrive/can/process_dbc.py Executable file
View File

@@ -0,0 +1,32 @@
#!/usr/bin/env python
import os
import sys
import jinja2
import opendbc
from common.dbc import dbc
if len(sys.argv) != 3:
print "usage: %s dbc_path struct_path" % (sys.argv[0],)
sys.exit(0)
dbc_fn = sys.argv[1]
out_fn = sys.argv[2]
template_fn = os.path.join(os.path.dirname(__file__), "dbc_template.cc")
can_dbc = dbc(dbc_fn)
with open(template_fn, "r") as template_f:
template = jinja2.Template(template_f.read(), trim_blocks=True, lstrip_blocks=True)
msgs = [(address, msg_name, sorted(msg_sigs, key=lambda s: s.name not in ("COUNTER", "CHECKSUM"))) # process counter and checksums first
for address, ((msg_name, _), msg_sigs) in sorted(can_dbc.msgs.iteritems()) if msg_sigs]
checksum_type = "honda" if can_dbc.name.startswith("honda") or can_dbc.name.startswith("acura") else None
parser_code = template.render(dbc=can_dbc, checksum_type=checksum_type, msgs=msgs, len=len)
with open(out_fn, "w") as out_f:
out_f.write(parser_code)

30
selfdrive/car/__init__.py Normal file
View File

@@ -0,0 +1,30 @@
from common.fingerprints import fingerprint
from .honda.interface import CarInterface as HondaInterface
try:
from .simulator.interface import CarInterface as SimInterface
except ImportError:
SimInterface = None
try:
from .simulator2.interface import CarInterface as Sim2Interface
except ImportError:
Sim2Interface = None
interfaces = {
"HONDA CIVIC 2016 TOURING": HondaInterface,
"ACURA ILX 2016 ACURAWATCH PLUS": HondaInterface,
"HONDA ACCORD 2016 TOURING": HondaInterface,
"HONDA CR-V 2016 TOURING": HondaInterface,
"simulator": SimInterface,
"simulator2": Sim2Interface
}
def get_car(logcan, sendcan=None):
candidate, fingerprints = fingerprint(logcan)
interface_cls = interfaces[candidate]
params = interface_cls.get_params(candidate, fingerprints)
return interface_cls(params, logcan, sendcan), params

View File

View File

@@ -1,8 +1,8 @@
import os
import dbcs
import opendbc
from collections import defaultdict
from selfdrive.controls.lib.hondacan import fix
from selfdrive.car.honda.hondacan import fix
from common.realtime import sec_since_boot
from common.dbc import dbc
@@ -19,13 +19,12 @@ class CANParser(object):
# monitored.
# - frequency is the frequency at which health should be monitored.
self.msgs_ck = [check[0] for check in checks]
self.frqs = [check[1] for check in checks]
self.msgs_ck = set([check[0] for check in checks])
self.frqs = dict(checks)
self.can_valid = False # start with False CAN assumption
self.msgs_upd = [] # list of updated messages
# list of received msg we want to monitor counter and checksum for
# read dbc file
self.can_dbc = dbc(os.path.join(dbcs.DBC_PATH, dbc_f))
self.can_dbc = dbc(os.path.join(opendbc.DBC_PATH, dbc_f))
# initialize variables to initial values
self.vl = {} # signal values
self.ts = {} # time stamp recorded in log
@@ -55,26 +54,28 @@ class CANParser(object):
self._message_indices[x].append(i)
def update_can(self, can_recv):
self.msgs_upd = []
msgs_upd = []
cn_vl_max = 5 # no more than 5 wrong counter checks
self.sec_since_boot_cached = sec_since_boot()
# we are subscribing to PID_XXX, else data from USB
for msg, ts, cdat in can_recv:
for msg, ts, cdat, _ in can_recv:
idxs = self._message_indices[msg]
if idxs:
self.msgs_upd += [msg]
msgs_upd.append(msg)
# read the entire message
out = self.can_dbc.decode([msg, 0, cdat])[1]
out = self.can_dbc.decode((msg, 0, cdat))[1]
# checksum check
self.ck[msg] = True
if "CHECKSUM" in out.keys() and msg in self.msgs_ck:
# remove checksum (half byte)
ck_portion = (''.join((cdat[:-1], '0'))).decode('hex')
ck_portion = cdat[:-1] + chr(ord(cdat[-1]) & 0xF0)
# recalculate checksum
msg_vl = fix(ck_portion, msg)
# compare recalculated vs received checksum
if msg_vl != cdat.decode('hex'):
print hex(msg), "CHECKSUM FAIL"
if msg_vl != cdat:
print "CHECKSUM FAIL: " + hex(msg)
self.ck[msg] = False
self.ok[msg] = False
# counter check
@@ -89,11 +90,12 @@ class CANParser(object):
self.cn_vl[msg] -= 1 # counter check passed
# message status is invalid if we received too many wrong counter values
if self.cn_vl[msg] >= cn_vl_max:
print "COUNTER WRONG: " + hex(msg)
self.ok[msg] = False
# update msg time stamps and counter value
self.ts[msg] = ts
self.ct[msg] = sec_since_boot()
self.ct[msg] = self.sec_since_boot_cached
self.cn[msg] = cn
self.cn_vl[msg] = min(max(self.cn_vl[msg], 0), cn_vl_max)
@@ -106,18 +108,20 @@ class CANParser(object):
sg = self._sgs[ii]
self.vl[msg][sg] = out[sg]
# for each message, check if it's too long since last time we received it
# for each message, check if it's too long since last time we received it
self._check_dead_msgs()
# assess overall can validity: if there is one relevant message invalid, then set can validity flag to False
self.can_valid = True
if False in self.ok.values():
print "CAN INVALID!"
#print "CAN INVALID!"
self.can_valid = False
return msgs_upd
def _check_dead_msgs(self):
### input:
## simple stuff for now: msg is not valid if a message isn't received for 10 consecutive steps
for msg in set(self._msgs):
if msg in self.msgs_ck and sec_since_boot() - self.ct[msg] > 10./self.frqs[self.msgs_ck.index(msg)]:
if msg in self.msgs_ck and self.sec_since_boot_cached - self.ct[msg] > 10./self.frqs[msg]:
self.ok[msg] = False

View File

@@ -1,12 +1,74 @@
from collections import namedtuple
import common.numpy_fast as np
import selfdrive.controls.lib.hondacan as hondacan
from common.numpy_fast import clip, interp
from common.realtime import sec_since_boot
from selfdrive.config import CruiseButtons
from selfdrive.boardd.boardd import can_list_to_can_capnp
from selfdrive.controls.lib.alert_database import process_hud_alert
from selfdrive.controls.lib.drive_helpers import actuator_hystereses, rate_limit
from selfdrive.controls.lib.drive_helpers import rate_limit
from . import hondacan
def actuator_hystereses(final_brake, braking, brake_steady, v_ego, civic):
# hyst params... TODO: move these to VehicleParams
brake_hyst_on = 0.055 if civic else 0.1 # to activate brakes exceed this value
brake_hyst_off = 0.005 # to deactivate brakes below this value
brake_hyst_gap = 0.01 # don't change brake command for small ocilalitons within this value
#*** histeresys logic to avoid brake blinking. go above 0.1 to trigger
if (final_brake < brake_hyst_on and not braking) or final_brake < brake_hyst_off:
final_brake = 0.
braking = final_brake > 0.
# for small brake oscillations within brake_hyst_gap, don't change the brake command
if final_brake == 0.:
brake_steady = 0.
elif final_brake > brake_steady + brake_hyst_gap:
brake_steady = final_brake - brake_hyst_gap
elif final_brake < brake_steady - brake_hyst_gap:
brake_steady = final_brake + brake_hyst_gap
final_brake = brake_steady
if not civic:
brake_on_offset_v = [.25, .15] # min brake command on brake activation. below this no decel is perceived
brake_on_offset_bp = [15., 30.] # offset changes VS speed to not have too abrupt decels at high speeds
# offset the brake command for threshold in the brake system. no brake torque perceived below it
brake_on_offset = interp(v_ego, brake_on_offset_bp, brake_on_offset_v)
brake_offset = brake_on_offset - brake_hyst_on
if final_brake > 0.0:
final_brake += brake_offset
return final_brake, braking, brake_steady
class AH:
#[alert_idx, value]
# See dbc files for info on values"
NONE = [0, 0]
FCW = [1, 0x8]
STEER = [2, 1]
BRAKE_PRESSED = [3, 10]
GEAR_NOT_D = [4, 6]
SEATBELT = [5, 5]
SPEED_TOO_HIGH = [6, 8]
def process_hud_alert(hud_alert):
# initialize to no alert
fcw_display = 0
steer_required = 0
acc_alert = 0
if hud_alert == AH.NONE: # no alert
pass
elif hud_alert == AH.FCW: # FCW
fcw_display = hud_alert[1]
elif hud_alert == AH.STEER: # STEER
steer_required = hud_alert[1]
else: # any other ACC alert
acc_alert = hud_alert[1]
return fcw_display, steer_required, acc_alert
HUDData = namedtuple("HUDData",
["pcm_accel", "v_cruise", "X2", "car", "X4", "X5",
@@ -14,18 +76,23 @@ HUDData = namedtuple("HUDData",
class CarController(object):
def __init__(self):
self.controls_allowed = False
self.mismatch_start, self.pcm_mismatch_start = 0, 0
self.braking = False
self.brake_steady = 0.
self.final_brake_last = 0.
# redundant safety check with the board
self.controls_allowed = False
def update(self, sendcan, enabled, CS, frame, final_gas, final_brake, final_steer, \
pcm_speed, pcm_override, pcm_cancel_cmd, pcm_accel, \
hud_v_cruise, hud_show_lanes, hud_show_car, hud_alert, \
snd_beep, snd_chime):
""" Controls thread """
# TODO: Make the accord work.
if CS.accord:
return
# *** apply brake hysteresis ***
final_brake, self.braking, self.brake_steady = actuator_hystereses(final_brake, self.braking, self.brake_steady, CS.v_ego, CS.civic)
@@ -61,9 +128,9 @@ class CarController(object):
#print chime, alert_id, hud_alert
fcw_display, steer_required, acc_alert = process_hud_alert(hud_alert)
hud = HUDData(pcm_accel, hud_v_cruise, 0x41, hud_car,
hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), 0x01, hud_car,
0xc1, 0x41, hud_lanes + steer_required,
snd_beep, 0x48, (snd_chime << 5) + fcw_display, acc_alert)
int(snd_beep), 0x48, (snd_chime << 5) + fcw_display, acc_alert)
if not all(isinstance(x, int) and 0 <= x < 256 for x in hud):
print "INVALID HUD", hud
@@ -71,67 +138,55 @@ class CarController(object):
# **** process the car messages ****
user_brake_ctrl = CS.user_brake/0.015625 # FIXME: factor needed to convert to old scale
# *** compute control surfaces ***
tt = sec_since_boot()
GAS_MAX = 1004
BRAKE_MAX = 1024/4
#STEER_MAX = 0xF00 if not CS.torque_mod else 0xF00/4 # ilx has 8x steering torque limit, used as a 2x
STEER_MAX = 0xF00 # ilx has 8x steering torque limit, used as a 2x
if CS.civic:
STEER_MAX = 0x1000
elif CS.crv:
STEER_MAX = 0x300 # CR-V only uses 12-bits and requires a lower value
else:
STEER_MAX = 0xF00
GAS_OFFSET = 328
# steer torque is converted back to CAN reference (positive when steering right)
apply_gas = int(np.clip(final_gas*GAS_MAX, 0, GAS_MAX-1))
apply_brake = int(np.clip(final_brake*BRAKE_MAX, 0, BRAKE_MAX-1))
apply_steer = int(np.clip(-final_steer*STEER_MAX, -STEER_MAX, STEER_MAX))
apply_gas = int(clip(final_gas*GAS_MAX, 0, GAS_MAX-1))
apply_brake = int(clip(final_brake*BRAKE_MAX, 0, BRAKE_MAX-1))
apply_steer = int(clip(-final_steer*STEER_MAX, -STEER_MAX, STEER_MAX))
# no gas if you are hitting the brake or the user is
if apply_gas > 0 and (apply_brake != 0 or user_brake_ctrl > 10):
print "CANCELLING GAS", apply_brake, user_brake_ctrl
if apply_gas > 0 and (apply_brake != 0 or CS.brake_pressed):
print "CANCELLING GAS", apply_brake
apply_gas = 0
# no computer brake if the user is hitting the gas
# if the computer is trying to brake, it can't be hitting the gas
# TODO: car_gas can override brakes without canceling... this is bad
# no computer brake if the gas is being pressed
if CS.car_gas > 0 and apply_brake != 0:
print "CANCELLING BRAKE"
apply_brake = 0
# any other cp.vl[0x18F]['STEER_STATUS'] is common and can happen during user override. sending 0 torque to avoid EPS sending error 5
if CS.steer_not_allowed:
print "STEER ALERT, TORQUE INHIBITED"
apply_steer = 0
# *** entry into controls state ***
if (CS.prev_cruise_buttons == CruiseButtons.DECEL_SET or CS.prev_cruise_buttons == CruiseButtons.RES_ACCEL) and \
CS.cruise_buttons == 0 and not self.controls_allowed:
print "CONTROLS ARE LIVE"
self.controls_allowed = True
# to avoid race conditions, check if control has been disabled for at least 0.2s
# keep resetting start timer if mismatch isn't true
if not (self.controls_allowed and not enabled):
self.mismatch_start = tt
# to avoid race conditions, check if control is disabled but pcm control is on for at least 0.2s
if not (not self.controls_allowed and CS.pcm_acc_status):
self.pcm_mismatch_start = tt
# something is very wrong, since pcm control is active but controls should not be allowed; TODO: send pcm fault cmd?
if (tt - self.pcm_mismatch_start) > 0.2:
pcm_cancel_cmd = True
# TODO: clean up gear condition, ideally only D (and P for debug) shall be valid gears
# *** exit from controls state on cancel, gas, or brake ***
if (CS.cruise_buttons == CruiseButtons.CANCEL or CS.brake_pressed or
CS.user_gas_pressed or (tt - self.mismatch_start) > 0.2 or
not CS.main_on or not CS.gear_shifter_valid or
(CS.pedal_gas > 0 and CS.brake_only)) and self.controls_allowed:
CS.user_gas_pressed or (CS.pedal_gas > 0 and CS.brake_only)) and self.controls_allowed:
print "CONTROLS ARE DEAD"
self.controls_allowed = False
# 5 is a permanent fault, no torque request will be fullfilled
# *** controls fail on steer error, brake error, or invalid can ***
if CS.steer_error:
print "STEER ERROR"
self.controls_allowed = False
# any other cp.vl[0x18F]['STEER_STATUS'] is common and can happen during user override. sending 0 torque to avoid EPS sending error 5
elif CS.steer_not_allowed:
print "STEER ALERT, TORQUE INHIBITED"
apply_steer = 0
if CS.brake_error:
print "BRAKE ERROR"
self.controls_allowed = False
@@ -140,19 +195,16 @@ class CarController(object):
print "CAN INVALID"
self.controls_allowed = False
if not self.controls_allowed:
apply_steer = 0
apply_gas = 0
apply_brake = 0
pcm_speed = 0 # make sure you send 0 target speed to pcm
#pcm_cancel_cmd = 1 # prevent pcm control from turning on. FIXME: we can't just do this
# Send CAN commands.
can_sends = []
# Send steering command.
idx = frame % 4
can_sends.append(hondacan.create_steering_control(apply_steer, idx))
if CS.accord:
idx = frame % 2
can_sends.append(hondacan.create_accord_steering_control(apply_steer, idx))
else:
idx = frame % 4
can_sends.extend(hondacan.create_steering_control(apply_steer, CS.crv, idx))
# Send gas and brake commands.
if (frame % 2) == 0:
@@ -160,9 +212,8 @@ class CarController(object):
can_sends.append(
hondacan.create_brake_command(apply_brake, pcm_override,
pcm_cancel_cmd, hud.chime, idx))
if not CS.brake_only:
# send exactly zero if apply_gas is zero. Interceptor will send the max between read value and apply_gas.
# send exactly zero if apply_gas is zero. Interceptor will send the max between read value and apply_gas.
# This prevents unexpected pedal range rescaling
gas_amount = (apply_gas + GAS_OFFSET) * (apply_gas > 0)
can_sends.append(hondacan.create_gas_command(gas_amount, idx))
@@ -170,16 +221,16 @@ class CarController(object):
# Send dashboard UI commands.
if (frame % 10) == 0:
idx = (frame/10) % 4
can_sends.extend(hondacan.create_ui_commands(pcm_speed, hud, CS.civic, idx))
can_sends.extend(hondacan.create_ui_commands(pcm_speed, hud, CS.civic, CS.accord, CS.crv, idx))
# radar at 20Hz, but these msgs need to be sent at 50Hz on ilx (seems like an Acura bug)
if CS.civic:
if CS.civic or CS.accord or CS.crv:
radar_send_step = 5
else:
radar_send_step = 2
if (frame % radar_send_step) == 0:
idx = (frame/radar_send_step) % 4
can_sends.extend(hondacan.create_radar_commands(CS.v_ego, CS.civic, idx))
can_sends.extend(hondacan.create_radar_commands(CS.v_ego, CS.civic, CS.accord, CS.crv, idx))
sendcan.send(can_list_to_can_capnp(can_sends).to_bytes())
sendcan.send(can_list_to_can_capnp(can_sends, msgtype='sendcan').to_bytes())

View File

@@ -0,0 +1,389 @@
import os
import time
import common.numpy_fast as np
from common.realtime import sec_since_boot
import selfdrive.messaging as messaging
from selfdrive.car.honda.can_parser import CANParser
from selfdrive.can.parser import CANParser as CANParserC
NEW_CAN = os.getenv("OLD_CAN") is None
def get_can_parser(CP):
# this function generates lists for signal, messages and initial values
if CP.carFingerprint == "HONDA CIVIC 2016 TOURING":
dbc_f = 'honda_civic_touring_2016_can.dbc'
signals = [
# sig_name, sig_address, default
("XMISSION_SPEED", 0x158, 0),
("WHEEL_SPEED_FL", 0x1d0, 0),
("WHEEL_SPEED_FR", 0x1d0, 0),
("WHEEL_SPEED_RL", 0x1d0, 0),
("STEER_ANGLE", 0x14a, 0),
("STEER_TORQUE_SENSOR", 0x18f, 0),
("GEAR", 0x191, 0),
("WHEELS_MOVING", 0x1b0, 1),
("DOOR_OPEN_FL", 0x405, 1),
("DOOR_OPEN_FR", 0x405, 1),
("DOOR_OPEN_RL", 0x405, 1),
("DOOR_OPEN_RR", 0x405, 1),
("CRUISE_SPEED_PCM", 0x324, 0),
("SEATBELT_DRIVER_LAMP", 0x305, 1),
("SEATBELT_DRIVER_LATCHED", 0x305, 0),
("BRAKE_PRESSED", 0x17c, 0),
("CAR_GAS", 0x130, 0),
("CRUISE_BUTTONS", 0x296, 0),
("ESP_DISABLED", 0x1a4, 1),
("HUD_LEAD", 0x30c, 0),
("USER_BRAKE", 0x1a4, 0),
("STEER_STATUS", 0x18f, 5),
("WHEEL_SPEED_RR", 0x1d0, 0),
("BRAKE_ERROR_1", 0x1b0, 1),
("BRAKE_ERROR_2", 0x1b0, 1),
("GEAR_SHIFTER", 0x191, 0),
("MAIN_ON", 0x326, 0),
("ACC_STATUS", 0x17c, 0),
("PEDAL_GAS", 0x17c, 0),
("CRUISE_SETTING", 0x296, 0),
("LEFT_BLINKER", 0x326, 0),
("RIGHT_BLINKER", 0x326, 0),
("COUNTER", 0x324, 0),
("ENGINE_RPM", 0x17C, 0)
]
checks = [
# address, frequency
(0x14a, 100),
(0x158, 100),
(0x17c, 100),
(0x191, 100),
(0x1a4, 50),
(0x326, 10),
(0x1b0, 50),
(0x1d0, 50),
(0x305, 10),
(0x324, 10),
(0x405, 3),
]
elif CP.carFingerprint == "ACURA ILX 2016 ACURAWATCH PLUS":
dbc_f = 'acura_ilx_2016_can.dbc'
signals = [
("XMISSION_SPEED", 0x158, 0),
("WHEEL_SPEED_FL", 0x1d0, 0),
("WHEEL_SPEED_FR", 0x1d0, 0),
("WHEEL_SPEED_RL", 0x1d0, 0),
("STEER_ANGLE", 0x156, 0),
("STEER_TORQUE_SENSOR", 0x18f, 0),
("GEAR", 0x1a3, 0),
("WHEELS_MOVING", 0x1b0, 1),
("DOOR_OPEN_FL", 0x405, 1),
("DOOR_OPEN_FR", 0x405, 1),
("DOOR_OPEN_RL", 0x405, 1),
("DOOR_OPEN_RR", 0x405, 1),
("CRUISE_SPEED_PCM", 0x324, 0),
("SEATBELT_DRIVER_LAMP", 0x305, 1),
("SEATBELT_DRIVER_LATCHED", 0x305, 0),
("BRAKE_PRESSED", 0x17c, 0),
("CAR_GAS", 0x130, 0),
("CRUISE_BUTTONS", 0x1a6, 0),
("ESP_DISABLED", 0x1a4, 1),
("HUD_LEAD", 0x30c, 0),
("USER_BRAKE", 0x1a4, 0),
("STEER_STATUS", 0x18f, 5),
("WHEEL_SPEED_RR", 0x1d0, 0),
("BRAKE_ERROR_1", 0x1b0, 1),
("BRAKE_ERROR_2", 0x1b0, 1),
("GEAR_SHIFTER", 0x1a3, 0),
("MAIN_ON", 0x1a6, 0),
("ACC_STATUS", 0x17c, 0),
("PEDAL_GAS", 0x17c, 0),
("CRUISE_SETTING", 0x1a6, 0),
("LEFT_BLINKER", 0x294, 0),
("RIGHT_BLINKER", 0x294, 0),
("COUNTER", 0x324, 0),
("ENGINE_RPM", 0x17C, 0)
]
checks = [
(0x156, 100),
(0x158, 100),
(0x17c, 100),
(0x1a3, 50),
(0x1a4, 50),
(0x1a6, 50),
(0x1b0, 50),
(0x1d0, 50),
(0x305, 10),
(0x324, 10),
(0x405, 3),
]
elif CP.carFingerprint == "HONDA ACCORD 2016 TOURING":
dbc_f = 'honda_accord_touring_2016_can.dbc'
signals = [
("XMISSION_SPEED", 0x158, 0),
("WHEEL_SPEED_FL", 0x1d0, 0),
("WHEEL_SPEED_FR", 0x1d0, 0),
("WHEEL_SPEED_RL", 0x1d0, 0),
("STEER_ANGLE", 0x156, 0),
#("STEER_TORQUE_SENSOR", 0x18f, 0),
("GEAR", 0x191, 0),
("WHEELS_MOVING", 0x1b0, 1),
("DOOR_OPEN_FL", 0x405, 1),
("DOOR_OPEN_FR", 0x405, 1),
("DOOR_OPEN_RL", 0x405, 1),
("DOOR_OPEN_RR", 0x405, 1),
("CRUISE_SPEED_PCM", 0x324, 0),
("SEATBELT_DRIVER_LAMP", 0x305, 1),
("SEATBELT_DRIVER_LATCHED", 0x305, 0),
("BRAKE_PRESSED", 0x17c, 0),
#("CAR_GAS", 0x130, 0),
("PEDAL_GAS", 0x17C, 0),
("CRUISE_BUTTONS", 0x1a6, 0),
("ESP_DISABLED", 0x1a4, 1),
("HUD_LEAD", 0x30c, 0),
("USER_BRAKE", 0x1a4, 0),
#("STEER_STATUS", 0x18f, 5),
("WHEEL_SPEED_RR", 0x1d0, 0),
("BRAKE_ERROR_1", 0x1b0, 1),
("BRAKE_ERROR_2", 0x1b0, 1),
("GEAR_SHIFTER", 0x191, 0),
("MAIN_ON", 0x1a6, 0),
("ACC_STATUS", 0x17c, 0),
("PEDAL_GAS", 0x17c, 0),
("CRUISE_SETTING", 0x1a6, 0),
("LEFT_BLINKER", 0x294, 0),
("RIGHT_BLINKER", 0x294, 0),
("COUNTER", 0x324, 0),
("ENGINE_RPM", 0x17C, 0)
]
checks = [
(0x156, 100),
(0x158, 100),
(0x17c, 100),
#(0x1a3, 50),
(0x1a4, 50),
(0x1a6, 50),
(0x1b0, 50),
(0x1d0, 50),
(0x305, 10),
(0x324, 10),
(0x405, 3),
]
elif CP.carFingerprint == "HONDA CR-V 2016 TOURING":
dbc_f = 'honda_crv_touring_2016_can.dbc'
signals = [
("XMISSION_SPEED", 0x158, 0),
("WHEEL_SPEED_FL", 0x1d0, 0),
("WHEEL_SPEED_FR", 0x1d0, 0),
("WHEEL_SPEED_RL", 0x1d0, 0),
("STEER_ANGLE", 0x156, 0),
("STEER_TORQUE_SENSOR", 0x18f, 0),
("GEAR", 0x191, 0),
("WHEELS_MOVING", 0x1b0, 1),
("DOOR_OPEN_FL", 0x405, 1),
("DOOR_OPEN_FR", 0x405, 1),
("DOOR_OPEN_RL", 0x405, 1),
("DOOR_OPEN_RR", 0x405, 1),
("CRUISE_SPEED_PCM", 0x324, 0),
("SEATBELT_DRIVER_LAMP", 0x305, 1),
("SEATBELT_DRIVER_LATCHED", 0x305, 0),
("BRAKE_PRESSED", 0x17c, 0),
#("CAR_GAS", 0x130, 0),
("CRUISE_BUTTONS", 0x1a6, 0),
("ESP_DISABLED", 0x1a4, 1),
("HUD_LEAD", 0x30c, 0),
("USER_BRAKE", 0x1a4, 0),
("STEER_STATUS", 0x18f, 5),
("WHEEL_SPEED_RR", 0x1d0, 0),
("BRAKE_ERROR_1", 0x1b0, 1),
("BRAKE_ERROR_2", 0x1b0, 1),
("GEAR_SHIFTER", 0x191, 0),
("MAIN_ON", 0x1a6, 0),
("ACC_STATUS", 0x17c, 0),
("PEDAL_GAS", 0x17c, 0),
("CRUISE_SETTING", 0x1a6, 0),
("LEFT_BLINKER", 0x294, 0),
("RIGHT_BLINKER", 0x294, 0),
("COUNTER", 0x324, 0),
("ENGINE_RPM", 0x17C, 0)
]
checks = [
(0x156, 100),
(0x158, 100),
(0x17c, 100),
(0x191, 100),
(0x1a3, 50),
(0x1a4, 50),
(0x1a6, 50),
(0x1b0, 50),
(0x1d0, 50),
(0x305, 10),
(0x324, 10),
(0x405, 3),
]
# add gas interceptor reading if we are using it
if CP.enableGas:
signals.append(("INTERCEPTOR_GAS", 0x201, 0))
checks.append((0x201, 50))
if NEW_CAN:
return CANParserC(os.path.splitext(dbc_f)[0], signals, checks, 0)
else:
return CANParser(dbc_f, signals, checks)
class CarState(object):
def __init__(self, CP, logcan):
self.civic = False
self.accord = False
self.crv = False
if CP.carFingerprint == "HONDA CIVIC 2016 TOURING":
self.civic = True
elif CP.carFingerprint == "ACURA ILX 2016 ACURAWATCH PLUS":
self.civic = False
elif CP.carFingerprint == "HONDA ACCORD 2016 TOURING":
# fake civic
self.accord = True
elif CP.carFingerprint == "HONDA CR-V 2016 TOURING":
self.crv = True
else:
raise ValueError("unsupported car %s" % CP.carFingerprint)
self.brake_only = CP.enableCruise
self.CP = CP
# initialize can parser
self.cp = get_can_parser(CP)
self.user_gas, self.user_gas_pressed = 0., 0
self.cruise_buttons = 0
self.cruise_setting = 0
self.blinker_on = 0
self.left_blinker_on = 0
self.right_blinker_on = 0
# TODO: actually make this work
self.a_ego = 0.
def update(self, can_pub_main=None):
cp = self.cp
if NEW_CAN:
cp.update(int(sec_since_boot() * 1e9), False)
else:
cp.update_can(can_pub_main)
# copy can_valid
self.can_valid = cp.can_valid
# car params
v_weight_v = [0., 1. ] # don't trust smooth speed at low values to avoid premature zero snapping
v_weight_bp = [1., 6.] # smooth blending, below ~0.6m/s the smooth speed snaps to zero
# update prevs, update must run once per loop
self.prev_cruise_buttons = self.cruise_buttons
self.prev_cruise_setting = self.cruise_setting
self.prev_blinker_on = self.blinker_on
self.prev_left_blinker_on = self.left_blinker_on
self.prev_right_blinker_on = self.right_blinker_on
self.rpm = cp.vl[0x17C]['ENGINE_RPM']
# ******************* parse out can *******************
self.door_all_closed = not any([cp.vl[0x405]['DOOR_OPEN_FL'], cp.vl[0x405]['DOOR_OPEN_FR'],
cp.vl[0x405]['DOOR_OPEN_RL'], cp.vl[0x405]['DOOR_OPEN_RR']])
self.seatbelt = not cp.vl[0x305]['SEATBELT_DRIVER_LAMP'] and cp.vl[0x305]['SEATBELT_DRIVER_LATCHED']
# error 2 = temporary
# error 4 = temporary, hit a bump
# error 5 (permanent)
# error 6 = temporary
# error 7 (permanent)
#self.steer_error = cp.vl[0x18F]['STEER_STATUS'] in [5,7]
# whitelist instead of blacklist, safer at the expense of disengages
if self.accord:
self.steer_error = False
self.steer_not_allowed = False
else:
self.steer_error = cp.vl[0x18F]['STEER_STATUS'] not in [0,2,4,6]
self.steer_not_allowed = cp.vl[0x18F]['STEER_STATUS'] != 0
if cp.vl[0x18F]['STEER_STATUS'] != 0:
print cp.vl[0x18F]['STEER_STATUS']
self.brake_error = cp.vl[0x1B0]['BRAKE_ERROR_1'] or cp.vl[0x1B0]['BRAKE_ERROR_2']
self.esp_disabled = cp.vl[0x1A4]['ESP_DISABLED']
# calc best v_ego estimate, by averaging two opposite corners
self.v_wheel = (
cp.vl[0x1D0]['WHEEL_SPEED_FL'] + cp.vl[0x1D0]['WHEEL_SPEED_FR'] +
cp.vl[0x1D0]['WHEEL_SPEED_RL'] + cp.vl[0x1D0]['WHEEL_SPEED_RR']) / 4.
# blend in transmission speed at low speed, since it has more low speed accuracy
self.v_weight = np.interp(self.v_wheel, v_weight_bp, v_weight_v)
self.v_ego = (1. - self.v_weight) * cp.vl[0x158]['XMISSION_SPEED'] + self.v_weight * self.v_wheel
if self.CP.enableGas:
# this is a hack
self.user_gas = cp.vl[0x201]['INTERCEPTOR_GAS']
self.user_gas_pressed = self.user_gas > 0 # this works because interceptor read < 0 when pedal position is 0. Once calibrated, this will change
#print self.user_gas, self.user_gas_pressed
if self.civic:
self.gear_shifter = cp.vl[0x191]['GEAR_SHIFTER']
self.angle_steers = cp.vl[0x14A]['STEER_ANGLE']
self.gear = 0 # TODO: civic has CVT... needs rev engineering
self.cruise_setting = cp.vl[0x296]['CRUISE_SETTING']
self.cruise_buttons = cp.vl[0x296]['CRUISE_BUTTONS']
self.main_on = cp.vl[0x326]['MAIN_ON']
self.gear_shifter_valid = self.gear_shifter in [1,8] # TODO: 1/P allowed for debug
self.blinker_on = cp.vl[0x326]['LEFT_BLINKER'] or cp.vl[0x326]['RIGHT_BLINKER']
self.left_blinker_on = cp.vl[0x326]['LEFT_BLINKER']
self.right_blinker_on = cp.vl[0x326]['RIGHT_BLINKER']
elif self.accord:
self.gear_shifter = cp.vl[0x191]['GEAR_SHIFTER']
self.angle_steers = cp.vl[0x156]['STEER_ANGLE']
self.gear = 0 # TODO: accord has CVT... needs rev engineering
self.cruise_setting = cp.vl[0x1A6]['CRUISE_SETTING']
self.cruise_buttons = cp.vl[0x1A6]['CRUISE_BUTTONS']
self.main_on = cp.vl[0x1A6]['MAIN_ON']
self.gear_shifter_valid = self.gear_shifter in [1,8] # TODO: 1/P allowed for debug
self.blinker_on = cp.vl[0x294]['LEFT_BLINKER'] or cp.vl[0x294]['RIGHT_BLINKER']
self.left_blinker_on = cp.vl[0x294]['LEFT_BLINKER']
self.right_blinker_on = cp.vl[0x294]['RIGHT_BLINKER']
elif self.crv:
self.gear_shifter = cp.vl[0x191]['GEAR_SHIFTER']
self.angle_steers = cp.vl[0x156]['STEER_ANGLE']
self.gear = cp.vl[0x191]['GEAR']
self.cruise_setting = cp.vl[0x1A6]['CRUISE_SETTING']
self.cruise_buttons = cp.vl[0x1A6]['CRUISE_BUTTONS']
self.main_on = cp.vl[0x1A6]['MAIN_ON']
self.gear_shifter_valid = self.gear_shifter in [1,8] # TODO: 1/P allowed for debug
self.blinker_on = cp.vl[0x294]['LEFT_BLINKER'] or cp.vl[0x294]['RIGHT_BLINKER']
self.left_blinker_on = cp.vl[0x294]['LEFT_BLINKER']
self.right_blinker_on = cp.vl[0x294]['RIGHT_BLINKER']
else:
self.gear_shifter = cp.vl[0x1A3]['GEAR_SHIFTER']
self.angle_steers = cp.vl[0x156]['STEER_ANGLE']
self.gear = cp.vl[0x1A3]['GEAR']
self.cruise_setting = cp.vl[0x1A6]['CRUISE_SETTING']
self.cruise_buttons = cp.vl[0x1A6]['CRUISE_BUTTONS']
self.main_on = cp.vl[0x1A6]['MAIN_ON']
self.gear_shifter_valid = self.gear_shifter in [1,4] # TODO: 1/P allowed for debug
self.blinker_on = cp.vl[0x294]['LEFT_BLINKER'] or cp.vl[0x294]['RIGHT_BLINKER']
self.left_blinker_on = cp.vl[0x294]['LEFT_BLINKER']
self.right_blinker_on = cp.vl[0x294]['RIGHT_BLINKER']
if self.accord:
# on the accord, this doesn't seem to include cruise control
self.car_gas = cp.vl[0x17C]['PEDAL_GAS']
self.steer_override = False
elif self.crv:
# like accord, crv doesn't include cruise control
self.car_gas = cp.vl[0x17C]['PEDAL_GAS']
self.steer_override = abs(cp.vl[0x18F]['STEER_TORQUE_SENSOR']) > 1200
else:
self.car_gas = cp.vl[0x130]['CAR_GAS']
self.steer_override = abs(cp.vl[0x18F]['STEER_TORQUE_SENSOR']) > 1200
self.brake_pressed = cp.vl[0x17C]['BRAKE_PRESSED']
self.user_brake = cp.vl[0x1A4]['USER_BRAKE']
self.standstill = not cp.vl[0x1B0]['WHEELS_MOVING']
self.v_cruise_pcm = cp.vl[0x324]['CRUISE_SPEED_PCM']
self.pcm_acc_status = cp.vl[0x17C]['ACC_STATUS']
self.pedal_gas = cp.vl[0x17C]['PEDAL_GAS']
self.hud_lead = cp.vl[0x30C]['HUD_LEAD']
self.counter_pcm = cp.vl[0x324]['COUNTER']

View File

@@ -44,15 +44,45 @@ def create_gas_command(gas_amount, idx):
msg = struct.pack("!H", gas_amount)
return make_can_msg(0x200, msg, idx, 0)
def create_steering_control(apply_steer, idx):
"""Creates a CAN message for the Honda DBC STEERING_CONTROL."""
msg = struct.pack("!h", apply_steer) + ("\x80\x00" if apply_steer != 0 else "\x00\x00")
return make_can_msg(0xe4, msg, idx, 0)
def create_accord_steering_control(apply_steer, idx):
# TODO: doesn't work for some reason
if apply_steer == 0:
dat = [0, 0, 0x40, 0]
else:
dat = [0,0,0,0]
rp = np.clip(apply_steer/0xF, -0xFF, 0xFF)
if rp < 0:
rp += 512
dat[0] |= (rp >> 5) & 0xf
dat[1] |= (rp) & 0x1f
if idx == 1:
dat[0] |= 0x20
dat[1] |= 0x20 # always
dat[3] = -(dat[0]+dat[1]+dat[2]) & 0x7f
def create_ui_commands(pcm_speed, hud, civic, idx):
# not first byte
dat[1] |= 0x80
dat[2] |= 0x80
dat[3] |= 0x80
dat = ''.join(map(chr, dat))
return [0,0,dat,8]
def create_steering_control(apply_steer, crv, idx):
"""Creates a CAN message for the Honda DBC STEERING_CONTROL."""
commands = []
if crv:
msg_0x194 = struct.pack("!h", apply_steer << 4) + ("\x80" if apply_steer != 0 else "\x00")
commands.append(make_can_msg(0x194, msg_0x194, idx, 0))
else:
msg_0xe4 = struct.pack("!h", apply_steer) + ("\x80\x00" if apply_steer != 0 else "\x00\x00")
commands.append(make_can_msg(0xe4, msg_0xe4, idx, 0))
return commands
def create_ui_commands(pcm_speed, hud, civic, accord, crv, idx):
"""Creates an iterable of CAN messages for the UIs."""
commands = []
pcm_speed_real = np.clip(int(round(pcm_speed / 0.002763889)), 0,
pcm_speed_real = np.clip(int(round(pcm_speed / 0.002759506)), 0,
64000) # conversion factor from dbc file
msg_0x30c = struct.pack("!HBBBBB", pcm_speed_real, hud.pcm_accel,
hud.v_cruise, hud.X2, hud.car, hud.X4)
@@ -63,24 +93,35 @@ def create_ui_commands(pcm_speed, hud, civic, idx):
if civic: # 2 more msgs
msg_0x35e = chr(0) * 7
commands.append(make_can_msg(0x35e, msg_0x35e, idx, 0))
if civic or accord:
msg_0x39f = (
chr(0) * 2 + chr(hud.acc_alert) + chr(0) + chr(0xff) + chr(0x7f) + chr(0)
)
commands.append(make_can_msg(0x39f, msg_0x39f, idx, 0))
return commands
def create_radar_commands(v_ego, civic, idx):
def create_radar_commands(v_ego, civic, accord, crv, idx):
"""Creates an iterable of CAN messages for the radar system."""
commands = []
v_ego_kph = np.clip(int(round(v_ego * CV.MS_TO_KPH)), 0, 255)
speed = struct.pack('!B', v_ego_kph)
msg_0x300 = ("\xf9" + speed + "\x8a\xd0" +\
("\x20" if idx == 0 or idx == 3 else "\x00") +\
"\x00\x00")
("\x20" if idx == 0 or idx == 3 else "\x00") +\
"\x00\x00")
if civic:
msg_0x301 = "\x02\x38\x44\x32\x4f\x00\x00"
# add 8 on idx.
commands.append(make_can_msg(0x300, msg_0x300, idx + 8, 1))
elif accord:
# 0300( 768)( 69) f9008ad0100000ef
# 0301( 769)( 69) 0ed8522256000029
msg_0x301 = "\x0e\xd8\x52\x22\x56\x00\x00"
# add 0xc on idx? WTF is this?
commands.append(make_can_msg(0x300, msg_0x300, idx + 0xc, 1))
elif crv:
msg_0x301 = "\x00\x00\x50\x02\x51\x00\x00"
commands.append(make_can_msg(0x300, msg_0x300, idx, 1))
else:
msg_0x301 = "\x0f\x18\x51\x02\x5a\x00\x00"
commands.append(make_can_msg(0x300, msg_0x300, idx, 1))

296
selfdrive/car/honda/interface.py Executable file
View File

@@ -0,0 +1,296 @@
#!/usr/bin/env python
import os
import time
import common.numpy_fast as np
from selfdrive.config import Conversions as CV
from .carstate import CarState
from .carcontroller import CarController, AH
from selfdrive.boardd.boardd import can_capnp_to_can_list
from cereal import car
from selfdrive.services import service_list
import selfdrive.messaging as messaging
NEW_CAN = os.getenv("OLD_CAN") is None
# Car button codes
class CruiseButtons:
RES_ACCEL = 4
DECEL_SET = 3
CANCEL = 2
MAIN = 1
#car chimes: enumeration from dbc file. Chimes are for alerts and warnings
class CM:
MUTE = 0
SINGLE = 3
DOUBLE = 4
REPEATED = 1
CONTINUOUS = 2
#car beepss: enumeration from dbc file. Beeps are for activ and deactiv
class BP:
MUTE = 0
SINGLE = 3
TRIPLE = 2
REPEATED = 1
class CarInterface(object):
def __init__(self, CP, logcan, sendcan=None):
self.logcan = logcan
self.CP = CP
self.frame = 0
self.can_invalid_count = 0
# *** init the major players ***
self.CS = CarState(CP, self.logcan)
# sending if read only is False
if sendcan is not None:
self.sendcan = sendcan
self.CC = CarController()
if self.CS.accord:
self.accord_msg = []
@staticmethod
def get_params(candidate, fingerprint):
# pedal
brake_only = 0x201 not in fingerprint
ret = car.CarParams.new_message()
ret.carName = "honda"
ret.radarName = "nidec"
ret.carFingerprint = candidate
ret.enableSteer = True
ret.enableBrake = True
ret.enableGas = not brake_only
ret.enableCruise = brake_only
#ret.enableCruise = False
# TODO: those parameters should be platform dependent
ret.wheelBase = 2.67
ret.slipFactor = 0.0014
if candidate == "HONDA CIVIC 2016 TOURING":
ret.steerRatio = 13.0
ret.steerKp, ret.steerKi = 6.0, 1.4
elif candidate == "ACURA ILX 2016 ACURAWATCH PLUS":
ret.steerRatio = 15.3
if not brake_only:
# assuming if we have an interceptor we also have a torque mod
ret.steerKp, ret.steerKi = 3.0, 0.7
else:
ret.steerKp, ret.steerKi = 6.0, 1.4
elif candidate == "HONDA ACCORD 2016 TOURING":
ret.steerRatio = 15.3
ret.steerKp, ret.steerKi = 6.0, 1.4
elif candidate == "HONDA CR-V 2016 TOURING":
ret.steerRatio = 15.3
ret.steerKp, ret.steerKi = 3.0, 0.7
else:
raise ValueError("unsupported car %s" % candidate)
return ret
# returns a car.CarState
def update(self):
# ******************* do can recv *******************
can_pub_main = []
canMonoTimes = []
if NEW_CAN:
self.CS.update(can_pub_main)
else:
for a in messaging.drain_sock(self.logcan):
canMonoTimes.append(a.logMonoTime)
can_pub_main.extend(can_capnp_to_can_list(a.can, [0,0x80]))
if self.CS.accord:
self.accord_msg.extend(can_capnp_to_can_list(a.can, [9]))
self.accord_msg = self.accord_msg[-1:]
self.CS.update(can_pub_main)
# create message
ret = car.CarState.new_message()
# speeds
ret.vEgo = self.CS.v_ego
ret.wheelSpeeds.fl = self.CS.cp.vl[0x1D0]['WHEEL_SPEED_FL']
ret.wheelSpeeds.fr = self.CS.cp.vl[0x1D0]['WHEEL_SPEED_FR']
ret.wheelSpeeds.rl = self.CS.cp.vl[0x1D0]['WHEEL_SPEED_RL']
ret.wheelSpeeds.rr = self.CS.cp.vl[0x1D0]['WHEEL_SPEED_RR']
# gas pedal
ret.gas = self.CS.car_gas / 256.0
if not self.CP.enableGas:
ret.gasPressed = self.CS.pedal_gas > 0
else:
ret.gasPressed = self.CS.user_gas_pressed
# brake pedal
ret.brake = self.CS.user_brake
ret.brakePressed = self.CS.brake_pressed != 0
# steering wheel
# TODO: units
ret.steeringAngle = self.CS.angle_steers
if self.CS.accord:
# TODO: move this into the CAN parser
ret.steeringTorque = 0
if len(self.accord_msg) > 0:
aa = map(lambda x: ord(x)&0x7f, self.accord_msg[0][2])
if len(aa) != 5 or (-(aa[0]+aa[1]+aa[2]+aa[3]))&0x7f != aa[4]:
print "ACCORD MSG BAD LEN OR CHECKSUM!"
# TODO: throw an error here?
else:
st = ((aa[0]&0xF) << 5) + (aa[1]&0x1F)
if st >= 256:
st = -(512-st)
ret.steeringTorque = st
ret.steeringPressed = abs(ret.steeringTorque) > 20
else:
ret.steeringTorque = self.CS.cp.vl[0x18F]['STEER_TORQUE_SENSOR']
ret.steeringPressed = self.CS.steer_override
# cruise state
ret.cruiseState.enabled = self.CS.pcm_acc_status != 0
ret.cruiseState.speed = self.CS.v_cruise_pcm * CV.KPH_TO_MS
ret.cruiseState.available = bool(self.CS.main_on)
# TODO: button presses
buttonEvents = []
if self.CS.left_blinker_on != self.CS.prev_left_blinker_on:
be = car.CarState.ButtonEvent.new_message()
be.type = 'leftBlinker'
be.pressed = self.CS.left_blinker_on != 0
buttonEvents.append(be)
if self.CS.right_blinker_on != self.CS.prev_right_blinker_on:
be = car.CarState.ButtonEvent.new_message()
be.type = 'rightBlinker'
be.pressed = self.CS.right_blinker_on != 0
buttonEvents.append(be)
if self.CS.cruise_buttons != self.CS.prev_cruise_buttons:
be = car.CarState.ButtonEvent.new_message()
be.type = 'unknown'
if self.CS.cruise_buttons != 0:
be.pressed = True
but = self.CS.cruise_buttons
else:
be.pressed = False
but = self.CS.prev_cruise_buttons
if but == CruiseButtons.RES_ACCEL:
be.type = 'accelCruise'
elif but == CruiseButtons.DECEL_SET:
be.type = 'decelCruise'
elif but == CruiseButtons.CANCEL:
be.type = 'cancel'
elif but == CruiseButtons.MAIN:
be.type = 'altButton3'
buttonEvents.append(be)
if self.CS.cruise_setting != self.CS.prev_cruise_setting:
be = car.CarState.ButtonEvent.new_message()
be.type = 'unknown'
if self.CS.cruise_setting != 0:
be.pressed = True
but = self.CS.cruise_setting
else:
be.pressed = False
but = self.CS.prev_cruise_setting
if but == 1:
be.type = 'altButton1'
# TODO: more buttons?
buttonEvents.append(be)
ret.buttonEvents = buttonEvents
# errors
# TODO: I don't like the way capnp does enums
# These strings aren't checked at compile time
errors = []
if not self.CS.can_valid:
self.can_invalid_count += 1
if self.can_invalid_count >= 5:
errors.append('commIssue')
else:
self.can_invalid_count = 0
if self.CS.steer_error:
errors.append('steerUnavailable')
elif self.CS.steer_not_allowed:
errors.append('steerTempUnavailable')
if self.CS.brake_error:
errors.append('brakeUnavailable')
if not self.CS.gear_shifter_valid:
errors.append('wrongGear')
if not self.CS.door_all_closed:
errors.append('doorOpen')
if not self.CS.seatbelt:
errors.append('seatbeltNotLatched')
if self.CS.esp_disabled:
errors.append('espDisabled')
if not self.CS.main_on:
errors.append('wrongCarMode')
if self.CS.gear_shifter == 2:
errors.append('reverseGear')
ret.errors = errors
ret.canMonoTimes = canMonoTimes
# cast to reader so it can't be modified
#print ret
return ret.as_reader()
# pass in a car.CarControl
# to be called @ 100hz
def apply(self, c):
#print c
if c.hudControl.speedVisible:
hud_v_cruise = c.hudControl.setSpeed * CV.MS_TO_KPH
else:
hud_v_cruise = 255
hud_alert = {
"none": AH.NONE,
"fcw": AH.FCW,
"steerRequired": AH.STEER,
"brakePressed": AH.BRAKE_PRESSED,
"wrongGear": AH.GEAR_NOT_D,
"seatbeltUnbuckled": AH.SEATBELT,
"speedTooHigh": AH.SPEED_TOO_HIGH}[str(c.hudControl.visualAlert)]
snd_beep, snd_chime = {
"none": (BP.MUTE, CM.MUTE),
"beepSingle": (BP.SINGLE, CM.MUTE),
"beepTriple": (BP.TRIPLE, CM.MUTE),
"beepRepeated": (BP.REPEATED, CM.MUTE),
"chimeSingle": (BP.MUTE, CM.SINGLE),
"chimeDouble": (BP.MUTE, CM.DOUBLE),
"chimeRepeated": (BP.MUTE, CM.REPEATED),
"chimeContinuous": (BP.MUTE, CM.CONTINUOUS)}[str(c.hudControl.audibleAlert)]
pcm_accel = int(np.clip(c.cruiseControl.accelOverride/1.4,0,1)*0xc6)
self.CC.update(self.sendcan, c.enabled, self.CS, self.frame, \
c.gas, c.brake, c.steeringTorque, \
c.cruiseControl.speedOverride, \
c.cruiseControl.override, \
c.cruiseControl.cancel, \
pcm_accel, \
hud_v_cruise, c.hudControl.lanesVisible, \
hud_show_car = c.hudControl.leadVisible, \
hud_alert = hud_alert, \
snd_beep = snd_beep, \
snd_chime = snd_chime)
self.frame += 1
return not (c.enabled and not self.CC.controls_allowed)

View File

@@ -0,0 +1,19 @@
CEREAL_CFLAGS = -I$(PHONELIBS)/capnp-c/include
CEREAL_CXXFLAGS = -I$(PHONELIBS)/capnp-cpp/include
ifeq ($(CEREAL_LIBS),)
CEREAL_LIBS = -L$(PHONELIBS)/capnp-cpp/aarch64/lib/ \
-L$(PHONELIBS)/capnp-c/aarch64/lib/ \
-l:libcapn.a -l:libcapnp.a -l:libkj.a
endif
CEREAL_OBJS = ../../cereal/gen/c/log.capnp.o ../../cereal/gen/c/car.capnp.o
log.capnp.o: ../../cereal/gen/cpp/log.capnp.c++
@echo "[ CXX ] $@"
$(CXX) $(CXXFLAGS) $(CEREAL_CXXFLAGS) \
-c -o '$@' '$<'
car.capnp.o: ../../cereal/gen/cpp/car.capnp.c++
@echo "[ CXX ] $@"
$(CXX) $(CXXFLAGS) $(CEREAL_CXXFLAGS) \
-c -o '$@' '$<'

View File

@@ -33,8 +33,12 @@ struct FramebufferState {
EGLContext context;
};
extern "C" void framebuffer_set_power(FramebufferState *s, int mode) {
SurfaceComposerClient::setDisplayPowerMode(s->dtoken, mode);
}
extern "C" FramebufferState* framebuffer_init(
const char* name, int32_t layer,
const char* name, int32_t layer, int alpha,
EGLDisplay *out_display, EGLSurface *out_surface,
int *out_w, int *out_h) {
status_t status;
@@ -53,6 +57,7 @@ extern "C" FramebufferState* framebuffer_init(
assert(status == 0);
int orientation = 3; // rotate framebuffer 270 degrees
//int orientation = 1; // rotate framebuffer 90 degrees
if(orientation == 1 || orientation == 3) {
int temp = s->dinfo.h;
s->dinfo.h = s->dinfo.w;
@@ -81,6 +86,7 @@ extern "C" FramebufferState* framebuffer_init(
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, alpha ? 8 : 0,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,

View File

@@ -10,12 +10,41 @@ extern "C" {
typedef struct FramebufferState FramebufferState;
FramebufferState* framebuffer_init(
const char* name, int32_t layer,
const char* name, int32_t layer, int alpha,
EGLDisplay *out_display, EGLSurface *out_surface,
int *out_w, int *out_h);
void framebuffer_set_power(FramebufferState *s, int mode);
/* Display power modes */
enum {
/* The display is turned off (blanked). */
HWC_POWER_MODE_OFF = 0,
/* The display is turned on and configured in a low power state
* that is suitable for presenting ambient information to the user,
* possibly with lower fidelity than normal but greater efficiency. */
HWC_POWER_MODE_DOZE = 1,
/* The display is turned on normally. */
HWC_POWER_MODE_NORMAL = 2,
/* The display is configured as in HWC_POWER_MODE_DOZE but may
* stop applying frame buffer updates from the graphics subsystem.
* This power mode is effectively a hint from the doze dream to
* tell the hardware that it is done drawing to the display for the
* time being and that the display should remain on in a low power
* state and continue showing its current contents indefinitely
* until the mode changes.
*
* This mode may also be used as a signal to enable hardware-based doze
* functionality. In this case, the doze dream is effectively
* indicating that the hardware is free to take over the display
* and manage it autonomously to implement low power always-on display
* functionality. */
HWC_POWER_MODE_DOZE_SUSPEND = 3,
};
#ifdef __cplusplus
}
#endif
#endif
#endif

71
selfdrive/common/glutil.c Normal file
View File

@@ -0,0 +1,71 @@
#include <stdlib.h>
#include <stdio.h>
#include <GLES3/gl3.h>
#include "glutil.h"
GLuint load_shader(GLenum shaderType, const char *src) {
GLint status = 0, len = 0;
GLuint shader;
if (!(shader = glCreateShader(shaderType)))
return 0;
glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status)
return shader;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len) {
char *msg = (char*)malloc(len);
if (msg) {
glGetShaderInfoLog(shader, len, NULL, msg);
msg[len-1] = 0;
fprintf(stderr, "error compiling shader:\n%s\n", msg);
free(msg);
}
}
glDeleteShader(shader);
return 0;
}
GLuint load_program(const char *vert_src, const char *frag_src) {
GLuint vert, frag, prog;
GLint status = 0, len = 0;
if (!(vert = load_shader(GL_VERTEX_SHADER, vert_src)))
return 0;
if (!(frag = load_shader(GL_FRAGMENT_SHADER, frag_src)))
goto fail_frag;
if (!(prog = glCreateProgram()))
goto fail_prog;
glAttachShader(prog, vert);
glAttachShader(prog, frag);
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status)
return prog;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
if (len) {
char *buf = (char*) malloc(len);
if (buf) {
glGetProgramInfoLog(prog, len, NULL, buf);
buf[len-1] = 0;
fprintf(stderr, "error linking program:\n%s\n", buf);
free(buf);
}
}
glDeleteProgram(prog);
fail_prog:
glDeleteShader(frag);
fail_frag:
glDeleteShader(vert);
return 0;
}

View File

@@ -0,0 +1,8 @@
#ifndef COMMON_GLUTIL_H
#define COMMON_GLUTIL_H
#include <GLES3/gl3.h>
GLuint load_shader(GLenum shaderType, const char *src);
GLuint load_program(const char *vert_src, const char *frag_src);
#endif

View File

@@ -1,13 +0,0 @@
#ifndef COMMON_MUTEX_H
#define COMMON_MUTEX_H
#include <pthread.h>
static inline void mutex_init_reentrant(pthread_mutex_t *mutex) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(mutex, &attr);
}
#endif

130
selfdrive/common/params.c Normal file
View File

@@ -0,0 +1,130 @@
#include "selfdrive/common/params.h"
#include "selfdrive/common/util.h"
#define _GNU_SOURCE
#include <sys/file.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int write_db_value(const char* params_path, const char* key, const char* value,
size_t value_size) {
int lock_fd = -1;
int tmp_fd = -1;
int result;
char tmp_path[1024];
char path[1024];
// Write value to temp.
result =
snprintf(tmp_path, sizeof(tmp_path), "%s/.tmp_value_XXXXXX", params_path);
if (result < 0) {
goto cleanup;
}
tmp_fd = mkstemp(tmp_path);
const ssize_t bytes_written = write(tmp_fd, value, value_size);
if (bytes_written != value_size) {
result = -20;
goto cleanup;
}
result = snprintf(path, sizeof(path), "%s/.lock", params_path);
if (result < 0) {
goto cleanup;
}
lock_fd = open(path, 0);
result = snprintf(path, sizeof(path), "%s/d/%s", params_path, key);
if (result < 0) {
goto cleanup;
}
// Take lock.
result = flock(lock_fd, LOCK_EX);
if (result < 0) {
goto cleanup;
}
// fsync to force persist the changes.
result = fsync(tmp_fd);
if (result < 0) {
goto cleanup;
}
// Move temp into place.
result = rename(tmp_path, path);
cleanup:
// Release lock.
if (lock_fd >= 0) {
close(lock_fd);
}
if (tmp_fd >= 0) {
if (result < 0) {
remove(tmp_path);
}
close(tmp_fd);
}
return result;
}
int read_db_value(const char* params_path, const char* key, char** value,
size_t* value_sz) {
int lock_fd = -1;
int result;
char path[1024];
result = snprintf(path, sizeof(path), "%s/.lock", params_path);
if (result < 0) {
goto cleanup;
}
lock_fd = open(path, 0);
result = snprintf(path, sizeof(path), "%s/d/%s", params_path, key);
if (result < 0) {
goto cleanup;
}
// Take lock.
result = flock(lock_fd, LOCK_EX);
if (result < 0) {
goto cleanup;
}
// Read value.
// TODO(mgraczyk): If there is a lot of contention, we can release the lock
// after opening the file, before reading.
*value = read_file(path, value_sz);
if (*value == NULL) {
result = -22;
goto cleanup;
}
// Remove one for null byte.
if (value_sz != NULL) {
*value_sz -= 1;
}
result = 0;
cleanup:
// Release lock.
if (lock_fd >= 0) {
close(lock_fd);
}
return result;
}
void read_db_value_blocking(const char* params_path, const char* key,
char** value, size_t* value_sz) {
while (1) {
const int result = read_db_value(params_path, key, value, value_sz);
if (result == 0) {
return;
} else {
// Sleep for 0.1 seconds.
usleep(100000);
}
}
}

35
selfdrive/common/params.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef _SELFDRIVE_COMMON_PARAMS_H_
#define _SELFDRIVE_COMMON_PARAMS_H_
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
int write_db_value(const char* params_path, const char* key, const char* value,
size_t value_size);
// Reads a value from the params database.
// Inputs:
// params_path: The path of the database, eg /sdcard/params.
// key: The key to read.
// value: A pointer where a newly allocated string containing the db value will
// be written.
// value_sz: A pointer where the size of value will be written. Does not
// include the NULL terminator.
//
// Returns: Negative on failure, otherwise 0.
int read_db_value(const char* params_path, const char* key, char** value,
size_t* value_sz);
// Reads a value from the params database, blocking until successful.
// Inputs are the same as read_db_value.
void read_db_value_blocking(const char* params_path, const char* key,
char** value, size_t* value_sz);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // _SELFDRIVE_COMMON_PARAMS_H_

View File

@@ -1,3 +1,5 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -10,6 +12,7 @@
#include <json.h>
#include "common/timing.h"
#include "common/version.h"
#include "swaglog.h"
@@ -19,22 +22,49 @@ typedef struct LogState {
JsonNode *ctx_j;
void *zctx;
void *sock;
int print_level;
} LogState;
static LogState s = {
.lock = PTHREAD_MUTEX_INITIALIZER,
};
static void cloudlog_bind_locked(const char* k, const char* v) {
json_append_member(s.ctx_j, k, json_mkstring(v));
}
static void cloudlog_init() {
if (s.inited) return;
s.ctx_j = json_mkobject();
s.zctx = zmq_ctx_new();
s.sock = zmq_socket(s.zctx, ZMQ_PUSH);
zmq_connect(s.sock, "ipc:///tmp/logmessage");
s.print_level = CLOUDLOG_WARNING;
const char* print_level = getenv("LOGPRINT");
if (print_level) {
if (strcmp(print_level, "debug") == 0) {
s.print_level = CLOUDLOG_DEBUG;
} else if (strcmp(print_level, "info") == 0) {
s.print_level = CLOUDLOG_INFO;
} else if (strcmp(print_level, "warning") == 0) {
s.print_level = CLOUDLOG_WARNING;
}
}
// openpilot bindings
char* dongle_id = getenv("DONGLE_ID");
if (dongle_id) {
cloudlog_bind_locked("dongle_id", dongle_id);
}
cloudlog_bind_locked("version", OPENPILOT_VERSION);
bool dirty = !getenv("CLEAN");
json_append_member(s.ctx_j, "dirty", json_mkbool(dirty));
s.inited = true;
}
void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func, const char* srctime,
void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func,
const char* fmt, ...) {
pthread_mutex_lock(&s.lock);
cloudlog_init();
@@ -50,7 +80,7 @@ void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func
return;
}
if (levelnum >= CLOUDLOG_PRINT_LEVEL) {
if (levelnum >= s.print_level) {
printf("%s: %s\n", filename, msg_buf);
}
@@ -63,7 +93,6 @@ void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func
json_append_member(log_j, "filename", json_mkstring(filename));
json_append_member(log_j, "lineno", json_mknumber(lineno));
json_append_member(log_j, "funcname", json_mkstring(func));
json_append_member(log_j, "srctime", json_mkstring(srctime));
json_append_member(log_j, "created", json_mknumber(seconds_since_epoch()));
char* log_s = json_encode(log_j);
@@ -85,6 +114,6 @@ void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func
void cloudlog_bind(const char* k, const char* v) {
pthread_mutex_lock(&s.lock);
cloudlog_init();
json_append_member(s.ctx_j, k, json_mkstring(v));
cloudlog_bind_locked(k, v);
pthread_mutex_unlock(&s.lock);
}

View File

@@ -7,15 +7,21 @@
#define CLOUDLOG_ERROR 40
#define CLOUDLOG_CRITICAL 50
#define CLOUDLOG_PRINT_LEVEL CLOUDLOG_WARNING
#ifdef __cplusplus
extern "C" {
#endif
void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func, const char* srctime,
void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func,
const char* fmt, ...) /*__attribute__ ((format (printf, 6, 7)))*/;
void cloudlog_bind(const char* k, const char* v);
#ifdef __cplusplus
}
#endif
#define cloudlog(lvl, fmt, ...) cloudlog_e(lvl, __FILE__, __LINE__, \
__func__, __DATE__ " " __TIME__, \
__func__, \
fmt, ## __VA_ARGS__)
#define LOGD(fmt, ...) cloudlog(CLOUDLOG_DEBUG, fmt, ## __VA_ARGS__)

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