At 02:27 AM 05/03/1997 -0800, you wrote: >John Dammeyer wrote: > >> The extra code penalty without the ability to use a jump table on a >> PIC is much too high. > > John: > > Jump tables are trivially easy (and fast) on the PIC: > > MOVF STATE,W ;switch (state) > ADDWF PCL ;{ > ; > GOTO CASE0 ; case 0: .... > GOTO CASE1 ; case 1: .... > GOTO CASE2 ; case 2: .... > etc... ;} > > On some parts, you need to do a little fiddling with the PCLATH > register, but I'm sure you get the idea. True. In assembler this is a snap as long as it all fits in the one page. If it doesn't then there can be a second level of indirect jumps. In either case a combination of assembler and C would make Case Statements more efficient. eg: Jump tables are trivially easy (and fast) on the PIC when jump tables are placed in the same page. MOVF STATE,W ;switch (state) ADDWF PCL ;{ ; GOTO _CASE0 ; case 0: .... GOTO _CASE1 ; case 1: .... GOTO _CASE2 ; case 2: .... _CASE0: BSF STATUS,PA0 BCF STATUS,PA1 GOTO CASE0 _CASE1: etc... There is just more administration needed to keep all this organized. It would be nice it the C compiler gave me the option to have this type of case statement. > >> I'll post the result when I'm done and like your example I'll make >> it small bite capable. BTW, to be fair you need to pack the >> result; mine was. 8-). Or else I need to unpack mine 8-(. > > If you can deal with an unpacked result, just use the excellent > routine that John Payson posted here a few months ago. It's > extremely fast, easily broken-up into small pieces, and it takes > very little code space. > As promised. Here is the C version of Steve Hardy's binary to BCD routine. I've modified it to handle 16 bit unsigned integers. It can be called from within the mainline polling loop so that the processor isn't tied down to doing conversions. What is interesting is the speed and code size is much smaller than the DAA simulation; kudos to Steve for the idea. I've also taken advantage of having access to the Carry flag to let it handle 16 bit unsigned 16 bit ints. With the exception of a few places where the compiler adds redundent PA0,PA1 bit setting for GOTO support the code generated isn't much slower or bigger than what would be generated by directly doing this in assembler. The most interesting part is the time taken to do each little bit - about 43 clocks on average. At 20MHz this is only 8.2 uSec and may be the best technique to avoid impacting the polling of other I/O. Size of DAA simulation method 94 instructions Execution speed for 59,999 (0xEA5F) -> 2798 clocks Size of DECIMAL SUBTRACTION method 86 instructions Execution speed -> 1575 clocks Average execution time for each call -> 43 clocks Size of BCD using 16 bit division 57 instructions Execution speed -> 2543 clocks. I have not included the 16/16 divide as I assume it would be used elsewhere in the application. Conclusions so far... If you need 16 bit divide anyway and speed isn't a problem use the inelegant divide technique; it's easy to understand and document and IMHO a well documented and easy to understand program is part of a correctly functioning program. If you need speed and space ... use Steve Hardy's successive subtraction method. It could be made faster by doing doing all the conversion in one time rather than in bits. As for John Payson's method. Haven't gotton to it yet. But the assembler version obviously takes 50 instructions. How much time is spent in the loops? Don't know yet. It will probably be the fastest and the smallest; understanding how it works may be more difficult. Now I must stop having fun get back to real work. 8-) Cheers John. -->> // Default for compiler is set to 8 bit ints and 16 bit longs. bits bcdFlags; #define COMPLETE bcdFlags.0 int digit[5]; unsigned long binary; unsigned long divisor; int digitNumber; unsigned int bin2dec () { if (COMPLETE) { digit[0] = 0; // LSDigit digit[1] = 0; digit[2] = 0; digit[3] = 0; digit[4] = 0; // MSdigit COMPLETE = 0; digitNumber = 4; divisor = 10000; } else { binary -= divisor; if (!STATUS.C) { binary +=divisor; if (--digitNumber == 0) { COMPLETE = 1; digit[digitNumber] = binary; } else { if (digitNumber == 3) divisor = 1000; else if (digitNumber == 2) divisor = 100; else divisor = 10; } } else { digit[digitNumber]++; }; }; return COMPLETE; } main() { COMPLETE = 1; // Signal that bin2dec() may convert a new value. binary = 0; // force to known value. while (1) { if (bin2dec()) { // returns TRUE if conversion complete. Display_BCD_Data(); // Put on LCD or LED display. // Now get new data to display. binary = CreateNewBinaryValueToDisplay(); }; // Do other real time processing every 10 uSeconds or so with a 20MHz // processor. } } <<-- Pioneers are the ones, face down in the mud, with arrows in their backs. Automation Artisans Inc. Ph. 1-250-544-4950 PO Box 20002 Fax 1-250-544-4954 Sidney, BC CANADA V8L 5C9