Jakes Daddy Posted March 28, 2007 Report Share Posted March 28, 2007 I'm having a problem with a variable of type float which I hope someone can help with.Basically I have a pot which is my pitch fader. It sends MIDI values 0-127. The centre point of the pot is 0% pitch, and sends a MIDI value of 63. My pitch range is +-6.5%I am trying to write a C function which will calculate the pitch and display it on the LCD.My formula for working out the pitch is:Work out the equivilant pitch value for each pot step or movement:eachIncrementValue = totalPitch / totalPossibleValueseachIncrementValue = (6.5 X 2)/ 127eachIncrementValue = 0.10236220472440944881889763779528Then work out the pitch:pitch = 0.0 + ( eachIncrementValue * (pin_value - zeroPosition) )pitch = 0.0 + ( 0.10236220472440944881889763779528 * (pin_value - 63) )pitch is obviously dependant on pin_value, but if it were 12 pitch = -5.22..... If pin_value were 79, pitch = 1.63..... So far so good. Now, I want to display the value on the LCD, and this is where I'm getting a bit stuck. I want to only display the value to 1 decimal place (eg. 1.6323534 should be displayed as 1.6; and 1.0 should be displayed as 1.0), and I want to display the + or - sign. As I don't know C very well, like how to round down a float, or how the MIOS_LCD_Print* routines would handle a float and the polarity sign I decided to do it myself: unsigned char totalPitch = 13; unsigned char totalPossibleValues = 127; unsigned char zeroPosition = 63; float eachIncrementValue; float pitch; unsigned char wholeNum; float remainder; eachIncrementValue = (float)totalPitch / totalPossibleValues; pitch = 0.0 + ( eachIncrementValue * (pin_value - zeroPosition) ); // position the cursor on the correct display if (pin==0) { MIOS_LCD_CursorSet(0x46); } else { MIOS_LCD_CursorSet(0xc6); } // if the pitch is negative then we need to display the minus sign, then multiply the value by -1 so we get the positive value if (pitch < 0.0) { MIOS_LCD_PrintChar('-'); pitch = pitch * -1; } else if (pitch == 0.0) { MIOS_LCD_PrintChar(' '); } else { MIOS_LCD_PrintChar('+'); } wholeNum = pitch; // this will explicitally truncate the fractional portion of the pitch - so we are left with the whole number MIOS_LCD_PrintBCD1((unsigned char)wholeNum); MIOS_LCD_PrintChar('.'); remainder = (pitch - wholeNum) * 10; MIOS_LCD_PrintBCD1((unsigned char)remainder); It all works with the exception of the line that attempts to convert a negative value to a positive: // if the pitch is negative then we need to display the minus sign, then multiply the value by -1 so we get the positive value if (pitch < 0.0) { MIOS_LCD_PrintChar('-'); pitch = pitch * -1; } else The code goes into the if block correctly, and the - sign is correctly displayed. However, the pitch = pitch * -1; appears to corrupt the value, and what I get printed on screen is -F.F for any negative value !! I have tried pitch = pitch * -1; pitch = pitch * (-1); pitch = pitch - pitch - pitch; None of these work; and so all I can assume is there is something odd about a C float ??Any ideas anyone ?CheersJD Quote Link to comment Share on other sites More sharing options...
stryd_one Posted March 28, 2007 Report Share Posted March 28, 2007 Not quite an answer but... Floating point math be mightily slow. Also, you should have a totalPossibleValues of 128, don't forget we're counting from zero.Aaaanyway... http://www.ucapps.de/mios_c_send_range.html Do it the easy way, steal it from TK hahahahaPost with an explanation. Quote Link to comment Share on other sites More sharing options...
audiocommander Posted March 28, 2007 Report Share Posted March 28, 2007 Hi JD,I'm always using triple subtraction to avoid multiplications and therefore the implementation of the SDCC lib which blows up the codesize (although in your case it wouldn't help, 'cause floats also need the lib):(+2) - (+2) - (+2) = (-2)(-5) - (-5) - (-5) = (+5)I quite sure it does not work for you, 'cause you'll need a [tt]signed[/tt] type somewhere. I think, SDCC interprets [tt]int[/tt] as [tt]unsigned int[/tt] by default. I haven't seen no [tt]signed float[/tt] in your code snippets.Then there are some helping functions for displaying numbers on the display.Not sure how/if it works with floats, but you can increase the float by multiplying it with ten and then display the result via (BCD = Binary Coded Digital with x chars):MIOS_LCD_PrintBCD1()MIOS_LCD_PrintBCD2()MIOS_LCD_PrintBCD3()12 as BCD3 would be printed as '012'. 11 as BCD1 would be printed as '1'.see the function reference listing on ucApps.Hope this helps,best regards,Michael Quote Link to comment Share on other sites More sharing options...
stryd_one Posted March 28, 2007 Report Share Posted March 28, 2007 Hey AC I've been using a fairly new SDCC and it is using the MULWF instructions now, so it's not such a stress :DIn fact I think the 2.6.0 release does it too? Quote Link to comment Share on other sites More sharing options...
Lall Posted March 28, 2007 Report Share Posted March 28, 2007 Hi JD,Have you tried with the following? pitch = pitch * -1.0f; Note that the following that you tried should work too: pitch = pitch - pitch - pitch;Stupid question but have you included the float library? I guess so otherwise you should have errors/warnings of undefined stuff.And is the memory model of the library matching the memory model of your program? I don't remember if it's applicable in this context of SDCC, I used it too long ago...Maybe you can look at what the compiler is generating in terms of assembly code from your code to check how this code is interpreted.Best regards,Lall Quote Link to comment Share on other sites More sharing options...
audiocommander Posted March 28, 2007 Report Share Posted March 28, 2007 Note that the following that you tried should work too:Code: pitch = pitch - pitch - pitch;As I already wrote, I believe it does not work, cause pitch is declared just as "float" and it should be "signed float". I'm using this and it works for me.@stryd: good to know. maybe I should give this one a try (although it was an unbelieveable hassle to get SDCC running last time)...Regards,Michael Quote Link to comment Share on other sites More sharing options...
Lall Posted March 28, 2007 Report Share Posted March 28, 2007 As I already wrote, I believe it does not work, cause pitch is declared just as "float" and it should be "signed float". I'm using this and it works for me.The SDCC doc talks about IEEE float support and to me IEEE float is signed by default but I may be wrong.I've actually never seen an unsigned float anywhere and on the bunch of platform I've used float is always signed float.But anyway I would say it's worth a try, it cost only very little time to do it and who knows about the oddities of a compiler or another ;)Best regards,Lall Quote Link to comment Share on other sites More sharing options...
Jakes Daddy Posted March 28, 2007 Author Report Share Posted March 28, 2007 Thanks for all the replies gents. You'll be pleased to hear that I have sorted it now ;D. The problem was one of those very subtle ones ......My original code was as I originally posted, and in particular the problem was here:void UpdatePitchValues(unsigned char pin, unsigned int pin_value) __wparam { unsigned char totalPitch = 13; unsigned char totalPossibleValues = 128; unsigned char zeroPosition = 63; float eachIncrementValue; float pitch; unsigned char wholeNum; float remainder; eachIncrementValue = (float)totalPitch / totalPossibleValues; pitch = 0.0 + ( eachIncrementValue * (pin_value - zeroPosition) );pin_value and zeroPosition are both unsigned, and the subtraction in brackets in the pitch=..... line would have resulted in an unsigned int.If pin_value was over 63 (the zeroPosition), the subtraction would have been correct, and the result would be a positive integer.If pin_value was below 63, the subtraction would have been incorrect, and the result would have been a very very large positive integer.So, my solution is to do the subtraction into a separate signed int as follows:void UpdatePitchValues(unsigned char pin, unsigned int pin_value) __wparam { unsigned char totalPitch = 13; unsigned char totalPossibleValues = 128; unsigned char zeroPosition = 63; signed int multiplier; float eachIncrementValue; float pitch; unsigned char wholeNum; float remainder; eachIncrementValue = (float)totalPitch / totalPossibleValues; multiplier = pin_value - zeroPosition; pitch = 0.0 + ( eachIncrementValue * multiplier );So, as I said, a very subtle problem, but I'm glad its sorted now ! ;D Quote Link to comment Share on other sites More sharing options...
Lall Posted March 28, 2007 Report Share Posted March 28, 2007 Héhé, excellent news :)The solution is indeed very logical... once it's found ;)Best regards,Lall Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.