Stef wrote:> In comp.arch.embedded, > Paul E. Schoen <pstech@smart.net> wrote: > >>I wrote a program that reads analog data (of 60 Hz current) at 2400 samples >>per second through a serial port at 57.6 kbps. It displays the relative >>value on a bar graph, and actual RMS current during operation, and it >>displays up to 5 pulses of current with various on and off times.<snip> To the O.P.: Even though I originally suggested 'gnuplot' I would be remiss to not mention using the vt100 graphics character set of a display terminal (or emulation) to display waveform data. I run an 'ascii oscilloscope' which provides the basic features of waveform display including scale factor, position controls, reticule, sweep rate, triggering, etc. and the displayed waveform has good fidelity on a 24 X 80 character screen and adequate refresh rates at serial port speeds above 9600 baud. I reiterate also the additional solution of using the tek4014 graphics primitives if your terminal emulator supports them. All this presumes the need for realtime display; if your requirement is only for data reduction and offline display than 'gnuplot' should suffice. Regards, Michael
Searching simple waveform viewer
Started by ●September 21, 2007
Reply by ●September 24, 20072007-09-24
Reply by ●September 24, 20072007-09-24
msg wrote:>... snip ...> > Even though I originally suggested 'gnuplot' I would be remiss to > not mention using the vt100 graphics character set of a display > terminal (or emulation) to display waveform data. I run an 'ascii > oscilloscope' which provides the basic features of waveform display > including scale factor, position controls, reticule, sweep rate, > triggering, etc. and the displayed waveform has good fidelity on a > 24 X 80 character screen and adequate refresh rates at serial port > speeds above 9600 baud._- and | can implement a 48 x 80 display on a 24 x 80 field. = and + may also be useful. -- Chuck F (cbfalconer at maineline dot net) Available for consulting/temporary embedded and systems. <http://cbfalconer.home.att.net> -- Posted via a free Usenet account from http://www.teranews.com
Reply by ●September 25, 20072007-09-25
Stef wrote:> it looks like it's highly specific to the original task it was created for. > So adapting it might be a big job and my Delphi skills are non existant. > I have used Borland C++ builder and did some Pascal way back.Here a very simple piece of C code which I use to display ADC data read from an Atmel Tiny45 by a two wire interface using the parallel port. You can download Visual C++ from Microsoft. #define _CRT_SECURE_NO_DEPRECATE 1 #define debug 1 #ifdef debug #include <io.h> #include <conio.h> #include <fcntl.h> #include <stdio.h> #endif #include <windows.h> #include <stdlib.h> #include <math.h> #include <conio.h> #define pi 3.1415927 #define size 10000 /**************************************************************************/ HDC globalhdc; HWND windowhandle; HPEN greenpen,bluepen,redpen,blackpen,black5pen,whitepen,oldpen; HFONT newfont,oldfont; int xpos=100,ypos=100,xsize=1000,ysize=750,xold,yold,ldown,rdown,nmax=10; int start=0, zoom=1; zoom0=3; zoom1[7]={-10,-5,-2,1,2,5,10}; int loop=0; double a[110]={0.0, 1.0}, b[110]={0.0, 0.5}, r[805]; int adc0[size+10],adc1[size+10],adc2[size+10],adc3[size+10]; FILE *save; char fname[7]={'s','a','v','e','.','a',0}; /**************************************************************************/ #ifdef debug void init_stdout() {int hCrt; FILE *hf; AllocConsole(); hCrt = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT); hf = _fdopen( hCrt, "w" ); *stdout = *hf; setvbuf( stdout, NULL, _IONBF, 0 ); printf("stdout is working!!!\n"); hCrt = _open_osfhandle((long)GetStdHandle(STD_INPUT_HANDLE),_O_TEXT); hf = _fdopen( hCrt, "r" ); *stdin = *hf; setvbuf( stdin, NULL, _IONBF, 0 ); printf("print a character followed by a <CR> to test stdin: "); /* printf("\nYou typed: %c\n",getchar()); */ } #endif void read_dat(int max) {int i,j,n,clock=0,data[5]; Rectangle(globalhdc,0,0,1000,750); SelectObject(globalhdc,redpen); MoveToEx(globalhdc,0,240,NULL); _outp(0x378,clock); /* reset clock */ if (max>10000) max=10000; for (n=0; n<max; n++) {while ((char)_inp(0x379) < 0); /* wait for bit7 = 0 */ for (i=0; i<5; i++) {data[i]=-1; for (j=1; j<=8; j++) {_outp(0x378,j&1); /* toggle clock */ _inp(0x379); _inp(0x379); data[i]=(data[i]<<1)+((_inp(0x379)>>7)&1); } if (i) data[i]=~( (data[i]<<2) + ((data[0]>>((4-i)*2))&0x03)); } _outp(0x378,1); _outp(0x378,0); adc0[n]=data[1]; adc1[n]=data[2]; adc2[n]=data[3]; adc3[n]=data[4]; LineTo(globalhdc,n/10,240-(data[2]-0x200)/7); SetPixel(globalhdc,n/10,400-(data[3]-0x200)/7,0); } } /**************************************************************************/ LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); VOID zeichne(HDC); /**************************************************************************/ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {int i; MSG msg; WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = "hand"; if (!RegisterClass(&wc)) return (FALSE); if (!(windowhandle=CreateWindow("hand", "", WS_POPUP|WS_VISIBLE,xpos, ypos, xsize, ysize,NULL, NULL, hInstance, NULL))) return (FALSE); globalhdc=GetDC(windowhandle); /**************************************************************************/ #ifdef debug init_stdout(); #endif /**************************************************************************/ for (i=0; i<10000; i++) {adc0[i]=(int)(sin(i/100.0)*0x1ff+0x200); adc1[i]=(int)(cos(i/100.0)*0x1ff+0x200); adc2[i]=(int)(sin(i/150.0)*0x1ff+0x200); adc3[i]=(int)(cos(i/150.0)*0x1ff+0x200);} greenpen=CreatePen(PS_SOLID,1,0x00ff00); bluepen =CreatePen(PS_SOLID,1,0xffb0b0); redpen =CreatePen(PS_SOLID,1,0xb0b0ff); blackpen=CreatePen(PS_SOLID,1,0x000000); black5pen=CreatePen(PS_SOLID,5,0x000000); oldpen = SelectObject(globalhdc,bluepen); zeichne(globalhdc); while (1) {if (loop && !PeekMessage(&msg, NULL,0,0,PM_NOREMOVE)) keybd_event(0x30,0,0,0); if (GetMessage(&msg, NULL,0,0)) {TranslateMessage(&msg); DispatchMessage(&msg);} else break; } DeleteObject(greenpen); DeleteObject(bluepen); DeleteObject(redpen); DeleteObject(blackpen); DeleteObject(black5pen); SelectObject(globalhdc,oldpen); ReleaseDC(NULL,globalhdc); return (msg.wParam); } /**************************************************************************/ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {PAINTSTRUCT ps; HDC hdc; int i,j; switch (message) {case WM_CHAR: if (wParam>='1' && wParam<='9') {read_dat((wParam-'0')*1000); zeichne(globalhdc); break;} if (wParam>='c' && wParam<='z') {fname[5]=wParam; if ( (save = fopen(fname,"rb")) == NULL) break; fread(adc0, sizeof(int), 10000, save); fread(adc1, sizeof(int), 10000, save); fread(adc2, sizeof(int), 10000, save); fread(adc3, sizeof(int), 10000, save); fclose(save); zeichne(globalhdc); break;} if (wParam>='C' && wParam<='Z') {fname[5]=wParam; if ( (save = fopen(fname,"wb")) == NULL) break; fwrite(adc0, sizeof(int), 10000, save); fwrite(adc1, sizeof(int), 10000, save); fwrite(adc2, sizeof(int), 10000, save); fwrite(adc3, sizeof(int), 10000, save); fclose(save); break;} switch(wParam) {case 'a' : for (i=0; i<10000; i++) {adc0[i]=(int)(sin(i/50.0)*0x1ff+0x200); adc1[i]=(int)(cos(i/20.0)*0x1ff+0x200); adc2[i]=(int)(sin(i/15.0)*0x1ff+0x200); adc3[i]=(int)(cos(i/5.0)*0x1ff+0x200);} zeichne(globalhdc); break; case 'b' : for (i=0; i<10000; i++) {adc0[i]=(int)(sin(i/150.0)*0x1ff+0x200); adc1[i]=(int)(cos(i/175.0)*0x1ff+0x200); adc2[i]=(int)(sin(i/50.0)*0x1ff+0x200); adc3[i]=(int)(cos(i/350.0)*0x1ff+0x200);} zeichne(globalhdc); break; case '0' : read_dat(10000); zeichne(globalhdc); break; case ' ' : loop=!loop; break; default:; } break; case WM_LBUTTONDOWN: xold=LOWORD(lParam); yold=HIWORD(lParam); ldown=1; if (yold>700 && yold<750) {if (xold>=13 && xold<313) {i=(xold-13 )/30; start=1000*i;} else if (xold>=343 && xold<643) {i=(xold-343)/30 ;start=start/1000*1000+i*100;} else if (xold>=673 && xold<988) {zoom0=(xold-673)/45; zoom=zoom1[zoom0];} if (zoom>0) {if ((start+(1000+(zoom-1))/zoom) > size) start= (size-(1000+(zoom-1))/zoom)/100*100;} else {if ((start+1000*(-zoom)) >size) start= (size-1000*(-zoom))/100*100;} zeichne(globalhdc); } break; case WM_LBUTTONUP: if (ldown<0) zeichne(globalhdc); ldown=0; break; case WM_RBUTTONDOWN: xold=LOWORD(lParam); yold=HIWORD(lParam); rdown=1; break; case WM_RBUTTONUP: rdown=0; break; case WM_MOUSEMOVE: if (rdown) {i=LOWORD(lParam); j=HIWORD(lParam); xpos=xpos-xold+LOWORD(lParam); ypos=ypos-yold+HIWORD(lParam); SetWindowPos(windowhandle,HWND_TOP,xpos,ypos,xsize,ysize,0); } break; case WM_PAINT: if (!rdown) {hdc = BeginPaint (hWnd, &ps); zeichne(hdc); EndPaint (hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0); } /**************************************************************************/ void zeichne(hdc) HDC hdc; {int i,k; char txt[20]; static char* (txt1[7])={"1:10"," 1:5"," 1:2"," 1:1"," 2:1"," 5:1","10:1"}; SelectObject(hdc,greenpen); Rectangle(hdc,0,0,1000,750); SelectObject(hdc,blackpen); MoveToEx(hdc,0,80,NULL); LineTo(hdc,999,80); MoveToEx(hdc,0,240,NULL); LineTo(hdc,999,240); MoveToEx(hdc,0,400,NULL); LineTo(hdc,999,400); MoveToEx(hdc,0,560,NULL); LineTo(hdc,999,560); SelectObject(hdc,redpen); MoveToEx(hdc,0,240-(adc1[start]-0x200)/7,NULL); for (i=0; i<1000/zoom; i++) {k=(adc1[start+i]-0x200)/7; LineTo(hdc,i*zoom,240-k);} for (i=0; i<(-1000*zoom); i++) {k=(adc1[start+i]-0x200)/7; LineTo(hdc,i/(-zoom),240-k);} SelectObject(hdc,bluepen); MoveToEx(hdc,0,400-(adc2[start]-0x200)/7,NULL); for (i=0; i<1000/zoom; i++) {k=(adc2[start+i]-0x200)/7; LineTo(hdc,i*zoom,400-k);} for (i=0; i<(-1000*zoom); i++) {k=(adc2[start+i]-0x200)/7; LineTo(hdc,i/(-zoom),400-k);} for (i=0; i<1000/zoom; i++) {/*k=(adc0[start+i]-0x200)/7; SetPixel(hdc,i*zoom,80-k,0);*/ k=(adc1[start+i]-0x200)/7; SetPixel(hdc,i*zoom,240-k,0); k=(adc2[start+i]-0x200)/7; SetPixel(hdc,i*zoom,400-k,0); /*k=(adc3[start+i]-0x200)/7; SetPixel(hdc,i*zoom,560-k,0)*/; } for (i=0; i<(-1000*zoom); i++) {/*k=(adc0[start+i]-0x200)/7; SetPixel(hdc,i/(-zoom),80-k,0);*/ k=(adc1[start+i]-0x200)/7; SetPixel(hdc,i/(-zoom),240-k,0); k=(adc2[start+i]-0x200)/7; SetPixel(hdc,i/(-zoom),400-k,0); /*k=(adc3[start+i]-0x200)/7; SetPixel(hdc,i/(-zoom),560-k,0);*/ } /* SetTextColor(hdc,0x0); */ SetBkColor(hdc,0xffffff); /* newfont=GetStockObject(ANSI_VAR_FONT); oldfont= SelectObject(hdc,newfont); */ txt[0]='0'; txt[1]='.'; for (i=0; i<10; i++){TextOut(hdc,20+i*30,700, txt,2); txt[0]++;} txt[0]='.'; txt[1]='0'; for (i=0; i<10; i++){TextOut(hdc,350+i*30,700, txt,2); txt[1]++;} for (i=0; i<7; i++) TextOut(hdc,680+i*45,700, txt1[i],4); /* SetTextColor(hdc,0x0); */ SetBkColor(hdc,0xffff00); i=start/1000; txt[1]='.'; txt[0]='0'+i; TextOut(hdc,20+i*30,700, txt,2); SetBkColor(hdc,0x0080ff); i=(start%1000)/100; txt[1]='0'+i; txt[0]='.'; TextOut(hdc,350+i*30,700, txt,2); SetBkColor(hdc,0x80ff00); TextOut(hdc,680+zoom0*45,700, txt1[zoom0],4); /* SelectObject(globalhdc,oldfont); */ }
Reply by ●September 25, 20072007-09-25
In comp.arch.embedded, Herbert Kleebauer <klee@unibwm.de> wrote:> > Here a very simple piece of C code which I use to display ADC data read > from an Atmel Tiny45 by a two wire interface using the parallel port. > You can download Visual C++ from Microsoft.<snip code> Thanks for that, saved it as an example for whenever I need to do some graphics using VC++. But for the current application, I will stay with gnuplot. It really worked well on my first day of real use. I prepared a little command file for it, so creating the graphs is a matter of seconds now. -- Stef (remove caps, dashes and .invalid from e-mail address to reply by mail)