diff --git a/src/Computrainer.cpp b/src/Computrainer.cpp index 40207ed41..d0c515579 100644 --- a/src/Computrainer.cpp +++ b/src/Computrainer.cpp @@ -373,7 +373,8 @@ void Computrainer::unpackTelemetry(int &ss1, int &ss2, int &ss3, int &buttons, i value12 = value8 | (b1&7)<<9 | (b3&2)<<7; if (buttons&64) { - memcpy((void*)spinScan, (void*)ss, 24); + memcpy((void*)spinScan, (void*)ss+3, 21); + memcpy((void*)spinScan+21, (void*)ss, 3); //for (pos=0; pos<24; pos++) fprintf(stderr, "%d, ", ss[pos]); //fprintf(stderr, "\n"); pos=0; diff --git a/src/SpinScanPlot.cpp b/src/SpinScanPlot.cpp index adacbea6a..8e06457b7 100644 --- a/src/SpinScanPlot.cpp +++ b/src/SpinScanPlot.cpp @@ -45,7 +45,7 @@ size_t SpinScanData::size() const { return 48; } QwtData *SpinScanData::copy() const { return new SpinScanData(spinData, isleft); } void SpinScanData::init() { } -SpinScanPlot::SpinScanPlot(uint8_t *spinData) : leftCurve(NULL), rightCurve(NULL), spinData(spinData) +SpinScanPlot::SpinScanPlot(QWidget *parent, uint8_t *spinData) : QwtPlot(parent), leftCurve(NULL), rightCurve(NULL), spinData(spinData) { setInstanceName("SpinScan Plot"); diff --git a/src/SpinScanPlot.h b/src/SpinScanPlot.h index 12f227791..c44e77833 100644 --- a/src/SpinScanPlot.h +++ b/src/SpinScanPlot.h @@ -64,7 +64,7 @@ class SpinScanPlot : public QwtPlot SpinScanData *leftSpinScanData; SpinScanData *rightSpinScanData; - SpinScanPlot(uint8_t *); + SpinScanPlot(QWidget *parent, uint8_t *); uint8_t *spinData; diff --git a/src/SpinScanPlotWindow.cpp b/src/SpinScanPlotWindow.cpp index c1c9e17b1..0d93b0055 100644 --- a/src/SpinScanPlotWindow.cpp +++ b/src/SpinScanPlotWindow.cpp @@ -24,9 +24,26 @@ SpinScanPlotWindow::SpinScanPlotWindow(MainWindow *mainWindow) : { setContentsMargins(0,0,0,0); setInstanceName("SpinScan Plot"); - setControls(NULL); setProperty("color", GColor(CRIDEPLOTBACKGROUND)); + // setup controls + QWidget *c = new QWidget; + QVBoxLayout *cl = new QVBoxLayout(c); + QHBoxLayout *style = new QHBoxLayout(); + cl->addLayout(style); + cl->addStretch(); + + QLabel *label = new QLabel("Style", this); + mode = new QComboBox(this); + mode->addItem("Bar"); + mode->addItem("Polar"); + + style->addWidget(label); + style->addWidget(mode); + style->addStretch(); + + setControls(c); + // init to zero history[0] = set1; history[1] = set2; @@ -46,8 +63,18 @@ SpinScanPlotWindow::SpinScanPlotWindow(MainWindow *mainWindow) : history[15] = set16; QVBoxLayout *layout = new QVBoxLayout(this); - rtPlot = new SpinScanPlot(spinData); - layout->addWidget(rtPlot); + stack = new QStackedWidget(this); + + rtPlot = new SpinScanPlot(this, spinData); + plPlot = new SpinScanPolarPlot(this, spinData); + + stack->addWidget(rtPlot); + stack->addWidget(plPlot); + + layout->addWidget(stack); + + // when we change styles.. + connect(mode, SIGNAL(currentIndexChanged(int)), this, SLOT(styleChanged())); // get updates.. connect(mainWindow, SIGNAL(telemetryUpdate(RealtimeData)), this, SLOT(telemetryUpdate(RealtimeData))); @@ -58,6 +85,20 @@ SpinScanPlotWindow::SpinScanPlotWindow(MainWindow *mainWindow) : stop(); // resets the array } +void +SpinScanPlotWindow::setStyle(int x) +{ + stack->setCurrentIndex(x); +} + +void +SpinScanPlotWindow::styleChanged() +{ + int index = mode->currentIndex(); + if (index < 0 || index > 1) return; + stack->setCurrentIndex(index); +} + void SpinScanPlotWindow::start() { @@ -96,5 +137,6 @@ SpinScanPlotWindow::telemetryUpdate(RealtimeData rtData) memcpy(history[current++], rtData.spinScan, 24); if (current==16) current=0; + plPlot->replot(); // redraw rtPlot->replot(); // redraw } diff --git a/src/SpinScanPlotWindow.h b/src/SpinScanPlotWindow.h index 0c0b2bdd6..1b18e1f9f 100644 --- a/src/SpinScanPlotWindow.h +++ b/src/SpinScanPlotWindow.h @@ -26,6 +26,7 @@ #include "MainWindow.h" #include "RideFile.h" // for data series types +#include "SpinScanPolarPlot.h" #include "SpinScanPlot.h" #include "RealtimeData.h" // for realtimedata structure @@ -37,6 +38,8 @@ class SpinScanPlotWindow : public GcWindow Q_OBJECT G_OBJECT + Q_PROPERTY(int style READ getStyle WRITE setStyle USER true) + public: SpinScanPlotWindow(MainWindow *mainWindow); @@ -49,6 +52,10 @@ class SpinScanPlotWindow : public GcWindow void stop(); void pause(); + int getStyle() const { return mode->currentIndex(); } + void setStyle(int x); + void styleChanged(); + private: // we keep 8 sets of spinscan data (last 2 seconds) @@ -80,9 +87,14 @@ class SpinScanPlotWindow : public GcWindow int current; MainWindow *mainWindow; + + QStackedWidget *stack; SpinScanPlot *rtPlot; + SpinScanPolarPlot *plPlot; uint8_t spinData[24]; // what we give to the plot + + QComboBox *mode; }; #endif // _GC_SpinScanPlotWindow_h diff --git a/src/SpinScanPolarPlot.cpp b/src/SpinScanPolarPlot.cpp new file mode 100644 index 000000000..d80d82dfd --- /dev/null +++ b/src/SpinScanPolarPlot.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2009 Mark Liversedge (liversedge@gmail.com) + * + * 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 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include +#include +#include +#include "SpinScanPolarPlot.h" +#include +#include "Colors.h" + +// to avoid excessive floating point operations when updating the display +// this is a precomputed value for cos(i*15) * (PI / 180) +static const double cosx[24] = { + 1.000000, 0.965926, 0.866026, 0.707107, 0.500001, 0.258820, + 0.000000, -0.258818, -0.499999, -0.707106, -0.866024, -0.965925, + -1.000000, -0.965926, -0.866027, -0.707109, -0.500003, -0.258822, + -0.000004, 0.258815, 0.499997, 0.707104, 0.866023, 0.965925 +}; + +// this is a precomputed value for sin(i*15) * (PI / 180) +static const double siny[24] = { + 0.000000, 0.258819, 0.500000, 0.707106, 0.866025, 0.965926, + 1.000000, 0.965926, 0.866026, 0.707108, 0.500002, 0.258821, + 0.000000, -0.258817, -0.499998, -0.707105, -0.866024, -0.965925, + -1.000000, -0.965927, -0.866027, -0.707110, -0.500004, -0.258823 +}; + +// SpinScan force/direction to cartesian for plotting +size_t SpinScanPolarData::size() const { return 13; } +QwtData *SpinScanPolarData::copy() const { return new SpinScanPolarData(spinData, isleft); } +void SpinScanPolarData::init() { } +double SpinScanPolarData::x(size_t i) const { i += isleft?0:12; if (i>=24) i=0; return cosx[i] * (double)spinData[i]; } +double SpinScanPolarData::y(size_t i) const { i += isleft?0:12; if (i>=24) i=0; return siny[i] * (double)spinData[i]; } + +// Original code before moving to precomputed constants +//double SpinScanPolarData::x(size_t i) const { if (i==24) i=0; return cos((i*15)*3.14159f/180.00f) * (double)spinData[i]; } +//double SpinScanPolarData::y(size_t i) const { if (i==24) i=0; return sin((i*15)*3.14159f/180.00f) * (double)spinData[i]; } + +SpinScanPolarPlot::SpinScanPolarPlot(QWidget *parent, uint8_t *spinData) : QwtPlot(parent), leftCurve(NULL), rightCurve(NULL), spinData(spinData) +{ + setInstanceName("SpinScan Plot"); + + // Setup the axis + setAxisTitle(yLeft, "SpinScan"); + setAxisMaxMinor(xBottom, 0); + setAxisMaxMinor(yLeft, 0); + + QPalette pal; + setAxisScale(yLeft, -90, 90); // max 8 bit plus a little + setAxisScale(xBottom, -90, 90); // max 8 bit plus a little + pal.setColor(QPalette::WindowText, GColor(CSPINSCANLEFT)); + pal.setColor(QPalette::Text, GColor(CSPINSCANLEFT)); + axisWidget(QwtPlot::yLeft)->setPalette(pal); + axisWidget(QwtPlot::yLeft)->scaleDraw()->setTickLength(QwtScaleDiv::MajorTick, 3); + + enableAxis(xBottom, false); // very little value and some cpu overhead + enableAxis(yLeft, false); + + rightCurve = new QwtPlotCurve("SpinScan Right"); + rightCurve->setRenderHint(QwtPlotItem::RenderAntialiased); // too cpu intensive + rightCurve->attach(this); + rightCurve->setYAxis(QwtPlot::yLeft); + rightSpinScanPolarData = new SpinScanPolarData(spinData, false); + + leftCurve = new QwtPlotCurve("SpinScan Left"); + leftCurve->setRenderHint(QwtPlotItem::RenderAntialiased); // too cpu intensive + leftCurve->attach(this); + leftCurve->setYAxis(QwtPlot::yLeft); + leftSpinScanPolarData = new SpinScanPolarData(spinData, true); + + canvas()->setFrameStyle(QFrame::NoFrame); + configChanged(); // set colors +} + +void +SpinScanPolarPlot::setAxisTitle(int axis, QString label) +{ + // setup the default fonts + QFont stGiles; // hoho - Chart Font St. Giles ... ok you have to be British to get this joke + stGiles.fromString(appsettings->value(this, GC_FONT_CHARTLABELS, QFont().toString()).toString()); + stGiles.setPointSize(appsettings->value(NULL, GC_FONT_CHARTLABELS_SIZE, 8).toInt()); + + QwtText title(label); + title.setFont(stGiles); + QwtPlot::setAxisFont(axis, stGiles); + QwtPlot::setAxisTitle(axis, title); +} + +void +SpinScanPolarPlot::configChanged() +{ + setCanvasBackground(GColor(CRIDEPLOTBACKGROUND)); + + QColor col = GColor(CSPINSCANRIGHT); + col.setAlpha(120); + QBrush brush = QBrush(col); + QPen pen(col); + pen.setWidth(4); // thicker pen + rightCurve->setBrush(Qt::NoBrush); + rightCurve->setPen(pen); + rightCurve->setStyle(QwtPlotCurve::Lines); + rightCurve->setData(*rightSpinScanPolarData); + + QColor col2 = GColor(CSPINSCANLEFT); + col2.setAlpha(120); + QBrush brush2 = QBrush(col2); + QPen pen2(col2); + pen2.setWidth(4); // thicker pen + leftCurve->setBrush(Qt::NoBrush); + leftCurve->setPen(pen2); + leftCurve->setStyle(QwtPlotCurve::Lines); + leftCurve->setData(*leftSpinScanPolarData); +} diff --git a/src/SpinScanPolarPlot.h b/src/SpinScanPolarPlot.h new file mode 100644 index 000000000..5e5d2cc27 --- /dev/null +++ b/src/SpinScanPolarPlot.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2009 Mark Liversedge (liversedge@gmail.com) + * + * 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 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _GC_SpinScanPolarPlot_h +#define _GC_SpinScanPolarPlot_h 1 +#include "GoldenCheetah.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Settings.h" + +#include //uint8_t + +class SpinScanPolarData : public QwtData +{ + bool isleft; + uint8_t *spinData; + + public: + SpinScanPolarData(uint8_t *spinData, bool isleft) : isleft(isleft), spinData(spinData) { init(); } + + double x(size_t i) const ; + double y(size_t i) const ; + size_t size() const ; + virtual QwtData *copy() const ; + void init() ; +}; + +class SpinScanPolarPlot : public QwtPlot +{ + Q_OBJECT + G_OBJECT + + private: + + QwtPlotCurve *leftCurve; + QwtPlotCurve *rightCurve; + + public: + void setAxisTitle(int axis, QString label); + + SpinScanPolarData *leftSpinScanPolarData; + SpinScanPolarData *rightSpinScanPolarData; + + SpinScanPolarPlot(QWidget *parent, uint8_t *); + + uint8_t *spinData; + + public slots: + void configChanged(); +}; + + + +#endif // _GC_SpinScanPolarPlot_h + diff --git a/src/src.pro b/src/src.pro index 04c4a8953..b580c775b 100644 --- a/src/src.pro +++ b/src/src.pro @@ -305,6 +305,7 @@ HEADERS += \ SimpleNetworkClient.h \ SpecialFields.h \ SpinScanPlot.h \ + SpinScanPolarPlot.h \ SpinScanPlotWindow.h \ SplitRideDialog.h \ SplitActivityWizard.h \ @@ -480,6 +481,7 @@ SOURCES += \ SmallPlot.cpp \ SpecialFields.cpp \ SpinScanPlot.cpp \ + SpinScanPolarPlot.cpp \ SpinScanPlotWindow.cpp \ SplitRideDialog.cpp \ SplitActivityWizard.cpp \