// // based on FLTK drawing example showing simple line drawing animation // erco 03/22/07 // clock ticks, ring fiber? // #include #include #include #include #include #include #include #include #include #define BG_COLOR 45 #define TICK_COLOR 50 #define CIRC_COLOR 0 #define PHY_COLOR FL_WHITE #define FPGA_COLOR FL_CYAN int xoff=-225; int yoff=-70; int gap=30; struct bitz { int x; int y; }; struct bitz track[141] = { // should be 41? {380, 100}, {420, 100}, {460, 100}, {460, 170}, {440, 170}, {420, 170}, {400, 170}, {380, 170} }; struct bitz track2[18] = { { 860, 695}, { 900, 695}, { 940, 695}, { 990, 550}, {1010, 550}, {1030, 550}, {1050, 550}, {1070, 550} }; void find_dot(double l, int *x, int *y, struct bitz *t) { if (l>=41.0) return; int l2 = (int) floor(l/8); // byte number double p = l-l2*8; int b = (int) floor(p); // bit number double r = p-b; // fractional bit double x_curve=0; if (b==2 && r != 0) { x_curve = 25; } if (b==7 && r != 0) { x_curve = -25; } double z = 4*r*(1-r); b=b+l2*8; double x1 = (1-r)*(t+b)->x + r*(t+b+1)->x + z*x_curve; double y1 = (1-r)*(t+b)->y + r*(t+b+1)->y; *x = int (floor(x1+.5))+xoff; *y = int (floor(y1+.5))+yoff; } /* * 0-2 controller Tx * 3-10 BPM1 * 11-18 BPM2 * 19-26 BPM3 * 27-34 BPM4 * 35-39 controller Rx */ void expand_track(void) { #if 0 for (unsigned jj=0; jj<7; jj++) { track2[jj].x = track[jj].x+300; track2[jj].y = track[jj].y+300; } #endif for (unsigned jj=1; jj<5; jj++) { for (unsigned ii=0; ii<8; ii++) { track[jj*8+ii].x = track[ii].x; track[jj*8+ii].y = track[ii].y+jj*150; } } for (unsigned ii=3; ii<8; ii++) { // 35-39 track[32+ii].x = 940+gap-track[ii].x; track[32+ii].y = 650-track[ii].y; } for (unsigned ii=0; ii<3; ii++) { // 0-2 track[ii].x = 940+gap-track[ii].x; track[ii].y = 500-track[ii].y; } #if 0 for (unsigned jj=0; jj<40; jj++) { printf("%4d %4d\n", track[jj].x, track[jj].y); } exit(0); #endif } void set_bpm_color(unsigned bpm) { switch (bpm) { case 0: fl_color(FL_MAGENTA); break; case 1: fl_color(FL_GREEN); break; case 2: fl_color(FL_RED); break; case 3: fl_color(FL_BLUE); break; } } static void draw_byte(int x, int y) { fl_pie(x-6,y-6,12,12,0.0,360.0); } static void draw_fbyte(int x, int y, int n) { switch (n%8) { case 0: fl_pie (x-6,y-6,12,12,0.0,360.0); break; case 1: fl_arc (x-6,y-6,12,12,0.0,360.0); break; case 2: fl_polygon(x-6,y-6,x+6,y-6,x,y+6); break; case 3: fl_loop (x-6,y-6,x+6,y-6,x,y+6); break; case 4: fl_rectf (x-6,y-6,12,12); break; case 5: fl_rect (x-6,y-6,12,12); break; case 6: fl_polygon(x-6,y+6,x+6,y+6,x,y-6); break; case 7: fl_loop (x-6,y+6,x+6,y+6,x,y-6); break; } } static void draw_abyte(int x, int y, int n) { // fl_pie(x-6,y-6,12,12,0.0,360.0); switch (n%2) { case 0: fl_rectf(x-5,y-5,10,10); break; case 1: fl_polygon(x-6,y,x,y+6,x+6,y,x,y-6); break; } } static void shift_inout(int x0, int y0, double t, int v, int h, double dt, int n) { if (dt>0 && t>(-1.0-dt) && t<-1.0) { // ripen data for (unsigned jj=0; jj<8; jj++) { int zx2 = x0+h*(jj-8)+xoff; int zy2 = y0-v+yoff; int r=(int) (6*(t+1+dt)/dt + 0.5); fl_pie(zx2-r,zy2-r,2*r,2*r,0.0,360.0); } } else if (t>=-1.0 && t<0.0) { // load register for (unsigned jj=0; jj<8; jj++) { int zx2 = x0+h*(jj-8)+xoff; int zy2 = y0+(int)floor(v*t+.5)+yoff; draw_fbyte(zx2,zy2,n); } } else if (t>=0.0 && t<8.0) { // shift out for (unsigned jj=0; jj<(8-t); jj++) { int zx2 = x0+(int)(h*(jj+t-8)+.5)+xoff; int zy2 = y0+yoff; draw_fbyte(zx2,zy2,n); } } } static void shift_out(int x0, int y0, double dt, double t) { shift_inout(x0, y0, t, 40, 15, dt, 0); } static void shift_in(int x0, int y0, double dt, double t) { shift_inout(x0, y0, 8-t, -40, -15, dt, 0); } int pack_color[56]; class MyTimer : public Fl_Box { void draw() { // COMPUTE NEW COORDS OF LINE static struct timespec start; static int timespec_rc = clock_gettime(CLOCK_REALTIME, &start); static int uninitialized = 1; (void) timespec_rc; struct timespec now; clock_gettime(CLOCK_REALTIME, &now); long tick = now.tv_sec - start.tv_sec; long loop_time = 60; // 50 if (tick > loop_time) { start.tv_sec += loop_time; tick -= loop_time; uninitialized = 1; } double t = (tick + now.tv_nsec * 1e-9)*2.0+0; char secs[80]; sprintf(secs, "%7.2f \265s", (t-38)*.08); // 10 ns * 8 bits // TELL BASE WIDGET TO DRAW ITS BACKGROUND Fl_Box::draw(); // BPM Boxes for (unsigned jj=0; jj<4; jj++) { int y0=155+jj*150+yoff; fl_color(PHY_COLOR); fl_rectf(380+xoff, y0, 80, 110); fl_color(FL_YELLOW); fl_rectf(245+xoff, y0, 135, 110); fl_color(FL_BLACK); fl_font(FL_HELVETICA,14); fl_draw("BPM",270+xoff,y0+20); fl_draw("ETH PHY",390+xoff, y0+60); } // Concentrator and Corrector Box int y0=385+yoff; int y1=455+yoff; int x4=750+gap+xoff; int y4=140+yoff; fl_color(PHY_COLOR); fl_rectf(480+gap+xoff,y0, 80,110); fl_rectf(830+gap+xoff,y0+215, 80, 110); fl_rectf(930+2*gap+xoff,y1, 80, 110); // Corrector fl_rectf(670+gap+xoff,y0-120, 110,120); // MGT Rx fl_rectf(670+gap+xoff,y0+325, 110, 60); // MGT Tx fl_color(FL_YELLOW); fl_rectf(560+gap+xoff,y0,270,325); // Concentrator fl_rectf(1010+2*gap+xoff,y1, 135, 110); fl_rectf(x4,y4+70,57,20); // FPGA key fl_color(FL_BLACK); fl_font(FL_HELVETICA,20); fl_draw("Simplified data flow",x4,y4-25); fl_font(FL_HELVETICA,14); fl_draw("Proposed architecture for deterministic latency",x4,y4); fl_draw("Fast orbit feedback",x4,y4+20); fl_draw("One of eight sectors",x4,y4+40); fl_draw("Larry Doolittle, LBNL, 2007-10-11",x4,y4+60); fl_draw("FPGA",x4+10,y4+85); fl_draw("1 data octet",x4+120,y4+85); fl_draw("Concentrator",580+gap+xoff,y0+20); fl_draw("ETH PHY",490+gap+xoff, y0+60); fl_draw("ETH PHY",840+gap+xoff, y0+275); fl_draw("ETH PHY",940+2*gap+xoff, y1+60); fl_draw("Corrector",1030+2*gap+xoff,y1+20); fl_draw("MGT Rx",710+gap+xoff, y0-55); fl_draw("MGT Tx",710+gap+xoff, y0+360); fl_color(FL_RED); draw_byte(x4+110,y4+80); unsigned ti = (unsigned) floor(t); if (uninitialized) { // reset for (unsigned jj=0; jj<48; jj++) pack_color[jj] = TICK_COLOR; uninitialized=0; } if (ti >=40 && ti <48) { pack_color[ 8+ti-40]=FL_BLUE; pack_color[16+ti-40]=FL_RED; pack_color[24+ti-40]=FL_GREEN; pack_color[32+ti-40]=FL_MAGENTA; } double fmult=8.0; for (unsigned bpm=0; bpm<4; bpm++) { set_bpm_color(bpm); shift_out(380, 250+bpm*150, 24.0, t-39); shift_in (560+gap, 480, 0.0, t-47-(3-bpm)*8); shift_out(695+gap, 560, 0.0, (t-56-(3-bpm)*8)*fmult-1); } int bpm_shift_out = ti >=39 && ti < 47; for (unsigned jj=0; (jj<=ti) && (jj<48); jj++) { int zx2, zy2; if (t-jj >= 39) continue; if (bpm_shift_out && ((ti-jj)%8==7)) continue; find_dot(t-jj, &zx2, &zy2, track); fl_color(pack_color[jj]); draw_byte(zx2, zy2); } // vertical flow through fiber double tf0=56.25; for (unsigned jj=0; jj<256; jj++) { unsigned bn = jj%8; unsigned bpm = jj/64; unsigned cu = (jj/8)%8; double d = ((t-tf0-bpm*8)*fmult-bn)*90; // distance from origin if (d<0) continue; if (jj%64==0) set_bpm_color(3-bpm); int zx2 = 695 + gap + xoff; int zy2 = (int)(d-cu*fmult*90+.5); zy2 = 560+zy2; if (cu==7 && zy2>600) continue; zy2 = zy2+yoff; if (zy2>10 && zy2<710) draw_fbyte(zx2, zy2, cu); } // MAC box fl_color(TICK_COLOR); fl_rectf(703+gap+xoff,635+yoff,119,40); // fiber receiver shift register double tf1=56.305; for (unsigned bpm=0; bpm<4; bpm++) { set_bpm_color(3-bpm); for (unsigned cu=0; cu<8; cu++) { double dt=t-tf1-cu-bpm*8; shift_inout(695+gap, 600, (1-dt)*fmult, -40, -15, 0, cu); } } // MAC double tf2=57.43; if (t>tf2 && ttf2+50) { // static result in corrector for (unsigned jj=0; jj<8; jj++) { int zx2=1025+2*gap+jj*15+xoff; int zy2=510+yoff; draw_byte(zx2,zy2); } } // Output 100 Mbit link double t3=t-(tf2+26); // tf2-8 for (int jj=0; jj<=((int)t3) && (jj<24); jj++) { int zx2, zy2; double zt=t3-jj; if (zt >= 7 || zt<=0) continue; find_dot(zt, &zx2, &zy2, track2); fl_color((jj/8==1)?FL_DARK_RED:TICK_COLOR); draw_byte(zx2, zy2); } // DRAW TIMER TEXT STRING fl_color(TICK_COLOR); fl_font(FL_HELVETICA,20); fl_draw(secs, x()+7, y()+h()-7); } static void Timer_CB(void *userdata) { MyTimer *o = (MyTimer*)userdata; o->redraw(); Fl::repeat_timeout(0.025, Timer_CB, userdata); } public: // CONSTRUCTOR MyTimer(int X,int Y,int W,int H,const char*L=0) : Fl_Box(X,Y,W,H,L) { box(FL_FLAT_BOX); color(BG_COLOR); Fl::add_timeout(0.25, Timer_CB, (void*)this); } }; // MAIN int main() { Fl_Double_Window win(1000, 720); MyTimer tim(10, 10, win.w()-20, win.h()-20); expand_track(); win.show(); return(Fl::run()); }