/* dro_simple 1 channel quadrature für avr-gcc auf 90s8515 */ /* Copyright (C) 2007 by Simon Schrödle */ /* max 7219 led driver */ /* 16 MHz */ #include #include #include #include #include typedef unsigned char u08; typedef unsigned short u16; #define F_CPU 16000000 /* 16.00 MHz */ #define maxclk 0x01 #define maxdat 0x00 #define maxcs 0x02 #define debounce 5 #define brightx 0x0a #define brighty 0x0a signed long int acntx, acnty,acntz; u08 merrorx,merrory,qinpx,qinpy,qinpz,test; u08 cosy=0; signed long int zerox[]={0,0,0,0,0,0,0,0,0,0}; signed long int zeroy[]={0,0,0,0,0,0,0,0,0,0}; signed long int zeroz[]={0,0,0,0,0,0,0,0,0,0}; signed char graytab[]={0,5,-5,0x10, -5,0,0x10,5, 5,0x10,0,-5, 0x10,-5,5,0}; /*0x10: error, more than one bit changed */ SIGNAL (SIG_OVERFLOW0) /* sample with approx 62.5 khz */ { signed char delta; u08 ind; ind=inp(PINB); qinpx|=(ind&0x03)<<4; /* old state is still in bit 3,2 */ qinpx>>=2; /* new state in bit 3,2; old state in bit 1,0 */ delta=graytab[qinpx]; if (delta==0x10) { delta=0; merrorx=0x80; } acntx+=delta; qinpy|=(ind&0x0c)<<2; /* old state is still in bit 3,2 */ qinpy>>=2; /* new state in bit 3,2; old state in bit 1,0 */ delta=graytab[qinpy]; if (delta==0x10) { delta=0; merrory=0x80; } acnty+=delta; /* qinpz|=(ind&0x30); qinpz>>=2; delta=graytab[qinpz]; if (delta==0x10) { delta=0; merror|=merrorz; } acntz+=delta; */ /* outp(128,TCNT0); check duration of signal call! max 0xff clocks! */ } u08 upc=0,downc=0; void check_keyb(void) { u08 ind; ind=inp(PINA); /*reset to zero buttons*/ if ((ind&1)==0) {zerox[cosy]=acntx; merrorx=0;merrory=0;} if ((ind&2)==0) {zeroy[cosy]=acnty; merrorx=0;merrory=0;} /* if (ind&4) {zeroz[cosy]=acntz;} */ /* cosy counter */ /* if (ind&8) {if (upc<=debounce) {upc++;}} else {upc=0;} if (ind&0x10) {if (downc<=debounce) {downc++;}} else {downc=0;} if ((upc==debounce)&&(cosy<9)) {cosy++;} if ((downc==debounce)&&(cosy>0)) {cosy--;} */ } void dwrite(u16 dcx,u16 dcy) /* write single command to max */ { u08 i=16; /* clock 16 bits to 3x max7219 */ sbi(PORTD,maxcs); cbi(PORTD,maxclk); cbi(PORTD,maxcs); /* CS LOW: start transmit */ do { /* outp(merror,PORTD);*/ if (dcy&0x8000) {sbi(PORTD,maxdat);} else {cbi(PORTD,maxdat);} dcy<<=1; sbi(PORTD,maxclk); /*CLOCK*/ cbi(PORTD,maxclk); /*CLOCK LOW*/ } while (--i); i=16; do { /* outp(merror,PORTD);*/ if (dcx&0x8000) {sbi(PORTD,maxdat);} else {cbi(PORTD,maxdat);} dcx<<=1; sbi(PORTD,maxclk); /*CLOCK*/ cbi(PORTD,maxclk); /*CLOCK LOW*/ } while (--i); sbi(PORTD,maxcs); /*CS HI: load into latch*/ } void init_leds(void) { dwrite(0xf00,0xf00); /*test off*/ dwrite(0x9ff,0x9ff); /*decode on*/ dwrite(0xb06,0xb06); /*7 digits (incl sign) -999.999 to +999.999*/ dwrite(0xc01,0xc01); /*display on*/ dwrite(0xa00|brightx,0xa00|brighty); /*brightness*/ } void write_leds(void) { u08 i,x,y,z,mx,my,mz,sumx,sumy; unsigned long int signx,signy; unsigned long int digi,d; signed long int xd,yd,zd; xd=acntx-zerox[cosy]; yd=acnty-zeroy[cosy]; /* xd=3; yd=54; */ signx=0x0700; /*blank sign */ signy=0x0700; if (xd<0) {xd=-xd;signx=0x0702;} /* signs in mx,my,mz */ if (yd<0) {yd=-yd;signy=0x0702;} dwrite(signx|merrorx,signy|merrory); d=100000; sumx=0; sumy=0; for (i=1;i<7;i++) { digi=i<<8; x=xd/d; xd=xd%d; y=yd/d; yd=yd%d; d=d/10; sumx+=x; /*leading zero supression */ sumy+=y; if (i<3) { if (sumx==0) {x=0x0f;} if (sumy==0) {y=0x0f;} } if (i==3) {x|=0x80;y|=0x80;} /* decimal point */ dwrite(digi|x,digi|y); } /*write data */ /*dwrite(0x0101,0x0106); dwrite(0x0202,0x0205); dwrite(0x0303,0x0304); dwrite(0x0404,0x0403); dwrite(0x0505,0x0502); dwrite(0x0606,0x0601);*/ } int main(void) { u08 ind; cli(); outp(0x00,DDRB); /* B: bit 0..1,2..3,4..5 phase a/b input bit 6..7 NC */ outp(0xff,PORTB); outp(0x00,DDRA); outp(0xff,PORTA); /* A: inputs 0..2 reset x,y,z (or keypad 0..5 3x3 matrix)*/ /* bit 3,4 cosys up-down */ outp(0xff,DDRD); /* bit 0 DATA, 1 CLK, 2 CS MAX7219 567 error xyz*/ outp(0x00,PORTD); sbi(TIMSK,TOIE0); /* Enable TCNT0 overflow */ outp(128,TCNT0); /* Reset Counter */ outp(0x01,TCCR0); /* Divisor: 1/1 clock */ ind=inp(PINB); /*initialize quad inputs to avoid error signal on startup*/ qinpx=(ind&0x03)<<2; ind>>=2; qinpy=(ind&0x03)<<2; ind>>=2; qinpz=(ind&0x03)<<2; acntx=0; acnty=0; acntz=0; zerox[0]=0; zeroy[0]=0; merrorx=0; merrory=0; sei(); /* enable interrupt */ init_leds(); while (1) { check_keyb(); write_leds(); } }