Perhaps it's me that's missing something. You have an 8 bit value (0-255), you want a range of "(about) 0..34,000 or so". Assuming 32,768 is close enough to "34,000 or so", why not just << 7 ? Or is this a case of "close enough" isn't close enough ? :-) -Denny On Wed, May 15, 2019 at 4:45 PM Dwayne Reid wrote: > Good day to all. > > I'm working on a project where I need to scale an 8-bit value to the > range of (about) 0..34,000 or so. This is to feed the period > register of a PWM generator - actual largest value is not > critical. This routine needs to execute very millisecond and system > clock frequency is 4 MHz (1us instruction rate), so I'm opting to go > with a simple integer-based fixed multiply routine. > > As always, I turn to Nikolai Golovchenko's wonderful ConstDivMul > calculator whenever I need to scale some quantity by a fixed-value > constant. It consistently generates code that is at least as tight > and small as anything that I can create myself. > > This time, however, the routine I came up with seems to be much > shorter / faster than Nilolai's version. I'm assuming that I somehow > made a mistake but I'm not seeing it. I'm hoping that some of the > math wizzes still on the list can give an opinion. > > Input quantity is a single byte (0..255) and is to multiplied by a > fixed constant of 132 > > ; ACC =3D ACC * 132.000000 > ; > ; ALGORITHM: > ; Clear accumulator > ; Add input * 128 to accumulator > ; Add input * 4 to accumulator > ; Move accumulator to result > ; > ; Error in constant approximation : 0.000000, % > > > ; Input: ACC0 (8 bits) > ; Output: ACC0 .. ACC1 (16 bits) > > cblock > ACC0 > ACC1 > TEMP0 > TEMP1 > endc > > clrc > rlf ACC0, f > clrf ACC1 > rlf ACC1, f > rlf ACC0, f > rlf ACC1, f > movf ACC0, w > movwf TEMP0 > movf ACC1, w > movwf TEMP1 > swapf TEMP1, f > swapf TEMP0, w > andlw 15 > iorwf TEMP1, f > swapf TEMP0, w > andlw -16 > movwf TEMP0 > clrc > rlf TEMP0, f > rlf TEMP1, f > movf TEMP0, w > addwf ACC0, f > movf TEMP1, w > skpnc > incfsz TEMP1, w > addwf ACC1, f > > > My version: > > ; Clear accumulator > ; Add input * 128 to accumulator > ; Add input * 4 to accumulator > ; Move accumulator to result > > clrf TEMP0 > clrf ACC1 > clrc ;* 128 > rrf ACC0,W ;b0 -> C > movwf TEMP1 ; > rrf TEMP0,F ;C -> b7 > > clrc ;* 4 > rlf ACC0,F > rlf ACC1,F > rlf ACC0,F > rlf ACC1,F > > movfw TEMP0 ;ACC1,0 + TEMP1,0 -> ACC1,0 > addwf ACC0,F > movfw TEMP1 > skpnc > incfsz TEMP1,W > addwf ACC1,F > > > Question: did I make some silly mistake or is my version reasonable? > > Anyone have any other optimizations to offer? > > Many thanks! > > dwayne > > -- > Dwayne Reid > Trinity Electronics Systems Ltd Edmonton, AB, CANADA > 780-489-3199 voice 780-487-6397 fax 888-489-3199 Toll Free > www.trinity-electronics.com > Custom Electronics Design and Manufacturing > > -- > http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist > --=20 http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .