2 * This file is part of the sigrok project.
4 * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "channelform.h"
23 #include "ui_channelform.h"
26 extern uint8_t *sample_buffer;
28 /* WHEEL_DELTA was introduced in Qt 4.6, earlier versions don't have it. */
30 #define WHEEL_DELTA 120
33 static QColor channelColors[] = {
34 QColor(0x00, 0x00, 0x00), /* Black */
35 QColor(0x96, 0x4B, 0x00), /* Brown */
36 QColor(0xFF, 0x00, 0x00), /* Red */
37 QColor(0xFF, 0xA5, 0x00), /* Orange */
38 QColor(0xFF, 0xFF, 0x00), /* Yellow */
39 QColor(0x9A, 0xCD, 0x32), /* Green */
40 QColor(0x64, 0x95, 0xED), /* Blue */
41 QColor(0xEE, 0x82, 0xEE), /* Violet */
42 QColor(0xA0, 0xA0, 0xA0), /* Gray */
43 QColor(0xFF, 0xFF, 0xFF), /* White */
46 /* TODO: Should move elsewhere. */
47 static int getbit(uint8_t *buf, int numbyte, int chan)
50 return ((buf[numbyte] & (1 << chan))) >> chan;
51 } else if (chan >= 8 && chan < 16) {
52 return ((buf[numbyte + 1] & (1 << (chan - 8)))) >> (chan - 8);
54 /* Error. Currently only 8bit and 16bit LAs are supported. */
59 ChannelForm::ChannelForm(QWidget *parent) :
61 m_ui(new Ui::ChannelForm)
71 painterPath = new QPainterPath();
74 ChannelForm::~ChannelForm()
79 void ChannelForm::changeEvent(QEvent *e)
81 QWidget::changeEvent(e);
84 case QEvent::LanguageChange:
85 m_ui->retranslateUi(this);
92 void ChannelForm::generatePainterPath(void)
95 double old_x, current_x;
96 int current_y, oldval, newval, x_change_visible;
97 int low = m_ui->renderAreaWidget->height() - 2, high = 20;
98 int ch = getChannelNumber();
101 if (sample_buffer == NULL)
104 scaleFactor = getScaleFactor();
107 painterPath = new QPainterPath();
109 old_x = current_x = (-getScrollBarValue() % stepSize);
111 ss = (getScrollBarValue() + current_x) * scaleFactor / stepSize;
112 se = ss + (getScaleFactor() * width()) * stepSize;
113 if (se > getNumSamples()) /* Do this _after_ calculating 'step'! */
114 se = getNumSamples();
116 oldval = getbit(sample_buffer, ss, ch);
117 current_y = (oldval) ? high : low;
118 painterPath->moveTo(current_x, current_y);
120 // qDebug() << "generatePainterPath() for ch" << getChannelNumber()
121 // << "(" << ss << " - " << se << ")";
123 for (uint64_t i = ss; i < se; i += scaleFactor) {
124 /* Process the samples shown in this step. */
125 for (uint64_t j = 0; (j < scaleFactor) && (i + j < se); j++) {
126 newval = getbit(sample_buffer, i + j, ch);
127 x_change_visible = current_x > old_x;
128 if (oldval != newval && x_change_visible) {
129 painterPath->lineTo(current_x, current_y);
130 current_y = (newval) ? high : low;
131 painterPath->lineTo(current_x, current_y);
135 current_x += (double)stepSize / (double)scaleFactor;
138 current_x += stepSize;
139 painterPath->lineTo(current_x, current_y);
141 /* Force a redraw. */
145 void ChannelForm::resizeEvent(QResizeEvent *event)
147 /* Avoid compiler warnings. */
150 stepSize = width() / 100;
153 stepSize = width() / 50;
156 stepSize = width() / 20;
158 /* Quick hack to force a redraw upon resize. */
159 generatePainterPath();
162 void ChannelForm::paintEvent(QPaintEvent *event)
165 // qDebug() << "Paint event on ch" << getChannelNumber();
167 // QPainter p(m_ui->renderAreaWidget);
170 /* Avoid compiler warnings. */
173 if (sample_buffer == NULL)
176 QPen penChannel(getChannelColor(), 1, Qt::SolidLine, Qt::SquareCap,
178 p.setPen(penChannel);
179 p.fillRect(0, 0, this->width(), 5, getChannelColor());
180 p.fillRect(0, 5, 5, this->height(), getChannelColor());
183 QPen penGraph(QColor(0, 0, 0), 1, Qt::SolidLine, Qt::SquareCap,
187 // p.fillRect(0, 0, this->width(), this->height(), QColor(Qt::gray));
188 p.setRenderHint(QPainter::Antialiasing, false);
190 // p.scale(getZoomFactor(), 1.0);
191 p.drawPath(*painterPath);
195 /* Draw minor ticks. */
196 tickStart = -getScrollBarValue() % stepSize;
197 for (int i = tickStart; i < width(); i += stepSize)
198 p.drawLine(i, 12, i, 15);
201 /* Draw major ticks every 10 minor tick. */
202 tickStart = -getScrollBarValue() % (stepSize*10);
203 for (int i = tickStart; i < width(); i += stepSize * 10) {
204 p.drawText(i, 10, QString::number((i + getScrollBarValue()) / stepSize * getScaleFactor()));
205 p.drawLine(i, 11, i, 17);
210 void ChannelForm::wheelEvent(QWheelEvent *event)
212 float scaleFactorNew;
214 if ((event->delta() / WHEEL_DELTA) == 1)
215 scaleFactorNew = getScaleFactor() * 2;
216 else if ((event->delta() / WHEEL_DELTA) == -1)
217 scaleFactorNew = getScaleFactor() / 2;
219 scaleFactorNew = getScaleFactor();
221 if (scaleFactorNew < 1)
224 setScaleFactor(scaleFactorNew);
226 /* TODO: Config option to scroll (instead of scale) via the wheel. */
229 void ChannelForm::setChannelColor(QColor color)
231 channelColor = color;
233 /* Set color of the channel name QLineEdit. */
234 QLineEdit *l = m_ui->channelLineEdit;
235 QPalette p = QPalette(QApplication::palette());
236 p.setColor(QPalette::Base, channelColor);
240 QColor ChannelForm::getChannelColor(void)
245 void ChannelForm::setChannelNumber(int c)
247 if (channelNumber < 0) {
248 /* Set a default color for this channel. */
249 /* FIXME: Channel color should be dependent on the selected LA. */
250 setChannelColor(channelColors[c % (ARRAY_SIZE(channelColors))]);
254 /* Set title of the channel name QLineEdit. */
255 QLineEdit *l = m_ui->channelLineEdit;
256 l->setText(QString(tr("Channel %1")).arg(channelNumber));
259 int ChannelForm::getChannelNumber(void)
261 return channelNumber;
264 void ChannelForm::setNumSamples(uint64_t s)
269 uint64_t ChannelForm::getNumSamples(void)
274 uint64_t ChannelForm::getNumSamplesVisible(void)
276 return (width() / stepSize) * scaleFactor;
279 int ChannelForm::getStepSize(void)
284 void ChannelForm::setSampleStart(uint64_t s)
288 emit(sampleStartChanged(sampleStart));
289 emit(sampleStartChanged(QString::number(sampleStart)));
292 uint64_t ChannelForm::getSampleStart(void)
297 void ChannelForm::setSampleEnd(uint64_t e)
301 emit(sampleEndChanged(sampleEnd));
302 emit(sampleEndChanged(QString::number(sampleEnd)));
305 uint64_t ChannelForm::getSampleEnd(void)
310 void ChannelForm::setScaleFactor(float z)
314 emit(scaleFactorChanged(scaleFactor));
315 emit(scaleFactorChanged(QString::number(scaleFactor)));
318 float ChannelForm::getScaleFactor(void)
323 int ChannelForm::getScrollBarValue(void)
325 return scrollBarValue;
328 void ChannelForm::setScrollBarValue(int value)
330 if (scrollBarValue == value)
333 // qDebug("Re-generating ch%d (value = %d)", getChannelNumber(), value);
335 scrollBarValue = value;
336 generatePainterPath();