242 lines
6.3 KiB
C++
242 lines
6.3 KiB
C++
/***************************************************************************
|
|
|
|
BionxControl
|
|
Copyright © 2025 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 <QDebug>
|
|
|
|
|
|
#include <bcdrivertinycan.h>
|
|
#include <can_drv.h>
|
|
|
|
|
|
BCDriverTinyCan::BCDriverTinyCan( QObject* parent )
|
|
: BCDriver(parent )
|
|
{
|
|
|
|
}
|
|
|
|
|
|
BCDriver::DriverState BCDriverTinyCan::loadDriver()
|
|
{
|
|
|
|
//qDebug() << "CanBusControl " << cbc::Version << '\n' << "based on BigXionFlasher (c) 2011-2013 by Thomas Koenig <info@bigxionflasher.org> - www.bigxionflasher.org";
|
|
|
|
struct ::TDeviceStatus canDevicestatus;
|
|
|
|
if( ::LoadDriver( NULL ) < 0 )
|
|
throw BCException( "Driver Error: 'LoadDriver'" );
|
|
|
|
setState(BCDriver::DriverState::Loaded);
|
|
|
|
if( ::CanInitDriver( NULL ) < 0 )
|
|
throw BCException( "Driver Error: 'InitDriver'" );
|
|
|
|
if( ::CanDeviceOpen( 0, NULL ) < 0 )
|
|
throw std::runtime_error( "Driver Error: 'DeviceOpen'" );
|
|
|
|
::CanSetSpeed( 0, CAN_125K_BIT );
|
|
::CanSetMode( 0, OP_CAN_START, CAN_CMD_ALL_CLEAR );
|
|
::CanGetDeviceStatus( 0, &canDevicestatus );
|
|
|
|
setState(BCDriver::DriverState::Initialized);
|
|
|
|
if( canDevicestatus.DrvStatus < DRV_STATUS_CAN_OPEN )
|
|
throw BCException( "Driver Error: could not open device." );
|
|
|
|
if( canDevicestatus.CanStatus == CAN_STATUS_BUS_OFF )
|
|
{
|
|
::CanSetMode( 0, OP_CAN_RESET, CAN_CMD_NONE );
|
|
throw BCException( "Driver Error: CAN Status 'BusOff'" );
|
|
}
|
|
|
|
setState(BCDriver::DriverState::Ready);
|
|
|
|
return BCDriver::DriverState::Ready;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
try
|
|
{
|
|
loadDriver();
|
|
initBCDevice::ID::Console();
|
|
}
|
|
|
|
catch( std::exception& except )
|
|
{
|
|
::CanDownDriver();
|
|
::UnloadDriver();
|
|
|
|
// re-throw
|
|
throw BCException( except.what() );
|
|
}
|
|
*/
|
|
|
|
|
|
BCDriver::DriverState BCDriverTinyCan::initDriver()
|
|
{
|
|
|
|
uint32_t console = static_cast<uint32_t>(BCDevice::ID::Console);
|
|
uint8_t slaveFlag = static_cast<uint8_t>(BC::ID::Cons_Status_Slave);
|
|
|
|
qDebug() << "XXX BCDriverTinyCan::Driver Init: putting BCDevice::ID::Console in slave mode ... ";
|
|
// BCDevice::ID::Console already in slave mode. good!
|
|
if( readRawByte( console, slaveFlag ) )
|
|
return DriverState::Ready;
|
|
|
|
qDebug() << "BCDriverTinyCan::BCDriverTinyCan::XXX Driver Init: putting BCDevice::ID::Console in slave mode ... ";
|
|
|
|
unsigned int retry = cTimeOuts;
|
|
emit statusHint( "Driver Init: putting BCDevice::ID::Console in slave mode ... " );
|
|
|
|
uint32_t isSlave = 0;
|
|
do
|
|
{
|
|
writeRawByte( console, slaveFlag, 1 );
|
|
isSlave = readRawByte( console, slaveFlag );
|
|
bc::delay_millis( 200 );
|
|
|
|
} while( retry-- && !isSlave );
|
|
|
|
bc::delay_millis( 500 ); // give the Console some time to settle
|
|
//if( !isSlave )
|
|
emit statusHint( QString("putting BCDevice::ID::Console in slave mode ") + (isSlave ? "done" : "failed") );
|
|
|
|
// ist das jetzt irgendwie schlimm, wenn wir keine slave BCDevice::ID::Console haben
|
|
//return isSlave ? BCDriver::connected
|
|
|
|
return DriverState::Ready;
|
|
|
|
|
|
}
|
|
|
|
|
|
uint32_t BCDriverTinyCan::readRawByte( uint32_t deviceID, uint8_t registerID ) const
|
|
{
|
|
|
|
if( getState() != DriverState::Ready)
|
|
throw BCException( "readRawValue error: driver not loaded." );
|
|
|
|
//uint32_t result = transmitter.readRawValue( deviceID, registerID );
|
|
|
|
//value.fromValue<uint32_t>( myRandomByte );
|
|
|
|
TCanMsg msg;
|
|
|
|
// msg verpacken
|
|
msg.MsgFlags = 0L;
|
|
msg.Id = deviceID;
|
|
msg.MsgLen = 2;
|
|
msg.MsgData[0] = 0x00;
|
|
msg.MsgData[1] = registerID;
|
|
|
|
// msg verschicken
|
|
::CanTransmit( 0, &msg, 1 );
|
|
|
|
int retries = cRetries; // 5?
|
|
// cTimeOuts (== 20) mal cTIMEOUT_MS (== 10 ms ) Versuche ...
|
|
int timeOuts = cTimeOuts; // 20 ?
|
|
|
|
// ... warten bis der Sendepuffer leer ist
|
|
while( timeOuts-- && ::CanTransmitGetCount( 0 ) )
|
|
bc::delay_millis( cTIMEOUT_MS );
|
|
|
|
if( timeOuts == -1 )
|
|
throw BCException( "readRawValue error: could not send value" );
|
|
|
|
retry:
|
|
|
|
// cTimeOuts (== 20) mal cTIMEOUT_MS (== 10 ms ) Versuche ...
|
|
timeOuts = cTimeOuts;
|
|
// ... warten, bis der Empfangspuffer nicht mehr leer ist
|
|
while( timeOuts-- && !::CanReceiveGetCount( 0 ) )
|
|
bc::delay_millis( cTIMEOUT_MS );
|
|
|
|
if( timeOuts == -1 )
|
|
throw BCException( "getValue error: no response from node" );
|
|
|
|
// message empfangen
|
|
int err = ::CanReceive( 0, &msg, 1 );
|
|
qDebug() << "HÄÄ ?" << err << "reg: "<< registerID <<" timeOuts: " << timeOuts;
|
|
|
|
if( err < 0 )
|
|
//throw BCException( "getValue error: could not receive value" );
|
|
qDebug( "getValue error: could not receive value" );
|
|
|
|
qDebug() << "HÄÄ 2" <<msg.Id;
|
|
qDebug() << "HÄÄ 2" <<msg.MsgLen;
|
|
qDebug() << "HÄÄ 2" <<msg.MsgData[1];
|
|
|
|
//if( err > 0 )
|
|
if( --retries && ( msg.Id != BIB || msg.MsgLen != 4 || msg.MsgData[1] != registerID ) )
|
|
goto retry;
|
|
|
|
if( !timeOuts )
|
|
throw BCException( "CAN --response errror" );
|
|
|
|
return (uint32_t) msg.MsgData[3];
|
|
|
|
}
|
|
|
|
|
|
// void BCDriverTinyCan::setValue( unsigned char receipient, unsigned char reg, unsigned char value )
|
|
void BCDriverTinyCan::writeRawByte( uint32_t deviceID, uint8_t registerID ,uint8_t value ) const
|
|
{
|
|
|
|
if( getState() != DriverState::Ready)
|
|
throw BCException( "writeRawValue error: driver not loaded." );
|
|
|
|
qDebug() << " --- BCDriverTinyCan writeRawValue: " << value;
|
|
return;
|
|
|
|
struct TCanMsg msg;
|
|
int timeout_count = cTIMEOUT_COUNT;
|
|
|
|
msg.MsgFlags = 0L;
|
|
msg.Id = deviceID;
|
|
msg.MsgLen = 4;
|
|
msg.MsgData[0] = 0x00;
|
|
msg.MsgData[1] = registerID;
|
|
msg.MsgData[2] = 0x00;
|
|
msg.MsgData[3] = value;
|
|
|
|
::CanTransmit( 0, &msg, 1 );
|
|
|
|
while( timeout_count-- && ::CanTransmitGetCount( 0 ) )
|
|
bc::delay_millis( cTIMEOUT_MS );
|
|
|
|
if( timeout_count == -1 )
|
|
emit statusHint( QString( "error: could not send value to %1" ).arg( deviceID ) );
|
|
|
|
}
|
|
|