Skip to content

Commit

Permalink
update plugin to match current dash version
Browse files Browse the repository at this point in the history
  • Loading branch information
egisz committed Jun 8, 2023
1 parent 8aadb97 commit e967138
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 45 deletions.
93 changes: 48 additions & 45 deletions bmw_f10_idrive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,30 @@

#include "bmw_f10_idrive.hpp"

// QString BmwF10::toDebug(const QByteArray & line) {

// QString s;
// uchar c;

// for ( int i=0 ; i < line.size() ; i++ ){
// c = line[i];
// if ( c >= 0x20 and c <= 126 ) {
// s.append(c);
// } else {
// s.append(QString("<%1>").arg(c, 2, 16, QChar('0')));
// }
// }
// return s;
// }
BmwF10::~BmwF10()
{
if (this->debug)
delete this->debug;
}

bool BmwF10::init(ICANBus* canbus){
F10_LOG(info)<<"loading plugin...";
if (this->arbiter) {
this->debug = new DebugWindow(*this->arbiter);
F10_LOG(info)<<"loading plugin...";
this->canbus = canbus;
canbus->registerFrameHandler(0x264, [this](QByteArray payload){this->monitorIdriveRotaryStatus(payload);});
canbus->registerFrameHandler(0x267, [this](QByteArray payload){this->monitorIdriveButtonStatus(payload);});
canbus->registerFrameHandler(0x21A, [this](QByteArray payload){this->monitorGearStatus(payload);});
canbus->registerFrameHandler(0x1A1, [this](QByteArray payload){this->monitorVehicleSpeed(payload);});
canbus->registerFrameHandler(0x0A5, [this](QByteArray payload){this->monitorEngineRPM(payload);});
// canbus->registerFrameHandler(0x1A1, [this](QByteArray payload){this->monitorVehicleSpeed(payload);});
// canbus->registerFrameHandler(0x0A5, [this](QByteArray payload){this->monitorEngineRPM(payload);});
canbus->registerFrameHandler(0x273, [this](QByteArray payload){this->monitorCicStatus(payload);});

// Switch to TV screen on connect.
auto *oaPage = this->arbiter->layout().openauto_page;
connect(oaPage, &OpenAutoPage::connected, this, [this](bool connected){
this->switchTVInput();
});
// connected event was removed :(
// auto *oaPage = this->arbiter->layout().openauto_page;
// connect(oaPage, &OpenAutoPage::connected, this, [this](bool connected){
this->switchTVInput();
// });
F10_LOG(info)<<"loaded successfully";
return true;
}
Expand All @@ -47,7 +38,9 @@ bool BmwF10::init(ICANBus* canbus){
QList<QWidget *> BmwF10::widgets()
{
QList<QWidget *> tabs;
tabs.append(this->debug);
if (this->debug) {
tabs.append(this->debug);
}
return tabs;
}

Expand All @@ -63,11 +56,11 @@ void BmwF10::monitorIdriveRotaryStatus(QByteArray payload){
if (this->rotaryPos < this->rotaryPrevPos && this->rotaryPrevPos != -1) {
// rotate counter clockwise
this->arbiter->send_openauto_button_press(aasdk::proto::enums::ButtonCode::SCROLL_WHEEL, openauto::projection::WheelDirection::LEFT);
F10_LOG(info)<<"Rotate counter clockwise";
// F10_LOG(info)<<"Rotate counter clockwise";
} else if (this->rotaryPos > this->rotaryPrevPos && this->rotaryPrevPos != -1) {
// rotate clockwise
this->arbiter->send_openauto_button_press(aasdk::proto::enums::ButtonCode::SCROLL_WHEEL, openauto::projection::WheelDirection::RIGHT);
F10_LOG(info)<<"Rotate clockwise";
// F10_LOG(info)<<"Rotate clockwise";
}
this->debug->rotaryPos->setText(QString::number(this->rotaryPos));
}
Expand All @@ -79,55 +72,65 @@ void BmwF10::monitorIdriveButtonStatus(QByteArray payload){
// unsigned char j = 0xE1;
// F10_LOG(info)<<"got 0x267 frame: "<< QString::number(j, 16).toStdString();
// qDebug() << "Value : " << hex << j;
//if(this->cic_fullscreen && payload.at(2) > this->msgCounter &&

if(this->cic_fullscreen && payload.at(2) > this->msgCounter &&
if(payload.at(2) > this->msgCounter &&
payload.at(0) == 0xE1 && payload.at(1) == 0xFD &&
(payload.at(4) == 0xDD || payload.at(4) == 0xDE)) {
if(payload.at(3) == 0x00 && this->lastKey != aasdk::proto::enums::ButtonCode::NONE){
// Release
F10_LOG(info)<<"Idrive button release";
// F10_LOG(info)<<"Idrive button release";
this->arbiter->send_openauto_button_press(this->lastKey);
this->lastKey = aasdk::proto::enums::ButtonCode::NONE;
} else if(payload.at(3) == 0x01 && payload.at(4) == 0xDE){
// Enter
F10_LOG(info)<<"Enter";
// } else if(payload.at(3) == 0x01 && payload.at(4) == 0xDE){
} else if(payload.at(3) == 0x11 && payload.at(4) == 0xDD){
// UP -> Enter
// F10_LOG(info)<<"Up -> Enter";
this->lastKey = aasdk::proto::enums::ButtonCode::ENTER;
this->debug->lastKey->setText(QString("Enter"));
} else if(payload.at(3) == 0x11 && payload.at(4) == 0xDD){
// UP
F10_LOG(info)<<"Idrive button UP";
// } else if(payload.at(3) == 0x11 && payload.at(4) == 0xDD){
} else if(payload.at(3) == 0x12 && payload.at(4) == 0xDD){
// UP Hold -> Up
// F10_LOG(info)<<"Idrive button UP Hold";
this->lastKey = aasdk::proto::enums::ButtonCode::UP;
this->debug->lastKey->setText(QString("Up"));
} else if(payload.at(3) == 0x12 && payload.at(4) == 0xDD){
// UP hold
this->lastKey = aasdk::proto::enums::ButtonCode::BACK;
this->debug->lastKey->setText(QString("Up Hold >> Back"));
// } else if(payload.at(3) == 0x12 && payload.at(4) == 0xDD){
// // UP hold
// this->lastKey = aasdk::proto::enums::ButtonCode::BACK;
// this->debug->lastKey->setText(QString("Up Hold >> Back"));
} else if(payload.at(3) == 0x41 && payload.at(4) == 0xDD){
// DOWN
F10_LOG(info)<<"Idrive button Down";
// F10_LOG(info)<<"Idrive button Down";
if (this->lastKey == aasdk::proto::enums::ButtonCode::DOWN) {
this->lastKey = aasdk::proto::enums::ButtonCode::UP;
this->debug->lastKey->setText(QString("Up"));
}
this->lastKey = aasdk::proto::enums::ButtonCode::DOWN;
this->debug->lastKey->setText(QString("Down"));
} else if(payload.at(3) == 0x42 && payload.at(4) == 0xDD){
// DOWN hold
this->lastKey = aasdk::proto::enums::ButtonCode::HOME;
this->debug->lastKey->setText(QString("Down Hold >> HOME"));
}
}
if(payload.at(0) == 0xE1 && payload.at(1) == 0xFD && payload.at(4) == 0xDD &&
(payload.at(3) == 0x41 || payload.at(3) == 0x11 || payload.at(3) == 0x12 )) {
payload[3] = (uint) 0xFF;
payload[4] = (uint) 0xDD;
this->canbus->writeFrame(QCanBusFrame(0x267, payload));
}

this->msgCounter = payload.at(2);
}

void BmwF10::monitorGearStatus(QByteArray payload){
if(payload.at(1)%2 == 1 && !this->inReverse){
F10_LOG(info)<<"Reverse Gear";
// F10_LOG(info)<<"Reverse Gear";
this->switchTVInput();
this->debug->inReverse->setText(QString("Yes"));
this->inReverse = true;
this->arbiter->set_curr_page(3);
} else if(payload.at(1)%2 == 0 && this->inReverse){
F10_LOG(info)<<"Not reverse";
// F10_LOG(info)<<"Not reverse";
this->debug->inReverse->setText(QString("No"));
this->inReverse = false;
this->arbiter->set_curr_page(0);
Expand All @@ -136,25 +139,25 @@ void BmwF10::monitorGearStatus(QByteArray payload){

void BmwF10::monitorEngineRPM(QByteArray payload){
int rpm = ((256.0 * (int)payload.at(6)) + (int)payload.at(5)) / 4.0;
F10_LOG(info)<<"RPM: "<<std::to_string(rpm);
// F10_LOG(info)<<"RPM: "<<std::to_string(rpm);
this->debug->rpm->setText(QString::number(rpm));
// this->arbiter->vehicle_update_data("rpm", rpm);
}

void BmwF10::monitorVehicleSpeed(QByteArray payload){
int speed = ((256.0 * (int)payload.at(3)) + (int)payload.at(2)) * 1.609344 / 100.0;
F10_LOG(info)<<"Speed: "<<std::to_string(speed);
// F10_LOG(info)<<"Speed: "<<std::to_string(speed);
// this->arbiter->vehicle_update_data("speed", speed);
}

void BmwF10::monitorCicStatus(QByteArray payload){
this->cic_fullscreen = payload.at(0) == 0x5D;
F10_LOG(info)<<"CIC fullscreen: "<<this->cic_fullscreen;
// F10_LOG(info)<<"CIC fullscreen: "<<this->cic_fullscreen;
}

void BmwF10::switchTVInput(){
if (!this->cic_fullscreen) {
F10_LOG(info)<<"Switch to TV source";
// F10_LOG(info)<<"Switch to TV source";
this->canbus->writeFrame(QCanBusFrame(0x0A2, QByteArray::fromHex("0080")));
this->canbus->writeFrame(QCanBusFrame(0x0A2, QByteArray::fromHex("0000")));
}
Expand Down
2 changes: 2 additions & 0 deletions bmw_f10_idrive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class BmwF10 : public QObject, VehiclePlugin
Q_INTERFACES(VehiclePlugin)

public:
BmwF10() {};
~BmwF10();
bool init(ICANBus* canbus) override;

private:
Expand Down
4 changes: 4 additions & 0 deletions bmw_f10_idrive.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name" : "BMW F10 idrive integration",
"version" : "1.0"
}
88 changes: 88 additions & 0 deletions setup_can.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/bin/bash -e

CAN_INTERFACE=can0
CAN_BITRATE=100k
CAN_OSCILATOR=8000000
CAN_INTERRUPT=12

# install required packages:
sudo apt-get install can-utils

echo "Setup can interface to bring up automatically on reboot..."

# setup can interface to bring up automatically on reboot.
FILE_CAN_INTERFACE=/etc/network/interfaces.d/$CAN_INTERFACE
if [ -f "$FILE_CAN_INTERFACE" ]; then
echo "can0 network interface found, skipping..."
else
echo "Setting up can0 interface"
cat > $FILE_CAN_INTERFACE <<EOF
auto $CAN_INTERFACE
iface $CAN_INTERFACE can manual
pre-up /sbin/ip link set $CAN_INTERFACE type can bitrate $CAN_BITRATE restart-ms 100
up /sbin/ifconfig $CAN_INTERFACE up txqueuelen 125
down /sbin/ifconfig $CAN_INTERFACE down
EOF
echo "File patched: $FILE_CAN_INTERFACE";
cat $FILE_CAN_INTERFACE
fi

echo "Enable NetworkManager"
sudo systemctl enable systemd-networkd
sudo systemctl start systemd-networkd
sudo systemctl status systemd-networkd

echo "Creating config file..."
FILE_CAN_INTERFACE=/etc/systemd/network/80-can.network
if [ -f "$FILE_CAN_INTERFACE" ]; then
echo "can0 network interface found, skipping..."
else
echo "Setting up can0 interface"
sudo cat > $FILE_CAN_INTERFACE <<EOF
[Match]
Name=$CAN_INTERFACE
[CAN]
BitRate=$CAN_BITRATE
RestartSec=100ms
EOF
echo "File patched: $FILE_CAN_INTERFACE";
sudo cat $FILE_CAN_INTERFACE
fi

echo "Enable SPI..."
sudo raspi-config nonint do_spi 0

#echo "Disable boot splash..."
#sudo raspi-config nonint do_boot_splash 1

echo "Disable screen blanking..."
sudo raspi-config nonint do_blanking 1

# patch config.txt
FILE_BOOT_CFG=/boot/config.txt
# detect Raspberry BCM chip
# BCM_CHIP=`cat /proc/cpuinfo | grep -oE 'BCM[0-9]{4}' | tr '[:upper:]' '[:lower:]'`
# if [ -z "$BCM_CHIP" ]; then
# echo "ERROR: Could not detect BCM chip. Exiting..."
# exit
# fi
# check if config already patched
if grep -q ^dtoverlay=mcp2515 "$FILE_BOOT_CFG"; then
echo "config.txt already patched, skipping..."
else
# check if file writable
if [ ! -w "$FILE_BOOT_CFG" ]; then
echo "/boot not writable, remounting"
sudo mount -o remount,rw /boot
fi
sudo cat >> $FILE_BOOT_CFG <<EOF
# CAN bus
dtoverlay=mcp2515,spi0-0,oscillator=$CAN_OSCILATOR,interrupt=$CAN_INTERRUPT
EOF
echo "File patched: $FILE_BOOT_CFG";
fi

echo "Done. Restart raspberry to enable CAN interface".
echo "If needed, use command to restart CAN interface: sudo systemctl restart systemd-networkd"

0 comments on commit e967138

Please sign in to comment.