/****************************************************************************** * * project name: S1P7 * initial date: 05/04/2001 * author: thomas.nussbaumer@gmx.net * description: pixel macros & line drawing demonstration * * compile with: tigcc -O3 drawline.c -Wall -w * *******************************************************************************/ #define SAVE_SCREEN // restore screen after program end #include /*---------------------------------------------------------------------------*/ /* global variables */ /*---------------------------------------------------------------------------*/ short _ti92plus; // needed to produce ti92plus code short _ti89; // needed to produce ti89 code /*---------------------------------------------------------------------------*/ /* speedy pixel access routines */ /*---------------------------------------------------------------------------*/ #define PIXOFFSET(x,y) ((y<<5)-(y<<1)+(x>>3)) #define PIXADDR(p,x,y) (((unsigned char*)(p))+PIXOFFSET(x,y)) #define PIXMASK(x) ((unsigned char)(0x80 >> ((x)&7))) #define GETPIX(p,x,y) (!(!(*PIXADDR(p,x,y) & PIXMASK(x)))) #define SETPIX(p,x,y) (*PIXADDR(p,x,y) |= PIXMASK(x)) #define CLRPIX(p,x,y) (*PIXADDR(p,x,y) &= ~PIXMASK(x)) #define XORPIX(p,x,y) (*PIXADDR(p,x,y) ^= PIXMASK(x)) /*---------------------------------------------------------------------------*/ /* useful macros */ /*---------------------------------------------------------------------------*/ #define ABS(a) (((a)<0) ? -(a): (a)) #define SGN(a) (((a)<0) ? -1 : 1) /*===========================================================================*/ /* draws a line from (x1,y1) to (x2,y2) in given plane */ /* */ /* valid modes: A_REPLACE,A_REVERSE,A_XOR */ /*===========================================================================*/ inline void drawline(unsigned char* plane, short x1,short y1, short x2,short y2, short mode) { short d,x,y,ax,ay,sx,sy,dx,dy; dx = x2 - x1; ax = ABS(dx)<<1; sx = SGN(dx); dy = y2 - y1; ay = ABS(dy)<<1; sy = SGN(dy); x = x1; y = y1; //------------------------------------------------------------------------- // for speedup reasons the different modes are handled by own blocks. // The only difference is the usage of SETPIX/CLRPIX or XORPIX //------------------------------------------------------------------------- // sets each pixel of the line ... if (mode == A_REPLACE) { if (ax>ay) { /* x dominant */ d = ay - (ax>>1); while (1) { SETPIX(plane,x,y); if (x==x2) return; if (d>=0) { y += sy; d -= ax; } x += sx; d += ay; } } else { /* y dominant */ d = ax - (ay>>1); while (1) { SETPIX(plane,x,y); if (y==y2) return; if (d>=0) { x += sx; d -= ay; } y += sy; d += ax; } } } // clears each pixel of the line ... else if (mode == A_REVERSE) { if (ax>ay) { /* x dominant */ d = ay - (ax>>1); while (1) { CLRPIX(plane,x,y); if (x==x2) return; if (d>=0) { y += sy; d -= ax; } x += sx; d += ay; } } else { /* y dominant */ d = ax - (ay>>1); while (1) { CLRPIX(plane,x,y); if (y==y2) return; if (d>=0) { x += sx; d -= ay; } y += sy; d += ax; } } } // XORs each pixel of the line ... else if (mode == A_XOR) { if (ax>ay) { /* x dominant */ d = ay - (ax>>1); while (1) { XORPIX(plane,x,y); if (x==x2) return; if (d>=0) { y += sy; d -= ax; } x += sx; d += ay; } } else { /* y dominant */ d = ax - (ay>>1); while (1) { XORPIX(plane,x,y); if (y==y2) return; if (d>=0) { x += sx; d -= ay; } y += sy; d += ax; } } } // NOTE: if the mode is not within A_REPLACE/A_REVERSE/A_XOR nothing is drawn !! } /*===========================================================================*/ /* main routine: where all the fun starts ... */ /*===========================================================================*/ void _main(void) { LCD_BUFFER save_buffer; short i,j; unsigned long measure_val; char tmpstr[30] = "Measuring, please wait ..."; short modes[6] = { A_REPLACE,A_XOR,A_REVERSE,A_XOR,A_REPLACE,A_REVERSE}; LCD_save(save_buffer); FontSetSys(F_4x6); OSFreeTimer(USER_TIMER); OSRegisterTimer(USER_TIMER,1000); ClearScreen(); DrawStr(0,0,tmpstr,A_REPLACE); do { //--------------------------------------------------------------------- // build-in AMS line drawing routine ... //--------------------------------------------------------------------- OSTimerRestart(USER_TIMER); for (j=0;j<6 && !kbhit();j++) { short used_mode = modes[j]; for (i=0; i<160;i++) DrawLine(80,50,i,8, used_mode); for (i=8; i<100;i++) DrawLine(80,50,159,i, used_mode); for (i=159;i>=0; i--) DrawLine(80,50,i,99, used_mode); for (i=99; i>=8; i--) DrawLine(80,50,0,i, used_mode); } measure_val = OSTimerCurVal(USER_TIMER); sprintf(tmpstr,"AMS Routine tooks %lu time units",(1000-measure_val)*50); memset(LCD_MEM,0,30*8); DrawStr(0,0,tmpstr,A_REPLACE); if (kbhit()) break; //--------------------------------------------------------------------- // new line drawing routine ... //--------------------------------------------------------------------- OSTimerRestart(USER_TIMER); for (j=0;j<6 && !kbhit();j++) { short used_mode = modes[j]; for (i=0; i<160;i++) drawline(LCD_MEM,80,50,i,8, used_mode); for (i=8; i<100;i++) drawline(LCD_MEM,80,50,159,i, used_mode); for (i=159;i>=0; i--) drawline(LCD_MEM,80,50,i,99, used_mode); for (i=99; i>=8; i--) drawline(LCD_MEM,80,50,0,i, used_mode); } measure_val = OSTimerCurVal(USER_TIMER); sprintf(tmpstr,"Own Routine tooks %lu time units",(1000-measure_val)*50); memset(LCD_MEM,0,30*8); DrawStr(0,0,tmpstr,A_REPLACE); } while (!kbhit()); ngetchx(); OSFreeTimer(USER_TIMER); LCD_restore(save_buffer); }