]> Shamusworld >> Repos - wozmaker/blob - src/waveformwidget.cpp
Flesh out the disk settings dialog.
[wozmaker] / src / waveformwidget.cpp
1 //
2 // waveformwidget.cpp: Track waveform window widget
3 //
4 // Part of the WOZ Maker project
5 // by James Hammons
6 // (C) 2018 Underground Software
7 //
8
9 #include "waveformwidget.h"
10 #include <math.h>
11 #include "dsp.h"
12 #include "fileio.h"
13 #include "global.h"
14
15
16 // Local variables
17 static uint32_t slip[6];
18 static bool foundBad = false;
19
20
21 WaveformWidget::WaveformWidget(QWidget * parent/*= 0*/): QWidget(parent)
22 {
23 #if 0
24         setGeometry(QRect(0, 0, 20, 240));
25         setMinimumHeight(240);
26         setMaximumHeight(240);
27 #else
28         setGeometry(QRect(0, 0, 20, 320));
29         setMinimumHeight(320);
30         setMaximumHeight(320);
31 #endif
32 }
33
34
35 WaveformWidget::~WaveformWidget(void)
36 {
37 }
38
39
40 void WaveformWidget::HandleUpdate(void)
41 {
42         // Set up vars that only change when the track changes...
43         uint32_t total = 0;
44         Global::streamCount = 0;
45         memset(slip, 0, sizeof(slip));
46         uint32_t xmax = 0;
47
48         // Find all non-BITS stream captures for this quarter-track
49         for(uint32_t i=0; i<Global::numStreams; i++)
50         {
51                 if ((Global::stream[i]->location != Global::trackNum)
52                         || (Global::stream[i]->captureType == 2))
53                         continue;
54
55                 uint32_t timeToNext = 0;
56                 uint32_t trackBytes = Uint32LE(Global::stream[i]->dataLength);
57
58                 // Set up stream vars for this track
59                 Global::streamData[Global::streamCount] = Global::stream[i]->data;
60                 Global::streamLen[Global::streamCount++] = trackBytes;
61
62                 // Save the stream number for later reference
63                 sNum[total++] = i;
64
65                 // Count time for this stream (skipping 0, because it doesn't count)
66                 for(uint32_t j=1; j<trackBytes; j++)
67                         timeToNext += Global::stream[i]->data[j];
68
69                 if ((timeToNext / 2) > xmax)
70                         xmax = timeToNext / 2;
71         }
72
73         Global::swLen = 0;
74
75 // !!! FIX !!! Need to take this out so it uses the already synthesized stuff done in the parallel thread...
76         if (Global::streamCount > 1)
77         {
78                 // Try aligning streams algorithmically...
79 //              FindSyncForStreams(slip, Global::streamCount);
80                 FindInitialSyncForStreams2(slip, Global::streamCount);
81 //              InitialSync(slip, Global::streamCount);
82 //              AttemptToFindStart(slip, Global::streamCount);
83                 Global::swLen = Synthesize2(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
84         }
85
86 for(uint32_t i=0; i<Global::streamCount; i++)
87 {       printf("Sync point %d: %d\n", sNum[i], slip[i]); }
88
89 #if 0
90 printf("Lookahead for track %.2f: %d\n", (float)Global::trackNum / 4.0f, Lookahead(slip, Global::streamCount, +1));
91 #endif
92
93         // And finally, update the display
94         setMinimumWidth(xmax);
95         setMaximumWidth(xmax);
96         update();
97 }
98
99
100 //#define PACKED
101 void WaveformWidget::HandleInitSync(void)
102 {
103 #ifdef PACKED
104         FindInitialSyncForStreams(slip, Global::streamCount);
105 #endif
106         foundBad = false;
107         update();
108
109 #if 1
110         printf("------------------------------\nInitial sync (%.2f): ", (float)Global::trackNum / 4.0f);
111         for(uint32_t i=0; i<Global::streamCount; i++)
112                 printf("<%d> ", slip[i]);
113         printf("\n\n");
114 #endif
115 }
116
117
118 void WaveformWidget::HandleStepBack(void)
119 {
120 #ifdef PACKED
121         static double a[10];
122 #endif
123         uint32_t minIdx = SmallestIndex(slip, Global::streamCount);
124
125         if (slip[minIdx] == 0)
126                 return;
127
128         if (!foundBad)
129         {
130 #ifdef PACKED
131                 StepBackUntilBad(slip, a, Global::streamCount);
132 #endif
133                 foundBad = true;
134
135                 for(uint32_t i=0; i<Global::streamCount; i++)
136                         printf("<%d> ", slip[i]);
137                 printf("\n");
138         }
139         else
140         {
141 #ifdef PACKED
142                 foundBad = StepBackThruBad(slip, a, Global::streamCount);
143 #endif
144         }
145
146         update();
147 }
148
149
150 void WaveformWidget::HandleManualSync(void)
151 {
152 #ifdef PACKED
153         double a[10];
154 #endif
155         foundBad = false;
156 #ifdef PACKED
157         StepBack(slip, a, Global::streamCount);
158 #endif
159         update();
160
161 #if 1
162         printf("------------------------------\nManual sync (%.2f): ", (float)Global::trackNum / 4.0f);
163         for(uint32_t i=0; i<Global::streamCount; i++)
164                 printf("<%d> ", slip[i]);
165         printf("\n\n");
166 #endif
167 }
168
169
170 void WaveformWidget::HandleZeroAll(void)
171 {
172         memset(slip, 0, sizeof(slip));
173         update();
174 }
175
176
177 void WaveformWidget::HandleSynthesize(void)
178 {
179 //      Global::swLen = Synthesize(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
180         Global::swLen = Synthesize2(slip, Global::streamCount, Global::synthWave, Global::swAmplitude);
181         emit(UpdateInfo());
182         update();
183 }
184
185
186 void WaveformWidget::HandleSynthesize2(void)
187 {
188         SynthesizeTrack(Global::trackNum);
189 //      emit(UpdateInfo());
190         update();
191 }
192
193
194 void WaveformWidget::HandleSync(int stream, int num)
195 {
196         if (stream > 9)
197                 return;
198
199         slip[stream] = num;
200         update();
201 }
202
203
204 void WaveformWidget::HandleWaveSync(int num)
205 {
206         Global::waveSync = num;
207         update();
208 }
209
210
211 void WaveformWidget::HandleRatio(int /*stream*/, int /*num*/)
212 {
213 //      if (stream > 9)
214 //              return;
215
216 //      ratio[stream] = (double)num / 1600000.0;
217         update();
218 }
219
220
221 /*
222 Now we have SynthesizeTrack(trackNo), so we can display the results of that here--including the loop point if we found one...
223
224 Now our analysis thread calcs it for us...  One less thing to worry about!
225 */
226
227 void WaveformWidget::paintEvent(QPaintEvent * event)
228 {
229         if (Global::a2r == NULL)
230                 return;
231
232         uint32_t xpos = event->rect().x();
233         uint32_t width = event->rect().width();
234
235         QPainter painter(this);
236         painter.setRenderHint(QPainter::Antialiasing);
237         QFont font;
238
239         font.setPixelSize(12);
240         font.setBold(true);
241         font.setStyleHint(QFont::TypeWriter);
242         painter.setFont(font);
243
244         QPen greenPen(QColor(0x66, 0x9E, 0x55, 0xFF), 2.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
245         QPen bluePen(QColor(0x20, 0x8F, 0xB5, 0xFF), 2.0, Qt::SolidLine);
246         QPen whitePen(Qt::white, 2.0, Qt::SolidLine);
247         QPen greyPen(QColor(0x4F, 0x49, 0x47, 0xFF), 2.0, Qt::SolidLine);
248         QPen orangePen(QColor(0xDE, 0x6A, 0x00, 0xFF), 2.0, Qt::SolidLine);
249
250 //BG: 3B3632, GRN: 669E55, BLU: 208FB5, V.Lines: 4F4947
251 // 12 (line + hex num), 3 space, 18 for trace, 7 after space
252 // 7px padding on top, 8px on bottom
253 // Nibble view is 52 x 12 bytes
254
255 //      float y = 7 + 12 + 18;
256         float y = 7 + 12 + 18 + (40 * 3);
257         float drawXPos = (xpos < 8 ? 0 : xpos - 8);
258         uint32_t wfNum = 0;
259
260 //printf("update: ");
261         for(uint32_t j=0; j<Global::numStreams; j++)
262         {
263                 if (Global::stream[j]->location != Global::trackNum)
264                         continue;
265
266                 float x = 0;
267                 float lastx = 0;
268 //              uint32_t trackBytes = Uint32LE(Global::stream[j]->dataLength);
269                 uint32_t trackBytes = Global::waveLen[j] - slip[wfNum];
270                 uint32_t estSplice = Uint32LE(Global::stream[j]->estLoopPoint);
271                 uint32_t byte = 1;
272                 uint32_t bytePos = 0;
273                 uint32_t bitCount = 1;
274 //              int32_t extra = (foundBad ? -1 : 0);
275                 uint32_t offset = slip[wfNum];
276 //printf("<%d> ", offset);
277
278                 if ((Global::stream[j]->captureType == 1) || (Global::stream[j]->captureType == 3))
279                 {
280                         for(uint32_t i=0; i<trackBytes; i++)
281                         {
282                                 uint32_t timeToNext = Global::wave[j][offset + i];
283
284 //                              if (i > 0)
285         //                              x += timeToNext / 2;
286                                         x += ((double)timeToNext / 2.0);
287
288 //                              if ((Global::stream[j]->data[offset + i] > 24) || (i == 0))
289                                 {
290                                         if (x >= drawXPos)
291                                         {
292                                                 if (x < (estSplice / 2))
293                                                         DrawPulse(&painter, &bluePen, lastx, x, y);
294                                                 else
295                                                         DrawPulse(&painter, Qt::magenta, lastx, x, y);
296
297                                                 lastx = x + 8.0;
298                                         }
299
300 //                                      if (i == 0)
301 //                                      {
302 //                                              byte = 1;
303 //                                              bitCount = 1;
304 //                                              bytePos = x;
305 //                                      }
306 //                                      else
307                                         {
308                                                 if ((timeToNext >= 24) && (timeToNext <= 49))
309                                                 {
310                                                         byte = (byte << 1) | 1;
311                                                         bitCount++;
312                                                 }
313                                                 else if ((timeToNext >= 50) && (timeToNext <= 80))
314                                                 {
315                                                         byte = (byte << 2) | 1;
316                                                         bitCount += 2;
317                                                 }
318                                                 else if ((timeToNext >= 81) && (timeToNext <= 112))
319                                                 {
320                                                         byte = (byte << 3) | 1;
321                                                         bitCount += 3;
322                                                 }
323                                                 else if ((timeToNext >= 113) && (timeToNext <= 137))
324                                                 {
325                                                         byte = (byte << 4) | 1;
326                                                         bitCount += 4;
327                                                 }
328                                                 else
329                                                 {
330                                                         // Handle zeros here...
331                                                         while (timeToNext > 32)
332                                                         {
333                                                                 byte <<= 1;
334                                                                 bitCount++;
335                                                                 timeToNext -= 32;
336                                                         }
337                                                 }
338                                         }
339
340                                         if (bitCount > 8)
341                                         {
342                                                 while (bitCount > 15)
343                                                         bitCount -= 8;
344
345                                                 uint16_t mask1[16] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF };
346                                                 uint16_t mask2[16] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
347                                                 uint8_t byteToShow = byte >> (bitCount - 8);
348                                                 bitCount -= 8;
349                                                 byte &= mask1[bitCount];
350                                                 uint8_t zeroes = 0;
351
352                                                 for(uint16_t z=bitCount; z>0; z--)
353                                                 {
354                                                         if ((byte & mask2[z - 1]) == 0)
355                                                         {
356                                                                 bitCount--;
357                                                                 zeroes++;
358                                                         }
359                                                         else
360                                                                 break;
361                                                 }
362
363                                                 char buf[10];
364                                                 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
365
366                                                 painter.setPen(whitePen);
367                                                 painter.drawText(bytePos, y - (18 + 6), buf);
368
369                                                 bytePos = x;
370
371                                                 if (bytePos > (xpos + width))
372                                                         break;
373                                         }
374                                 }
375                         }
376                 }
377                 else if (Global::stream[j]->captureType == 2)
378                 {
379                         // BITS capture
380 /*
381 x positions are 16 pix apart, ideally.  So to get the # of bits, we need to divide the width / 16.  To get the # of bytes, we then divide by 8.
382 */
383                         uint32_t bpStart = xpos / 16;
384                         x = bpStart * 16.0;
385
386                         for(uint32_t i=bpStart; i<bpStart+(width/16)+4; i++)
387                         {
388                                 if (Global::stream[j]->data[i / 8] & Global::bit[i % 8])
389                                 {
390                                         DrawPulse(&painter, Qt::cyan, lastx, x, y);
391                                         lastx = x + 8.0;
392                                 }
393
394                                 x += 16.0;
395                         }
396                 }
397
398                 y += 40.0;
399                 wfNum++;
400         }
401 //printf("\n");
402
403         if (Global::swLen == 0)
404                 return;
405
406         // Reset Y coord to the top
407         y = 7 + 12 + 18;
408         float x = 0;
409         float lastx = 0;
410         uint32_t byte = 1;
411         uint32_t bytePos = x;
412         uint32_t bitCount = 1;
413
414         DrawPulse(&painter, &greenPen, lastx, x, y);
415         lastx = x + 8.0;
416
417         for(uint32_t i=0; i<Global::swLen; i++)
418         {
419                 uint32_t timeToNext = Global::synthWave[i];
420                 x += (double)timeToNext / 2.0;
421
422                 if ((timeToNext > 0) || (i == 0))
423                 {
424                         if (x >= drawXPos)
425                         {
426                                 DrawPulse(&painter, &greenPen, lastx, x, y, Global::swAmplitude[i]);
427                                 lastx = x + 8.0;
428                         }
429
430                         if ((timeToNext >= 24) && (timeToNext <= 49))
431                         {
432                                 byte = (byte << 1) | 1;
433                                 bitCount++;
434                         }
435                         else if ((timeToNext >= 50) && (timeToNext <= 80))
436                         {
437                                 byte = (byte << 2) | 1;
438                                 bitCount += 2;
439                         }
440                         else if ((timeToNext >= 81) && (timeToNext <= 112))
441                         {
442                                 byte = (byte << 3) | 1;
443                                 bitCount += 3;
444                         }
445                         else if ((timeToNext >= 113) && (timeToNext <= 137))
446                         {
447                                 byte = (byte << 4) | 1;
448                                 bitCount += 4;
449                         }
450                         else
451                         {
452                                 // Handle zeros here...
453                                 while (timeToNext > 32)
454                                 {
455                                         byte <<= 1;
456                                         bitCount++;
457                                         timeToNext -= 32;
458                                 }
459                         }
460
461                         if (bitCount > 8)
462                         {
463                                 while (bitCount > 15)
464                                         bitCount -= 8;
465
466                                 uint16_t mask1[16] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF };
467                                 uint16_t mask2[16] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
468                                 uint8_t byteToShow = byte >> (bitCount - 8);
469                                 bitCount -= 8;
470                                 byte &= mask1[bitCount];
471                                 uint8_t zeroes = 0;
472
473                                 for(uint16_t z=bitCount; z>0; z--)
474                                 {
475                                         if ((byte & mask2[z - 1]) == 0)
476                                         {
477                                                 bitCount--;
478                                                 zeroes++;
479                                         }
480                                         else
481                                                 break;
482                                 }
483
484                                 char buf[10];
485                                 sprintf(buf, "|%02X%s", byteToShow, (zeroes == 0 ? "" : (zeroes == 1 ? "." : (zeroes == 2 ? ".." : "..."))));
486
487                                 painter.setPen(whitePen);
488                                 painter.drawText(bytePos, y - (18 + 6), buf);
489
490                                 bytePos = x;
491
492                                 if (bytePos > (xpos + width))
493                                         break;
494                         }
495                 }
496         }
497
498         if (Global::synWaveLen[Global::trackNum] == 0)
499                 return;
500
501         // Reset Y coord to the top
502         y = 7 + 12 + 18 + (40 * 1);
503         x = 0;
504         lastx = 0;
505
506         DrawPulse(&painter, &orangePen, lastx, x, y);
507         lastx = x + 8.0;
508
509         for(uint32_t i=0; i<Global::synWaveLen[Global::trackNum]; i++)
510         {
511                 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
512                 x += (double)timeToNext / 2.0;
513
514                 if (x >= drawXPos)
515                 {
516                         DrawPulse(&painter, &orangePen, lastx, x, y);
517                         lastx = x + 8.0;
518                 }
519
520                 char buf[10];
521
522                 if ((i % 10) == 0)
523                 {
524                         sprintf(buf, "|%d", i + 1);
525                         painter.setPen(whitePen);
526                         painter.drawText(x, y - (18 + 6), buf);
527                 }
528
529                 if (x > (xpos + width))
530                         break;
531         }
532
533         y = 7 + 12 + 18 + (40 * 2);
534         x = 0;
535         lastx = 0;
536
537         DrawPulse(&painter, &orangePen, lastx, x, y);
538         lastx = x + 8.0;
539
540         for(uint32_t i=Global::waveSync; i<Global::synWaveLen[Global::trackNum]; i++)
541         {
542                 uint32_t timeToNext = Global::synWave[Global::trackNum][i];
543                 x += (double)timeToNext / 2.0;
544
545                 if (x >= drawXPos)
546                 {
547                         DrawPulse(&painter, &orangePen, lastx, x, y);
548                         lastx = x + 8.0;
549                 }
550
551                 char buf[10];
552
553                 if ((i % 10) == 0)
554                 {
555                         sprintf(buf, "|%d", i + 1);
556                         painter.setPen(whitePen);
557                         painter.drawText(x, y - (18 + 6), buf);
558                 }
559
560                 if (x > (xpos + width))
561                         break;
562         }
563 }
564
565
566 void WaveformWidget::DrawPulse(QPainter * painter, QPen * pen, float lastx, float x, float y, float height/*= 1.0*/)
567 {
568         float yHeight = y - (17.0 * height);
569         painter->setPen(*pen);
570         painter->drawLine(lastx, y, x, y);
571         painter->drawLine(x, y, x + 4.0, y);
572         painter->drawLine(x + 4.0, y, x + 4.0, yHeight);
573         painter->drawLine(x + 4.0, yHeight, x + 8.0, yHeight);
574         painter->drawLine(x + 8.0, yHeight, x + 8.0, y);
575 }
576
577
578 void WaveformWidget::DrawPulse(QPainter * painter, Qt::GlobalColor color, float lastx, float x, float y, float height/*= 1.0*/)
579 {
580         QPen pen(color);
581         DrawPulse(painter, &pen, lastx, x, y, height);
582 }
583
584
585 void WaveformWidget::mousePressEvent(QMouseEvent * event)
586 {
587         if (event->button() == Qt::LeftButton)
588         {
589                 event->accept();
590         }
591 }
592
593
594 void WaveformWidget::mouseMoveEvent(QMouseEvent * event)
595 {
596         if (event->buttons() & Qt::LeftButton)
597         {
598                 event->accept();
599         }
600 }
601
602
603 void WaveformWidget::mouseReleaseEvent(QMouseEvent * event)
604 {
605         if (event->button() == Qt::LeftButton)
606         {
607                 event->accept();
608         }
609 }
610
611
612 void WaveformWidget::mouseDoubleClickEvent(QMouseEvent * event)
613 {
614         if (event->button() == Qt::LeftButton)
615         {
616                 event->accept();
617         }
618 }
619
620
621 void WaveformWidget::keyPressEvent(QKeyEvent * event)
622 {
623         int key = event->key();
624
625         if (key == Qt::Key_Up)
626         {
627         }
628         else if (key == Qt::Key_Down)
629         {
630         }
631         else if (key == Qt::Key_Left)
632         {
633         }
634         else if (key == Qt::Key_Right)
635         {
636         }
637         else
638                 return;
639
640         // Only update if a key we recognize has been pressed!
641         update();
642 }
643
644
645 void WaveformWidget::keyReleaseEvent(QKeyEvent * /*event*/)
646 {
647 }
648
649
650 void WaveformWidget::resizeEvent(QResizeEvent * /*event*/)
651 {
652 //      ResizeGrid();
653 }
654