From: Greg King (gngking_at_erols.com)
Date: 2004-12-13 08:38:59
From: Jim Brain; on Date: December 09, 2004, 03:19 PM -0500 > > > Is that sign-inversion necessary? If the code to subtract the old > > counter value from the new one is less efficient, then can't you use > > the negative difference directly? (If it's greater than -7000, then, > > compare it to -4096.) > > Dunno, let me see: > > void calc(unsigned int old, unsigned int new) { > unsigned int tmp; > if (new < old) { > tmp=old-new; > } else { > tmp=new-old; > } > if (tmp < 7000) { > ... > } > } > > ... Is the old code. > > void calc(unsigned int old, unsigned int new) { > int tmp; > tmp=new-old; > if (tmp > -7000 && tmp < 7000) { > ... > } > } > > The corner case is when the counter is at 65535 (for example), and it > wraps, to 4095. > > 4095-65535 = -61440 -> (signed int) -4095 (I think...) > > It would seem to work, and it'd be a bit faster, but someone needs to > check my math. I think the intermediate result would be stuffed into 16 > bits, and that would normalize to -4095, but someone needs to verify. There are two problems with my questions: 1. I didn't know that you're writing the code in the C language. I had assumed that you were using assembly language. (Silly me -- I should have known it, from a previous message of yours.) 2. I had forgotten that the free-running timer-counter wraps around. Those two revelations change everything! First, they raise a new question: How wide is the "int" type in your micro-controller's C compiler? In the rest of this letter, I will assume that it's 16 bits. Second, the calc function must use "clock arithmetic" because of that wrap-around. For example, if the old value is 65532, and the new value is 5, then the (16-bit) distance between them is 9, not +/- 65527. Fortunately, as Spiro said, two's-complement arithmetic, working in unsigned variables, does what you need [a signed 16-bit -65527, when cast into (unsigned), is 9]. So, calc() should be: void calc(unsigned int old, unsigned int new) { unsigned int tmp; tmp = new - old; if (tmp < 7000 && tmp != 0) { if (tmp < 4096) { /* Run faster. */ ... } else if (tmp > 4096) { /* Run slower. */ ... } } } That "tmp != 0" catches the case when the counter wraps completely around to its original value (the distance actually is 65536). Message was sent through the cbm-hackers mailing list
Archive generated by hypermail pre-2.1.8.