829 lines
26 KiB
C++
829 lines
26 KiB
C++
/* BigXionFlasher.c */
|
|
/* ====================================================================
|
|
* Copyright (c) 2011-2013 by Thomas König <info@bigxionflasher.org>.
|
|
* All rights reserved.
|
|
*
|
|
* 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. All advertising materials mentioning features or use of this
|
|
* software must display the following acknowledgment:
|
|
* "This product includes software developed by the
|
|
* BigXionFlasher Project. (http://www.bigxionflasher.org/)"
|
|
*
|
|
* 4. The name "BigXionFlasher" must not be used to
|
|
* endorse or promote products derived from this software without
|
|
* prior written permission. For written permission, please contact
|
|
* info@bigxionflasher.org.
|
|
*
|
|
* 5. Products derived from this software may not be called "BigXionFlasher"
|
|
* nor may "BigXionFlasher" appear in their names without prior written
|
|
* permission of the BigXionFlasher Project.
|
|
*
|
|
* 6. Redistributions of any form whatsoever must retain the following
|
|
* acknowledgment:
|
|
* "This product includes software developed by the
|
|
* BigXionFlasher Project. (http://www.bigxionflasher.org/)"
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE BigXionFlasher PROJECT ``AS IS'' AND ANY
|
|
* EXPRESSED 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 BigXionFlasher PROJECT OR
|
|
* ITS 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.
|
|
* ====================================================================
|
|
*
|
|
*/
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#ifdef __WIN32__
|
|
#include <conio.h>
|
|
#define DEVICE_OPEN NULL
|
|
#define TREIBER_NAME "mhstcan.dll"
|
|
#define _NL "\n\r"
|
|
#define _DEGREE_SIGN "o"
|
|
#else
|
|
#define DEVICE_OPEN NULL
|
|
#define TREIBER_NAME "libmhstcan.so"
|
|
#define _NL "\n"
|
|
#define _DEGREE_SIGN "°"
|
|
#endif
|
|
#include "can_drv.h"
|
|
|
|
#define __DOSTR(v) #v
|
|
#define __STR(v) __DOSTR(v)
|
|
|
|
#define __BXF_VERSION__ "V 0.2.4 rev. 97"
|
|
|
|
#define UNLIMITED_SPEED_VALUE 70 /* Km/h */
|
|
#define UNLIMITED_MIN_SPEED_VALUE 30 /* Km/h */
|
|
#define MAX_THROTTLE_SPEED_VALUE 70 /* Km/h */
|
|
|
|
//#include "registers.h"
|
|
|
|
#define TIMEOUT_VALUE 80
|
|
#define TIMEOUT_US 10000 // 10ms
|
|
|
|
|
|
|
|
#define BATTERY_REF_HW 1
|
|
#define BATTERY_REF_SW 1
|
|
#define BATTERY_SN_PN_HI 1
|
|
#define BATTERY_SN_PN_LO 1
|
|
#define BATTERY_SN_ITEM_HI 1
|
|
#define BATTERY_SN_ITEM_LO 1
|
|
#define BATTERY_STATUS_VBATT_HI 1
|
|
#define BATTERY_STATUS_VBATT_LO 1
|
|
#define BATTERY_STATUS_LEVEL 1
|
|
#define BATTERY_STATS_VBATTMAX 1
|
|
#define BATTERY_STATS_VBATTMIN 1
|
|
#define BATTERY_STATS_VBATTMEA 1
|
|
#define BATTERY_STATS_VBATTMEAN 1
|
|
#define BATTERY_STATS_RESET_HI 1
|
|
#define BATTERY_STATS_RESET_LO 1
|
|
#define BATTERY_STSTS_GGJSRCALIB 1
|
|
|
|
#define BATTERY_STSTS_VCTRLSHORTS 1
|
|
#define BATTERY_STATS_LMD_HI 1
|
|
#define BATTERY_STATS_LMD_LO 1
|
|
#define BATTERY_CONFIG_CELLCAPACITY_HI 1
|
|
#define BATTERY_CONFIG_CELLCAPACITY_LO 1
|
|
|
|
#define BATTERY_STATS_CHARGETIMEWORST_HI 1
|
|
#define BATTERY_STATS_CHARGETIMEWORST_LO 1
|
|
#define BATTERY_STATS_CHARGETIMEMEAN_HI 1
|
|
#define BATTERY_STATS_CHARGETIMEMEAN_LO 1
|
|
#define BATTERY_STATS_BATTCYCLES_HI 1
|
|
#define BATTERY_STATS_BATTCYCLES_LO 1
|
|
#define BATTERY_STATS_BATTFULLCYCLES_HI 1
|
|
#define BATTERY_STATS_BATTFULLCYCLES_LO 1
|
|
#define BATTERY_STATS_POWERCYCLES_HI 1
|
|
#define BATTERY_STATS_POWERCYCLES_LO 1
|
|
|
|
#define BATTERY_STATS_TBATTMAX 1
|
|
#define BATTERY_STATS_TBATTMIN 1
|
|
#define MOTOR_REF_HW 1
|
|
#define MOTOR_REF_SW 1
|
|
#define MOTOR_REALTIME_TEMP 1
|
|
#define MOTOR_SN_PN_HI 1
|
|
#define MOTOR_SN_PN_LO 1
|
|
#define MOTOR_SN_ITEM_HI 1
|
|
#define MOTOR_SN_ITEM_LO 1
|
|
|
|
#define CONSOLE_STATUS_SLAVE 1
|
|
#define BATTERY_CONFIG_SHUTDOWN 1
|
|
|
|
#define CONSOLE_ASSIST_MAXSPEEDFLAG 1
|
|
#define CONSOLE_ASSIST_MAXSPEED_HI 1
|
|
#define CONSOLE_ASSIST_MAXSPEED_LO 1
|
|
#define MOTOR_PROTECT_UNLOCK 1
|
|
#define MOTOR_PROTECT_UNLOCK_KEY 1
|
|
#define MOTOR_ASSIST_MAXSPEED 1
|
|
#define CONSOLE_GEOMETRY_CIRC_HI 1
|
|
#define CONSOLE_GEOMETRY_CIRC_LO1
|
|
|
|
#define CONSOLE_GEOMETRY_CIRC_LO 1
|
|
#define MOTOR_GEOMETRY_CIRC_HI1
|
|
#define MOTOR_GEOMETRY_CIRC_HI 1
|
|
#define MOTOR_GEOMETRY_CIRC_LO 1
|
|
#define CONSOLE_ASSIST_MINSPEEDFLAG 1
|
|
#define CONSOLE_ASSIST_MINSPEED 1
|
|
|
|
#define CONSOLE_THROTTLE_MAXSPEEDFLAG 1
|
|
#define CONSOLE_THROTTLE_MAXSPEED_HI 1
|
|
#define CONSOLE_THROTTLE_MAXSPEED_LO 1
|
|
|
|
#define BATTERY_CONFIG_PACKSERIAL 1
|
|
#define BATTERY_CELLMON_BALANCERENABLED 1
|
|
#define BATTERY_CONFIG_PACKPARALLEL 1
|
|
#define BATTERY_CELLMON_CHANNELADDR 1
|
|
#define BATTERY_CELLMON_CHANNELDATA_HI 1
|
|
|
|
#define BATTERY_STATUS_PACKTEMPERATURE1 1
|
|
|
|
#define BATTERY_CELLMON_CHANNELDATA_LO 1
|
|
|
|
#define CONSOLE_REF_HW 1
|
|
#define CONSOLE_REF_SW 1
|
|
#define CONSOLE_ASSIST_INITLEVEL 1
|
|
#define CONSOLE_SN_PN_HI 1
|
|
#define CONSOLE_SN_PN_LO 1
|
|
#define CONSOLE_SN_ITEM_HI 1
|
|
#define CONSOLE_SN_ITEM_LO 1
|
|
#define CONSOLE_ASSIST_MOUNTAINCAP 1
|
|
#define CONSOLE_STATS_BCValueTypeWord_1 1
|
|
#define CONSOLE_STATS_BCValueTypeWord_2 1
|
|
#define CONSOLE_STATS_BCValueTypeWord_3 1
|
|
|
|
#define CONSOLE_STATS_BCValueTypeWord_4 1
|
|
|
|
#define doSleep(x) usleep(x*1000)
|
|
|
|
int gAssistInitLevel = -1, gPrintSystemSettings = 0, gSkipShutdown = 0, gPowerOff = 0, gConsoleSetSlaveMode = 1, gNoSerialNumbers = 0, gSetMountainCap = -1, gSetWheelCircumference = 0;
|
|
double gSetSpeedLimit = -1, gSetMinSpeedLimit = -1, gSetThrottleSpeedLimit = -1;
|
|
|
|
#define CONSOLE 1
|
|
#define MOTOR 2
|
|
#define BATTERY 3
|
|
#define BIB 4
|
|
|
|
/*
|
|
class ThemeSwitchButton : public QPushButton {
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit ThemeSwitchButton(QWidget *parent = nullptr)
|
|
: QPushButton(parent), m_isDarkMode(true)
|
|
{
|
|
// 1. Visuelles Setup: Flach, keine Ränder, Hand-Cursor
|
|
setFlat(true);
|
|
setCursor(Qt::PointingHandCursor);
|
|
setFixedSize(32, 24); // Kleiner Footprint im StatusBar
|
|
|
|
// CSS: Transparent, damit es sich nahtlos in den StatusBar einfügt
|
|
// Schriftgröße etwas erhöhen, damit die Emojis gut erkennbar sind
|
|
setStyleSheet(R"(
|
|
QPushButton {
|
|
border: none;
|
|
background-color: transparent;
|
|
font-size: 14pt;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: rgba(128, 128, 128, 30); // Leichter Hover-Effekt
|
|
border-radius: 4px;
|
|
}
|
|
)");
|
|
|
|
// 2. Initialer Status (Startet im Dark Mode -> zeigt Mond)
|
|
updateIcon();
|
|
|
|
// 3. Klick verbinden
|
|
connect(this, &QPushButton::clicked, this, &ThemeSwitchButton::toggle);
|
|
}
|
|
|
|
signals:
|
|
void themeChanged(bool isDark);
|
|
|
|
private slots:
|
|
void toggle() {
|
|
m_isDarkMode = !m_isDarkMode;
|
|
updateIcon();
|
|
emit themeChanged(m_isDarkMode);
|
|
}
|
|
|
|
private:
|
|
void updateIcon() {
|
|
// Logik:
|
|
// Ist Dark Mode an? Zeige Mond (oder Sonne, je nach Geschmack).
|
|
// Hier: Zeige das Symbol des AKTUELLEN Modus.
|
|
setText(m_isDarkMode ? "🌙" : "☀️");
|
|
setToolTip(m_isDarkMode ? "Switch to Light Mode" : "Switch to Dark Mode");
|
|
}
|
|
|
|
bool m_isDarkMode;
|
|
};
|
|
*/
|
|
|
|
/*
|
|
class MainWindow : public QMainWindow
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
MainWindow(QWidget *parent = nullptr)
|
|
: QMainWindow(parent)
|
|
{
|
|
setWindowTitle("Fluent Theme Switcher");
|
|
resize(800, 600);
|
|
|
|
// --- STATUSBAR SETUP ---
|
|
QStatusBar *statBar = statusBar();
|
|
|
|
// Optional: Normale Nachricht links
|
|
statBar->showMessage("Ready");
|
|
|
|
// 1. Unseren Switcher erstellen
|
|
ThemeSwitchButton *themeBtn = new ThemeSwitchButton(this);
|
|
|
|
// 2. WICHTIG: Rechts hinzufügen
|
|
statBar->addPermanentWidget(themeBtn);
|
|
|
|
// 3. Signal verbinden: Button klick -> Theme ändern
|
|
connect(themeBtn, &ThemeSwitchButton::themeChanged, this, [this](bool isDark){
|
|
if (isDark) {
|
|
applyFluentDarkTheme(*qApp); // Funktion von vorhin
|
|
statusBar()->showMessage("Dark Mode Activated", 3000);
|
|
} else {
|
|
applyFluentLightTheme(*qApp); // Funktion von vorhin
|
|
statusBar()->showMessage("Light Mode Activated", 3000);
|
|
}
|
|
});
|
|
|
|
// Initiale Anwendung (Dark Mode)
|
|
applyFluentDarkTheme(*qApp);
|
|
}
|
|
};
|
|
*/
|
|
|
|
char *getNodeName(unsigned char id)
|
|
{
|
|
if (id == CONSOLE)
|
|
return "console";
|
|
else if (id == BATTERY)
|
|
return "battery";
|
|
else if (id == MOTOR)
|
|
return "motor";
|
|
else if (id == BIB)
|
|
return "bib";
|
|
else
|
|
return "UNKNOWN";
|
|
}
|
|
|
|
void setValue(unsigned char receipient, unsigned char reg, unsigned char value)
|
|
{
|
|
struct TCanMsg msg;
|
|
int timeout = TIMEOUT_VALUE;
|
|
|
|
msg.MsgFlags = 0L;
|
|
msg.Id = receipient;
|
|
msg.MsgLen = 4;
|
|
msg.MsgData[0] = 0x00;
|
|
msg.MsgData[1] = reg;
|
|
msg.MsgData[2] = 0x00;
|
|
msg.MsgData[3] = value;
|
|
|
|
CanTransmit(0, &msg, 1);
|
|
|
|
while(timeout-- && CanTransmitGetCount(0))
|
|
usleep(TIMEOUT_US);
|
|
|
|
if (timeout == -1)
|
|
printf("error: could not send value to %s" _NL, getNodeName(receipient));
|
|
}
|
|
|
|
unsigned int getValue(unsigned char receipient, unsigned char reg)
|
|
{
|
|
struct TCanMsg msg;
|
|
int err, retry = 20;
|
|
int timeout = TIMEOUT_VALUE;
|
|
|
|
msg.MsgFlags = 0L;
|
|
msg.Id = receipient;
|
|
msg.MsgLen = 2;
|
|
msg.MsgData[0] = 0x00;
|
|
msg.MsgData[1] = reg;
|
|
|
|
CanTransmit(0, &msg, 1);
|
|
|
|
while(timeout-- && CanTransmitGetCount(0))
|
|
usleep(TIMEOUT_US);
|
|
|
|
if (timeout == -1)
|
|
printf("error: could not send value to node %s" _NL, getNodeName(receipient));
|
|
|
|
retry:
|
|
|
|
timeout = TIMEOUT_VALUE;
|
|
while(timeout-- && !CanReceiveGetCount(0))
|
|
usleep(TIMEOUT_US);
|
|
|
|
if (timeout == -1)
|
|
{
|
|
printf("error: no response from node %s" _NL, getNodeName(receipient));
|
|
return 0;
|
|
}
|
|
|
|
if ((err = CanReceive(0, &msg, 1)) > 0)
|
|
{
|
|
if (--retry && (msg.Id != BIB || msg.MsgLen != 4 || msg.MsgData[1] != reg))
|
|
goto retry;
|
|
|
|
if (!retry)
|
|
{
|
|
printf("error: no response from node %s to %s" _NL, getNodeName(receipient), getNodeName(BIB));
|
|
return 0;
|
|
}
|
|
|
|
return (unsigned int) msg.MsgData[3];
|
|
}
|
|
else
|
|
{
|
|
printf("Error: %d" _NL, err);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void setSpeedLimit(double speed)
|
|
{
|
|
int limit = (speed != 0);
|
|
|
|
if (!speed)
|
|
speed = UNLIMITED_SPEED_VALUE;
|
|
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEEDFLAG, limit);
|
|
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_HI, ((int)(speed * 10)) >> 8);
|
|
setValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_LO, ((int)(speed * 10)) & 0xff);
|
|
setValue(MOTOR, MOTOR_PROTECT_UNLOCK, MOTOR_PROTECT_UNLOCK_KEY);
|
|
setValue(MOTOR, MOTOR_ASSIST_MAXSPEED, (int)speed);
|
|
}
|
|
|
|
|
|
void setWheelCircumference(unsigned short circumference)
|
|
{
|
|
if (!circumference)
|
|
return;
|
|
|
|
setValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_HI, (int) (circumference >> 8));
|
|
setValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_LO, (int) (circumference & 0xff));
|
|
setValue(MOTOR, MOTOR_PROTECT_UNLOCK, MOTOR_PROTECT_UNLOCK_KEY);
|
|
setValue(MOTOR, MOTOR_GEOMETRY_CIRC_HI, (int) (circumference >> 8));
|
|
setValue(MOTOR, MOTOR_GEOMETRY_CIRC_LO, (int) (circumference & 0xff));
|
|
}
|
|
|
|
void setMinSpeedLimit(double speed)
|
|
{
|
|
char limit = (speed != 0);
|
|
|
|
setValue(CONSOLE, CONSOLE_ASSIST_MINSPEEDFLAG, limit);
|
|
setValue(CONSOLE, CONSOLE_ASSIST_MINSPEED, (int)(speed * 10));
|
|
}
|
|
|
|
|
|
void setThrottleSpeedLimit(double speed)
|
|
{
|
|
int limit = (speed != 0);
|
|
|
|
if (!speed)
|
|
speed = MAX_THROTTLE_SPEED_VALUE;
|
|
|
|
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEEDFLAG, limit);
|
|
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_HI, ((int)(speed * 10)) >> 8);
|
|
setValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_LO, ((int)(speed * 10)) & 0xff);
|
|
}
|
|
|
|
void printBatteryStats()
|
|
{
|
|
int channel = 1, packSerial, packParallel;
|
|
|
|
printf( " balancer enabled ...: %s" _NL _NL, (getValue(BATTERY, BATTERY_CELLMON_BALANCERENABLED != 0) ? "yes" : "no"));
|
|
|
|
packSerial = getValue(BATTERY, BATTERY_CONFIG_PACKSERIAL);
|
|
packParallel = getValue(BATTERY, BATTERY_CONFIG_PACKPARALLEL);
|
|
|
|
packSerial = (packSerial > 20) ? 0 : packSerial;
|
|
packParallel = (packParallel > 20) ? 0 : packParallel;
|
|
|
|
for (;channel <= packSerial; channel++) {
|
|
setValue(BATTERY, BATTERY_CELLMON_CHANNELADDR, (int)0x80 + channel);
|
|
printf(" voltage cell #%02d ...: %.3fV" _NL, channel,
|
|
((getValue(BATTERY, BATTERY_CELLMON_CHANNELDATA_HI) << 8) + getValue(BATTERY,BATTERY_CELLMON_CHANNELDATA_LO)) * 0.001);
|
|
}
|
|
|
|
for (channel = 0 ; channel < packParallel ; channel ++)
|
|
printf(" temperature pack #%02d: %d" _DEGREE_SIGN "C" _NL, channel + 1,
|
|
getValue(BATTERY, BATTERY_STATUS_PACKTEMPERATURE1 + channel));
|
|
|
|
printf(_NL);
|
|
}
|
|
|
|
void printChargeStats() {
|
|
int channel = 1, totalChagres = 0, c;
|
|
|
|
for (channel = 1 ; channel <= 10; channel++) {
|
|
setValue(BATTERY, 0xf6, channel);
|
|
c = (getValue(BATTERY, 0xf7) << 8) + getValue(BATTERY,0xf8);
|
|
totalChagres += c;
|
|
printf(" charge level @ %03d%% : %04d" _NL, channel*10, c);
|
|
}
|
|
|
|
printf(" total # of charges .: %04d" _NL _NL, totalChagres);
|
|
}
|
|
|
|
double getVoltageValue(unsigned char in, unsigned char reg)
|
|
{
|
|
return (getValue(BATTERY, reg) + 20.8333) * 0.416667;
|
|
}
|
|
|
|
void usage(void) {
|
|
printf( "usage:" _NL
|
|
" -l <speedLimit> .......... set the speed limit to <speedLimit> (1 - " __STR(UNLIMITED_SPEED_VALUE) "), 0 = remove the limit" _NL );
|
|
}
|
|
|
|
int parseOptions(int argc, char **argv)
|
|
{
|
|
int oc;
|
|
char odef[] = "l:t:m:sa:pnxio:c:h?";
|
|
|
|
while((oc = getopt(argc,argv,odef)) != -1) {
|
|
switch(oc) {
|
|
case 'p':
|
|
gPowerOff = 1;
|
|
break;
|
|
case 'x':
|
|
gSkipShutdown = 1;
|
|
break;
|
|
case 'l':
|
|
gSetSpeedLimit = atof(optarg);
|
|
if (gSetSpeedLimit > UNLIMITED_SPEED_VALUE || gSetSpeedLimit < 0) {
|
|
printf("error: speed limit %.2f is out of range. exiting..." _NL, gSetSpeedLimit);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 't':
|
|
gSetThrottleSpeedLimit = atof(optarg);
|
|
if (gSetThrottleSpeedLimit > MAX_THROTTLE_SPEED_VALUE || gSetThrottleSpeedLimit < 0) {
|
|
printf("error: throttle speed limit %.2f is out of range. exiting..." _NL, gSetThrottleSpeedLimit);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'm':
|
|
gSetMinSpeedLimit = atof(optarg);
|
|
if (gSetMinSpeedLimit > UNLIMITED_MIN_SPEED_VALUE || gSetMinSpeedLimit < 0) {
|
|
printf("error: min speed limit %.2f is out of range. exiting..." _NL, gSetMinSpeedLimit);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'a':
|
|
gAssistInitLevel = atoi(optarg);
|
|
if (gAssistInitLevel > 4 || gAssistInitLevel < 0) {
|
|
printf("error: initial assist level %d is out of range. exiting..." _NL, gAssistInitLevel);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'o':
|
|
gSetMountainCap = atoi(optarg);
|
|
if (gSetMountainCap > 100 || gSetMountainCap < 0) {
|
|
printf("error: mountain cap level %d is out of range. exiting..." _NL, gSetMountainCap);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'c':
|
|
gSetWheelCircumference = atoi(optarg);
|
|
if (gSetWheelCircumference > 3000 || gSetWheelCircumference < 1000) {
|
|
printf("error: wheel circumference %d is out of range. exiting..." _NL, gSetWheelCircumference);
|
|
return -1;
|
|
}
|
|
break;
|
|
case 'n':
|
|
gConsoleSetSlaveMode = 0;
|
|
break;
|
|
case 'i':
|
|
gNoSerialNumbers = 1;
|
|
break;
|
|
case 's':
|
|
gPrintSystemSettings = 1;
|
|
break;
|
|
case 'h':
|
|
case '?':
|
|
default:
|
|
usage();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void printSystemSettings()
|
|
{
|
|
int hwVersion, swVersion, wheelCirc;
|
|
char *sl;
|
|
double speedLimit = 0;
|
|
|
|
printf(_NL _NL);
|
|
|
|
hwVersion = getValue(CONSOLE, CONSOLE_REF_HW);
|
|
|
|
if (hwVersion == 0)
|
|
printf("Console not responding" _NL _NL);
|
|
else {
|
|
swVersion = getValue(CONSOLE, CONSOLE_REF_SW);
|
|
printf( "Console information:" _NL
|
|
" hardware version ........: %02d" _NL
|
|
" software version ........: %02d" _NL
|
|
" assistance level ........: %d" _NL,
|
|
hwVersion, swVersion,
|
|
getValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL)
|
|
);
|
|
|
|
if (!gNoSerialNumbers)
|
|
printf( " part number .............: %05d" _NL
|
|
" item number .............: %05d" _NL _NL,
|
|
((getValue(CONSOLE, CONSOLE_SN_PN_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_PN_LO)),
|
|
((getValue(CONSOLE, CONSOLE_SN_ITEM_HI) << 8) + getValue(CONSOLE, CONSOLE_SN_ITEM_LO))
|
|
);
|
|
|
|
/* ASSIST speed limit */
|
|
sl = getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
|
|
speedLimit = ((getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_HI) << 8) + getValue(CONSOLE, CONSOLE_ASSIST_MAXSPEED_LO)) / (double)10;
|
|
printf( " max limit enabled .......: %s" _NL
|
|
" speed limit .............: %0.2f Km/h" _NL _NL, sl, speedLimit);
|
|
|
|
/* MIN speed limit */
|
|
sl = getValue(CONSOLE, CONSOLE_ASSIST_MINSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
|
|
speedLimit = (getValue(CONSOLE, CONSOLE_ASSIST_MINSPEED)) / (double)10;
|
|
printf( " min limit enabled .......: %s" _NL
|
|
" min speed limit .........: %0.2f Km/h" _NL _NL, sl, speedLimit);
|
|
|
|
/* THROTTLE speed limit */
|
|
sl = getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEEDFLAG) == 0 ? (char*)"no" : (char*)"yes";
|
|
speedLimit = ((getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_HI) << 8) + getValue(CONSOLE, CONSOLE_THROTTLE_MAXSPEED_LO)) / (double)10;
|
|
printf( " throttle limit enabled ..: %s" _NL
|
|
" throttle speed limit ....: %0.2f Km/h" _NL _NL, sl, speedLimit);
|
|
|
|
/* WHEEL CIRCUMFERENCE */
|
|
wheelCirc = (getValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_HI) << 8) + getValue(CONSOLE, CONSOLE_GEOMETRY_CIRC_LO);
|
|
printf( " wheel circumference .....: %d mm" _NL _NL, wheelCirc);
|
|
|
|
if (swVersion >= 59)
|
|
printf(
|
|
" mountain cap ............: %0.2f%%" _NL,
|
|
(getValue(CONSOLE, CONSOLE_ASSIST_MOUNTAINCAP) * 1.5625));
|
|
|
|
printf( " odo .....................: %0.2f Km" _NL _NL,
|
|
((getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_1) << 24) +
|
|
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_2) << 16) +
|
|
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_3) << 8) +
|
|
(getValue(CONSOLE, CONSOLE_STATS_BCValueTypeWord_4))) / (double)10
|
|
);
|
|
}
|
|
|
|
hwVersion = getValue(BATTERY, BATTERY_REF_HW);
|
|
if (hwVersion == 0)
|
|
printf("Battery not responding" _NL _NL);
|
|
else {
|
|
printf( "Battery information:" _NL
|
|
" hardware version ........: %02d" _NL
|
|
" software version ........: %02d" _NL,
|
|
hwVersion, getValue(BATTERY, BATTERY_REF_SW)
|
|
);
|
|
|
|
if (!gNoSerialNumbers)
|
|
printf( " part number .............: %05d" _NL
|
|
" item number .............: %05d" _NL,
|
|
((getValue(BATTERY, BATTERY_SN_PN_HI) << 8) + getValue(BATTERY, BATTERY_SN_PN_LO)),
|
|
((getValue(BATTERY, BATTERY_SN_ITEM_HI) << 8) + getValue(BATTERY, BATTERY_SN_ITEM_LO))
|
|
);
|
|
|
|
printf( " voltage .................: %0.2fV" _NL
|
|
" battery level ...........: %0.2f%%" _NL
|
|
" maximum voltage .........: %0.2f%%" _NL
|
|
" minimum voltage .........: %0.2f%%" _NL
|
|
" mean voltage ............: %0.2f%%" _NL
|
|
" resets ..................: %0d" _NL
|
|
" ggjrCalib ...............: %0d" _NL
|
|
" vctrlShorts .............: %0d" _NL
|
|
" lmd .....................: %0.2fAh" _NL
|
|
" cell capacity ...........: %0.2fAh" _NL _NL,
|
|
((getValue(BATTERY, BATTERY_STATUS_VBATT_HI) << 8) + getValue(BATTERY, BATTERY_STATUS_VBATT_LO)) * 0.001,
|
|
(getValue(BATTERY, BATTERY_STATUS_LEVEL) * 6.6667),
|
|
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMAX),
|
|
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMIN),
|
|
getVoltageValue(BATTERY, BATTERY_STATS_VBATTMEAN),
|
|
(getValue(BATTERY, BATTERY_STATS_RESET_HI) << 8) + getValue(BATTERY, BATTERY_STATS_RESET_LO),
|
|
getValue(BATTERY, BATTERY_STSTS_GGJSRCALIB),
|
|
getValue(BATTERY, BATTERY_STSTS_VCTRLSHORTS),
|
|
((getValue(BATTERY, BATTERY_STATS_LMD_HI) << 8) + getValue(BATTERY, BATTERY_STATS_LMD_LO)) * 0.002142,
|
|
((getValue(BATTERY, BATTERY_CONFIG_CELLCAPACITY_HI) << 8) + getValue(BATTERY, BATTERY_CONFIG_CELLCAPACITY_LO)) * 0.001
|
|
);
|
|
|
|
|
|
printf( " charge time worst .......: %0d" _NL
|
|
" charge time mean ........: %0d" _NL
|
|
" charge cycles ...........: %0d" _NL
|
|
" full charge cycles ......: %0d" _NL
|
|
" power cycles ............: %0d" _NL
|
|
" battery temp max ........: %0d" _NL
|
|
" battery temp min ........: %0d" _NL _NL,
|
|
(getValue(BATTERY, BATTERY_STATS_CHARGETIMEWORST_HI) << 8) + getValue(BATTERY, BATTERY_STATS_CHARGETIMEWORST_LO),
|
|
(getValue(BATTERY, BATTERY_STATS_CHARGETIMEMEAN_HI) << 8) + getValue(BATTERY, BATTERY_STATS_CHARGETIMEMEAN_LO),
|
|
(getValue(BATTERY, BATTERY_STATS_BATTCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_BATTCYCLES_LO),
|
|
(getValue(BATTERY, BATTERY_STATS_BATTFULLCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_BATTFULLCYCLES_LO),
|
|
(getValue(BATTERY, BATTERY_STATS_POWERCYCLES_HI) << 8) + getValue(BATTERY, BATTERY_STATS_POWERCYCLES_HI),
|
|
getValue(BATTERY, BATTERY_STATS_TBATTMAX),
|
|
getValue(BATTERY, BATTERY_STATS_TBATTMIN)
|
|
);
|
|
|
|
printChargeStats();
|
|
|
|
if (hwVersion >= 60)
|
|
printBatteryStats();
|
|
else
|
|
printf(" no battery details supported by battery hardware #%d" _NL _NL, hwVersion);
|
|
}
|
|
|
|
hwVersion = getValue(MOTOR, MOTOR_REF_HW);
|
|
if (hwVersion == 0)
|
|
printf("Motor not responding" _NL _NL);
|
|
else {
|
|
printf( "Motor information:" _NL
|
|
" hardware version ........: %02d" _NL
|
|
" software version ........: %02d" _NL
|
|
//" temperature .............: %02d" _DEGREE_SIGN "C"_NL
|
|
" speed limit .............: %02d Km/h" _NL,
|
|
hwVersion, getValue(MOTOR, MOTOR_REF_SW),
|
|
getValue(MOTOR, MOTOR_REALTIME_TEMP),
|
|
getValue(MOTOR, MOTOR_ASSIST_MAXSPEED)
|
|
);
|
|
|
|
wheelCirc = (getValue(MOTOR, MOTOR_GEOMETRY_CIRC_HI) << 8) + getValue(MOTOR, MOTOR_GEOMETRY_CIRC_LO);
|
|
printf( " wheel circumference .....: %d mm" _NL _NL, wheelCirc);
|
|
|
|
if (!gNoSerialNumbers)
|
|
printf( " part number .............: %05d" _NL
|
|
" item number .............: %05d" _NL _NL,
|
|
((getValue(MOTOR, MOTOR_SN_PN_HI) << 8) + getValue(MOTOR, MOTOR_SN_PN_LO)),
|
|
((getValue(MOTOR, MOTOR_SN_ITEM_HI) << 8) + getValue(MOTOR, MOTOR_SN_ITEM_LO))
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int xmain(int argc, char **argv)
|
|
{
|
|
int err, doShutdown = 0, consoleInSlaveMode = 0;
|
|
struct TDeviceStatus status;
|
|
|
|
printf("BigXionFlasher USB " __BXF_VERSION__ _NL " (c) 2011-2013 by Thomas Koenig <info@bigxionflasher.org> - www.bigxionflasher.org" _NL);
|
|
|
|
if ((err=parseOptions(argc, argv) < 0))
|
|
exit(1);
|
|
|
|
if ((err = LoadDriver(TREIBER_NAME)) < 0) {
|
|
printf("LoadDriver error: %d" _NL, err);
|
|
goto error;
|
|
}
|
|
|
|
if ((err = CanInitDriver(NULL)) < 0) {
|
|
printf("CanInitDriver error: %d" _NL, err);
|
|
goto error;
|
|
}
|
|
|
|
if ((err = CanDeviceOpen(0, DEVICE_OPEN)) < 0) {
|
|
printf("CanDeviceOpen error: %d" _NL, err);
|
|
goto error;
|
|
}
|
|
|
|
CanSetSpeed(0, CAN_125K_BIT);
|
|
CanSetMode(0, OP_CAN_START, CAN_CMD_ALL_CLEAR);
|
|
CanGetDeviceStatus(0, &status);
|
|
|
|
if (status.DrvStatus >= DRV_STATUS_CAN_OPEN) {
|
|
if (status.CanStatus == CAN_STATUS_BUS_OFF) {
|
|
printf("CAN Status BusOff" _NL);
|
|
CanSetMode(0, OP_CAN_RESET, CAN_CMD_NONE);
|
|
}
|
|
} else {
|
|
printf("error: could not open device" _NL);
|
|
goto error;
|
|
}
|
|
|
|
|
|
|
|
|
|
consoleInSlaveMode = getValue(CONSOLE, CONSOLE_STATUS_SLAVE);
|
|
if (consoleInSlaveMode) {
|
|
printf("console already in salve mode. good!" _NL _NL);
|
|
} else {
|
|
if (gConsoleSetSlaveMode) {
|
|
int retry = 20;
|
|
|
|
printf("putting console in salve mode ... ");
|
|
do {
|
|
setValue(CONSOLE, CONSOLE_STATUS_SLAVE, 1);
|
|
consoleInSlaveMode = getValue(CONSOLE, CONSOLE_STATUS_SLAVE);
|
|
usleep(200000);
|
|
} while(retry-- && !consoleInSlaveMode);
|
|
|
|
doSleep(500); // give the console some time to settle
|
|
printf("%s" _NL _NL, consoleInSlaveMode ? "done" : "failed");
|
|
} else
|
|
printf("console not in slave mode" _NL _NL);
|
|
}
|
|
|
|
if (gAssistInitLevel != -1) {
|
|
printf("setting initial assistance level to %d" _NL, gAssistInitLevel);
|
|
setValue(CONSOLE, CONSOLE_ASSIST_INITLEVEL, gAssistInitLevel);
|
|
}
|
|
|
|
if (gSetSpeedLimit > 0) {
|
|
printf("set speed limit to %0.2f km/h" _NL, gSetSpeedLimit);
|
|
setSpeedLimit(gSetSpeedLimit);
|
|
doShutdown = 1;
|
|
} else if (gSetSpeedLimit == 0) {
|
|
printf("disable speed limit, drive carefully" _NL);
|
|
setSpeedLimit(0);
|
|
doShutdown = 1;
|
|
}
|
|
|
|
if (gSetMinSpeedLimit > 0) {
|
|
printf("set minimal speed limit to %0.2f km/h" _NL, gSetMinSpeedLimit);
|
|
setMinSpeedLimit(gSetMinSpeedLimit);
|
|
doShutdown = 1;
|
|
} else if (gSetMinSpeedLimit == 0) {
|
|
printf("disable minimal speed limit, drive carefully" _NL);
|
|
setMinSpeedLimit(0);
|
|
doShutdown = 1;
|
|
}
|
|
|
|
if (gSetThrottleSpeedLimit > 0) {
|
|
printf("set throttle speed limit to %0.2f km/h" _NL, gSetThrottleSpeedLimit);
|
|
setThrottleSpeedLimit(gSetThrottleSpeedLimit);
|
|
doShutdown = 1;
|
|
} else if (gSetThrottleSpeedLimit == 0) {
|
|
printf("disable throttle speed limit, drive carefully" _NL);
|
|
setThrottleSpeedLimit(0);
|
|
doShutdown = 1;
|
|
}
|
|
|
|
if (gSetMountainCap > 0) {
|
|
printf("set mountain cap level to %0.2f%%" _NL, ((int)gSetMountainCap / 1.5625) * 1.5625);
|
|
setValue(CONSOLE, CONSOLE_ASSIST_MOUNTAINCAP, gSetMountainCap / 1.5625);
|
|
}
|
|
|
|
if (gSetWheelCircumference > 0) {
|
|
printf("set wheel circumference to %d" _NL, gSetWheelCircumference);
|
|
setWheelCircumference(gSetWheelCircumference);
|
|
}
|
|
|
|
if (gPrintSystemSettings)
|
|
printSystemSettings();
|
|
|
|
if ((doShutdown && !gSkipShutdown) || gPowerOff) {
|
|
doSleep(1000);
|
|
printf("shutting down system." _NL);
|
|
setValue(BATTERY, BATTERY_CONFIG_SHUTDOWN, 1);
|
|
}
|
|
|
|
CanDownDriver();
|
|
UnloadDriver();
|
|
|
|
return 0;
|
|
|
|
error:
|
|
CanDownDriver();
|
|
UnloadDriver();
|
|
|
|
return 1;
|
|
|
|
}
|