1 /*
2  * Author: spencer jackson 2014
3  *         ssjackson71@gmail.com
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21 
22 
23 #ifndef FFF_SCOPE_H
24 #define FFF_SCOPE_H
25 
26 
27 #include <FL/Fl_Widget.H>
28 #include <FL/Fl.H>
29 #include <valarray>
30 #include <string>
31 #include <cairo.h>
32 
33 //avtk drawing method (adapted)
default_scope_drawing(cairo_t * cr,float * data,unsigned short start)34 static void default_scope_drawing(cairo_t *cr,float *data,unsigned short start)
35 {
36     cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
37     cairo_set_line_width(cr,1);
38     cairo_set_miter_limit(cr,4);
39     cairo_set_source_rgb(cr,0,1,0);
40     cairo_new_path(cr);
41 
42     cairo_move_to(cr,100,100*data[start]);
43     for (int i=1; i<100; i++)
44     {
45         cairo_line_to(cr,100-i,100*data[(start-i)&0x07FF]);
46     }
47     cairo_stroke(cr);
48 };
49 
50 namespace ffffltk
51 {
52 
53 static void scope_callback(void* handle);
54 
55 class Scope: public Fl_Widget
56 {
57 public:
58     Scope(int _x, int _y, int _w, int _h, const char *_label = ""):
Fl_Widget(_x,_y,_w,_h,_label)59         Fl_Widget(_x, _y, _w, _h, _label)
60     {
61         x = _x;
62         y = _y;
63         w = _w;
64         h = _h;
65 
66         label = _label;
67 
68         drawing_w = 100;
69         drawing_h = 100;
70         drawing_f = &default_scope_drawing;
71 
72         average = false;
73         avg = 0;
74         p = 0;
75         nvals = 0;
76         min_val = 0;
77         max_val = 1;
78         for(int i=0; i<2048; i++)
79             data[i] = 0;
80         Fl::add_timeout(.10,scope_callback,this);
81     }
82 
~Scope()83     ~Scope()
84     {
85         Fl::remove_timeout(scope_callback);
86     }
87 
88     bool highlight;
89     int x, y, w, h;
90     const char* label;
91 
92     int drawing_w;
93     int drawing_h;
94     void (*drawing_f)(cairo_t*,float*, unsigned short);//pointer to draw function
95 
96     float data[2048];
97     int min_val;
98     int max_val;
99     bool average;
100 
101     float avg;
102     int p;
103     int nvals;
104 
push_val(float val)105     void push_val(float val)
106     {
107         if(average)
108         {
109             avg += val;
110             nvals++;
111         }
112         else
113         {
114             data[p++] = val;
115             p&=0x07FF;
116         }
117     }
118 
push_avg()119     void push_avg()
120     {
121         avg/= (double)nvals;
122         data[p++] = avg;
123         p&=0x07FF;
124         nvals = 0;
125     }
126 
draw()127     void draw()
128     {
129         if (damage() & FL_DAMAGE_ALL)
130         {
131             cairo_t *cr = Fl::cairo_cc();
132 
133             cairo_save( cr );
134 
135             //calcluate scale and centering
136             double scalex,
137                    scaley,
138                    shiftx=0,
139                    shifty=0;
140             scalex = w/(double)drawing_w;
141             scaley = h/(double)drawing_h;
142             {
143                 if(scalex > scaley)
144                 {
145                     scalex = scaley;
146                     shiftx = (w - scalex*drawing_w)/2.f;
147                 }
148                 else
149                 {
150                     scaley = scalex;
151                     shifty = h - scaley*drawing_h;
152                 }
153             }
154             //move to position in the window
155             cairo_translate(cr,x+shiftx,y+shifty);
156             //scale the drawing
157             cairo_scale(cr,scalex,scaley);
158             //call the draw function
159             if(drawing_f) drawing_f(cr,data,p);
160             else default_scope_drawing(cr,data,p);
161 
162             cairo_restore( cr );
163         }
164     }
165 
resize(int X,int Y,int W,int H)166     void resize(int X, int Y, int W, int H)
167     {
168         Fl_Widget::resize(X,Y,W,H);
169         x = X;
170         y = Y;
171         w = W;
172         h = H;
173         redraw();
174     }
175 
176     /*
177     int handle(int event)
178     {
179       return 0;
180 
181       switch(event)
182       {
183         case FL_PUSH:
184           highlight = 0;
185           redraw();
186           return 1;
187         case FL_DRAG: {
188             int t = Fl::event_inside(this);
189             if (t != highlight) {
190               redraw();
191             }
192           }
193           return 1;
194         case FL_SHORTCUT:
195           if ( test_shortcut() )
196           {
197             do_callback();
198             return 1;
199           }
200           return 0;
201         default:
202           return Fl_Widget::handle(event);
203       }
204     }
205     */
206 };
207 
scope_callback(void * handle)208 static void scope_callback(void* handle)
209 {
210     Scope* scope = (Scope*)handle;
211     Fl::repeat_timeout(.10,scope_callback,handle);
212     if(scope->average)
213     {
214         scope->push_avg();
215     }
216     scope->redraw();
217 };
218 
219 } // ffffltk
220 
221 #endif // FFF_SCOPE_H
222 
223