213 lines
5.9 KiB
C++
213 lines
5.9 KiB
C++
/***************************************************************************
|
|
|
|
BionxControl
|
|
© 2025 -2026 christoph holzheuer
|
|
christoph.holzheuer@gmail.com
|
|
|
|
Using:
|
|
|
|
mhs_can_drv.c
|
|
© 2011 - 2023 by MHS-Elektronik GmbH & Co. KG, Germany
|
|
Klaus Demlehner, klaus@mhs-elektronik.de
|
|
@see www.mhs-elektronik.de
|
|
|
|
Based on Bionx data type descriptions from:
|
|
|
|
BigXionFlasher USB V 0.2.4 rev. 97
|
|
© 2011-2013 by Thomas Koenig <info@bigxionflasher.org>
|
|
@see www.bigxionflasher.org
|
|
|
|
Bionx Bike Info
|
|
© 2018 Thorsten Schmidt (tschmidt@ts-soft.de)
|
|
@see www.ts-soft.de
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
@see https://github.com/bikemike/bionx-bikeinfo
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
#include <QThread>
|
|
#include <QDebug>
|
|
#include <QCoreApplication>
|
|
|
|
#include <bctransmitter.h>
|
|
|
|
/**
|
|
* @brief Kosntruktion. Aktiviert erstmal den Dummy-Driver.
|
|
*/
|
|
|
|
BCTransmitter::BCTransmitter(QObject *parent)
|
|
: QObject(parent)//, _isBusy(false)
|
|
{
|
|
//_canDriver = new BCDriverTinyCan{this};
|
|
_canDriver = &_dummyDriver;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Steuert die Verbindung mit dem 'echten' CAN-Bus Treiber.
|
|
* @param connect true: Vesuche den CAN-Bus Treiber zu laden und zu verbinden
|
|
* false: Disconnect & Cleanup
|
|
*/
|
|
|
|
void BCTransmitter::onToggleDriverConnection( bool connect )
|
|
{
|
|
if( connect )
|
|
emit driverStateChanged(BCDriver::DriverState::NotPresent, "Native Treiber wird geladen.");
|
|
|
|
/*
|
|
// kill all pending stuff
|
|
//QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
|
|
BCDriver::DriverState state = connect ? BCDriver::DriverState::DeviceReady : BCDriver::DriverState::NotPresent;
|
|
const QString& message = connect ? "Trying to connect" : " FAILED";
|
|
emit driverStateChanged(state, message);
|
|
return;
|
|
*/
|
|
|
|
connect ? connectCanDriver() : disconnectCanDriver();
|
|
|
|
}
|
|
|
|
|
|
void BCTransmitter::connectCanDriver()
|
|
{
|
|
// hier gehts nur um den echten Treiber
|
|
|
|
// Treiber laden und/oder starten:
|
|
BCDriver::DriverStateResult result; //(defaults to 'NotPresent')
|
|
if( _tinyCanDriver.getDriverState() != BCDriver::DriverState::DeviceReady )
|
|
result = _tinyCanDriver.loadAndStartDriver();
|
|
|
|
|
|
QString message("Treiber geladen (nicht verbunden)");
|
|
|
|
// Der result-Wert im ERfolgsfall ist der driver state.
|
|
if(result.has_value() )
|
|
{
|
|
switch( result.value() )
|
|
{
|
|
case BCDriver::DriverState::Opened:
|
|
|
|
message = "Treiber geladen (Device antwortet nicht)";
|
|
break;
|
|
|
|
case BCDriver::DriverState::DeviceReady:
|
|
|
|
message = "Treiber geladen und Device verbunden.";
|
|
// swap driver
|
|
_canDriver = &_tinyCanDriver;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
else // Fehlerfall, wir holen die Fehlermeldung
|
|
{
|
|
message = result.error();
|
|
}
|
|
|
|
emit driverStateChanged( _tinyCanDriver.getDriverState(), message );
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Native-Treiber zurücksetzen, Dummy-Treiber wieder aktivieren.
|
|
*/
|
|
|
|
void BCTransmitter::disconnectCanDriver()
|
|
{
|
|
_tinyCanDriver.resetDriver();
|
|
_canDriver = &_dummyDriver;
|
|
emit driverStateChanged( _tinyCanDriver.getDriverState(), "Disconnected, Dummy Treiber aktiviert." );
|
|
}
|
|
|
|
|
|
void BCTransmitter::onUpdateValue( BCValuePtrConst valuePtr)
|
|
{
|
|
|
|
// wir stellen hier auf die harte Tour sicher, das onUpdateValue
|
|
// nicht aus dem Parent-Thread direkt sondern über die EventQueue aufgerufen wurde.
|
|
|
|
Q_ASSERT(QThread::currentThread() == this->thread());
|
|
|
|
// Wir arbeiten hier ohne besondere Threadsynchronisation, mutexed o.ä: Die
|
|
// entkoppelung und serialisierung passiert bereits durch die Qt-Eventqueue.
|
|
// Das klappt aber nur in der hier gewählten Konstellation mit einer Parent-Thread
|
|
// und einem Worker.
|
|
|
|
// Kosmetik
|
|
const BCValue& value = *(valuePtr.get());
|
|
|
|
uint32_t devID = static_cast<uint32_t>(value.getDeviceID());
|
|
uint8_t regID = static_cast<uint8_t> (value.getRegisterID());
|
|
|
|
// Für den Fehlerfall: Wir senden den alten Wert einfach zurück
|
|
uint32_t newValue = value.getRawValue();
|
|
BCValue::Flag newState = BCValue::Flag::Failed;
|
|
|
|
|
|
if(value.testFlag( BCValue::Flag::WriteMe ) )
|
|
{
|
|
|
|
}
|
|
// oder sollen wir hier beides erlauben ? readFlag & writeFlag ?
|
|
// Was kommt dann zuerst? Schreiben und lesen als verify ?
|
|
|
|
else if( value.testFlag( BCValue::Flag::ReadMe ) )
|
|
{
|
|
// wir sind hier im anderen thread! nicht einfach so reinschreiben, nur lesen
|
|
TransmitResult result = value.isWord() ? readWordValue( devID, regID ) : readByteValue( devID, regID );
|
|
if( result.has_value() )
|
|
{
|
|
newState = BCValue::Flag::InSync;
|
|
newValue = result.value();
|
|
qDebug() << " ---- " << BCTimeStamp << " DevID: " << devID << " RegID: " << regID << " Value: " << newValue;
|
|
}
|
|
}
|
|
|
|
emit valueUpdated( value.getDeviceID(), value.getIndexRow(), newState, newValue );
|
|
}
|
|
|
|
/**
|
|
* @brief Wenn dieser SLOT in der Event-Queue erreicht wird, dedeutet dies, das die
|
|
* Übertrgung vom Mainwindow abgeschlossen wurde. Wir schicken zur Bestätigung das
|
|
* Signal 'endOfProcessing' (Welches dann den 'Sync' - Button wieder einschaltet.
|
|
*/
|
|
|
|
void BCTransmitter::onEndOfTransmission()
|
|
{
|
|
emit endOfProcessing();
|
|
}
|
|
|
|
|
|
TransmitResult BCTransmitter::readByteValue( uint32_t deviceID, uint8_t registerID )
|
|
{
|
|
// Wir lesen nur ein Byte und gut.
|
|
return _canDriver->readRawByte( deviceID, registerID );
|
|
}
|
|
|
|
|
|
TransmitResult BCTransmitter::readWordValue( uint32_t deviceID, uint8_t registerID )
|
|
{
|
|
uint32_t result{};
|
|
// hi byte Leseversuch.
|
|
TransmitResult value = _canDriver->readRawByte( deviceID, registerID );
|
|
// Fehler? dann weg
|
|
if( !value)
|
|
return std::unexpected( value.error() );
|
|
// hi byte speichern
|
|
result = *value << 8;
|
|
// low byte, liegt im followup register: +1
|
|
value = _canDriver->readRawByte( deviceID, registerID+1 );
|
|
if( !value)
|
|
return std::unexpected( value.error() );
|
|
result += *value;
|
|
return result;
|
|
}
|