Jump to content

Neil

EstablishedMember
  • Content Count

    26
  • Joined

  • Last visited

Community Reputation

0 Neutral

About Neil

  • Rank
    Regular
  1. Hi I complained too soon!! It seems my code does not fit into the ROM!!! Sorry for the false alarm. May be a more informative message from the IDE? Just a thought. Thanks Neil Hi I have just upgraded to 6.97 from 6.96 While re-building my project, the IDE is failing. It seems the linker is running out of memory when linking my project. There are many object files and the float lib. I am bulding for a PIC18F8722 running at 40Mhz I do not know if this is a new bug, but it has just started after my upgrade to 6.97 I am close to a product release, so this is a real problem for me. A sollution or work around would be very welcome. I am happy to send the project, but not post it on an open forum. Thanks Neil
  2. Hi PeterK Its been a while since I have be on the boards, so sorry for the late reply. While developing my own code, I had a need for float math. I soon found, as may had that BoostC++ does not provide any. So, as a service, I freely gave away my source code. No license, do with as you see fit. Kindly, some have helped to improve it. I am no compiler writer, so excude me for a poor implementaton. I will look into Henry Pade, may be I can write a better lib. While I apreciate your comments, and your clear knowledge on this point, I do not see any source code to help the rest of the community. May be you could share your code as I have done. regards Neil
  3. Hi Dave Thanks for the update Neil
  4. Hi I think I have bumped into a compiler bug. I am using 6.96 pro on XP. I have code that allocates an array of structs, similar to the following struct foo { unsigned char a; unsigned char b; unsigned char c; unsigned char d; } foo myFoo[256]; If I go above 256 then i get a comiler warning to use a switch that will be in 7.0. This makes sence to me. Cant do this yet. If I stick to 256 It compiles, runs and has all sorts of run time errors, which apear to be memory coruption. If I go down to 64, all is well.! I thought that the bigest size array was limited to 1 code bank, so 256? If thi is so, the compiler should check the size of the array and the size of the object. I susspect that a bug has crept in during 7.0 evelopment. Im sure it did not use to do this. Comments welcome. Neil
  5. Hi All Is the source code for the float lib avalible? I need to implement a 16bit floating point value, and the src would give me a head start. Thanks Neil
  6. Hi Dave and Reynard Thanks for the interest. Im more than happy for the code to go into BoostC. From the tests I have doen, all the paths functions work correctly. The could be faster, but Reynard seems to be on the case. I feel they really need some testing by others to shake out any other bugs. Feel free to include my code into BoostC. I dont know when I will next get time to work on this code. It just depends on what project Im working on. Best regards Neil PS I do think sprintf32 is now working!!
  7. Hi Reynard Thanks for the bug fix. I have not tested the functions to distruction, so I expect some bugs. As I use a function I test it more!! I first wrote these under gcc/linux and compared the resulst over many values. Porting to PIC float lib was not as simple as I expected, mainly due to rounding etc. If there is a better place for this code Im happy to donate it. Also, I just put a bug fix into sprintf32f. Id would print 1.002 as 001.2 !!! Fixed now!!!! Neil
  8. Neil

    Float Lib Bug

    Hi Reynard It seems you are the only one who ever replys to me!! I dod not use the simulator, I used a real PIC18. May be that accounts for the difference? Neil
  9. Hi I found that both sprintf and sprintf32 contain the code fragment // Next character if valid digit indicates field width unsigned char fieldWidth = 0; while( c > '0' && c <= '9' ) { fieldWidth *= 10; fieldWidth += c; fieldWidth -= '0'; c = format[fi++]; // read next string format character if ( !c ) goto end; // end of format string reached } Which I think should be // Next character if valid digit indicates field width unsigned char fieldWidth = 0; while( c >= '0' && c <= '9' ) { fieldWidth *= 10; fieldWidth += c; fieldWidth -= '0'; c = format[fi++]; // read next string format character if ( !c ) goto end; // end of format string reached } Note the c > '0' is now c >= '0'. With the original code if you do %f10.2 for example, the width is set to 1 as the zero is ignored Neil OS XPpro, BoostC++ 6.90, PIC18f8722
  10. Neil

    Float Lib Bug

    Hi It seems that code like: float foo; float bar[2]; foo = bar[1]; does not correctly copy values. You can work round this using memcpy((void*)&foo, (void*)&bar[1], 4) Neil OS XPpro, BoostC++ 6.90 PIC18f8722
  11. Hi Dave Thanks for the note. I know it is difficult to say, but when do you expect to have this feature? I may well delay my development of the bit of my code. Thanks Neil
  12. Hi all I dont know if this is where I should do this, so sorry if Im in error. I have seen some posts regarding float maths functions. Here is some code that I have writen to provide some functions. I dont clame it to be fast or even bug free, but it works for me. If you find it usfull all well and good. Ive added an sprintf32 function. The code is derived from BoostC stdio.c. e.g. sprintf32f(myStr, "%8.2f", myFloat); The format string is:- "%[optional '-'][optional ' ' or '+'][optional width][optional .precision]f" were '-' gives left justification were '+' always shows the sign (except if it is zero) were ' ' pads a positive sign value with one space were the - or + would be were width is the total width of the value, all chars including sign, decimal point and padding MAY TRUNCATE were . (period) precision is the number of chars after the decimal point. a value of 0 supresses the decimal point Also added atof Added bug fixes in both sprintf32f and atof Added yet another bug fix to sprintf32f Neil #ifndef _mcuMath_h #define _mcuMath_h #include <float.h> unsigned char sprintf32f( char* buffer, const char *format, float val ); float atof(char* str); float mcu_sin(float x); float mcu_cos(float x); float mcu_tan(float x); float mcu_asin(float x); float mcu_acos(float x); float mcu_atan(float x); float mcu_epowx(float x); float mcu_ln(float x); float mcu_log10(float x); float mcu_xpown(float x, float n); #endif // _mcuMath_h The code #include <float.h> #include "mcuMath.h" const float mcu_PI = 3.14159265359; const float mcu_hPI = 1.57079632679; const float mcu_E = 2.71828182846; float mcu_sin(float x) { float_rounding_mode = float_round_down; float ac = 0.0; float nv = 1.0; float xv = x; for(unsigned char cnt = 2; cnt < 50; cnt+=2) { ac = float32_add(ac, float32_div(xv, nv)); nv = float32_mul(nv, float32_mul(float32_from_int32((int32)cnt), float32_from_int32((int32)(cnt + 1)))); xv = float32_mul(xv, float32_mul(x, x)); xv = float32_mul(xv, -1.0); } return ac; } float mcu_cos(float x) { float_rounding_mode = float_round_down; float ac = 0.0; float nv = 1.0; float xv = 1.0; for(unsigned char cnt = 1; cnt < 50; cnt+=2) { ac = float32_add(ac, float32_div(xv, nv)); nv = float32_mul(nv, float32_mul(float32_from_int32((int32)cnt), float32_from_int32((int32)(cnt + 1)))); xv = float32_mul(xv, float32_mul(x, x)); xv = float32_mul(xv, -1.0); } return ac; } float mcu_tan(float x) { return float32_div(mcu_sin(x), mcu_cos(x)); } float mcu_asin(float x) { return mcu_atan(float32_div(x, float32_sqrt(float32_sub(1.0, float32_mul(x, x))))); } float mcu_acos(float x) { float_rounding_mode = float_round_down; float ac = 0; ac = mcu_atan(float32_div(float32_sqrt(float32_sub(1.0, float32_mul(x, x))), x)); if(float32_lt(x, 0) != 0) ac = float32_add(mcu_PI, ac); return ac; } float mcu_atan(float x) { float_rounding_mode = float_round_down; unsigned char inv = 0; if(float32_gt(x, 1.0) != 0) { x = float32_div(1.0, x); inv = 1; } if(float32_lt(x, 1.0) != 0) { x = float32_div(1.0, x); inv = 2; } float ac = 0.0; float nv = 1.0; float xv = x; for(unsigned int cnt = 1; cnt < 500; cnt++) { ac = float32_add(ac, float32_div(xv, nv)); nv = float32_add(nv, 2.0); xv = float32_mul(xv, float32_mul(x, x)); xv = float32_mul(xv, -1.0); } if(inv == 1) { ac = float32_sub(mcu_hPI, ac); } if(inv == 2) { ac = float32_add(mcu_hPI, ac); ac = float32_mul(ac, -1.0); } return ac; } float mcu_epowx(float x) { float_rounding_mode = float_round_down; int val = (int)float32_to_int32(x); x = float32_sub(x, float32_from_int32((int32)val)); float ac = 1.0; float nv = 1.0; float xv = x; for(unsigned char cnt = 1; cnt < 8; ++cnt) { nv = float32_mul(nv, float32_from_int32((int32)cnt)); ac = float32_add(ac, float32_div(xv, nv)); xv = float32_mul(xv, x); } float esum = 1.0; unsigned int cntL; if(val < 0) cntL = (unsigned int)(val * -1); else cntL = (unsigned int) val; for(unsigned int cnt2 = 0; cnt2 < cntL; ++cnt2) { if(val > 0) esum = float32_mul(esum, mcu_E); else esum = float32_div(esum, mcu_E); } return float32_mul(ac, esum); } float mcu_ln(float x) { float_rounding_mode = float_round_down; int cnt = 0; while(float32_gt(x, 1.0) != 0) { x = float32_div(x, 2.71828182846); cnt++; } x = float32_sub(x, 1.0); float ac = 0; float xv = x; for(unsigned char cnt2 = 1; cnt2 < 100; ++cnt2) { ac = float32_add(ac, float32_div(xv, float32_from_int32((int32)cnt2))); xv = float32_mul(xv, x); xv = float32_mul(xv, -1.0); } ac = float32_add(ac, float32_from_int32((int32)cnt)); return ac; } float mcu_log10(float x) { return float32_div(mcu_ln(x), 2.30258509299); // = ln(10.0); } float mcu_xpown(float x, float n) { float_rounding_mode = float_round_down; bool inv = false; if(float32_lt(n, 0.0) != 0) { n = float32_mul(n, -1.0); inv = true; } int val = (int)float32_to_int32(n); n = float32_sub(n, float32_from_int32((int32)val)); x = float32_sub(1.0, x); float ac = 0.0; float xv = 1.0; float nv = float32_mul(-1.0, n); float cv = 1.0; ac = float32_add(ac, xv); for(unsigned char cnt = 1; cnt < 25; ++cnt) { cv = float32_mul(cv, float32_from_int32((int32)cnt)); xv = float32_mul(xv, x); ac = float32_add(ac, float32_div(float32_mul(nv, xv), cv)); nv = float32_mul(nv, float32_sub(n, float32_from_int32((int32)cnt))); nv = float32_mul(nv, -1.0); } x = float32_sub(1.0, x); float xsum = 1.0; unsigned int cntL; if(val < 0) cntL = (unsigned int)(val * -1); else cntL = (unsigned int) val; for(unsigned int cnt2 = 1; cnt2 < cntL; ++cnt2) { if(val > 0) xsum = float32_mul(xsum, mcu_E); else xsum = float32_div(xsum, mcu_E); } ac = float32_mul(ac, xsum); if(inv == true) ac = float32_div(1.0, ac); return ac; } /////////////////////////////////////////////////////// // stdio.c /////////////////////////////////////////////////////// // This file is a part of the system libraries // supplied with BoostC C compiler distribution. // More information can be found on: // http://www.sourceboost.com // // You are allowed to use or modify this code as // long as the following conditions are met: // 1. this entire text from this comment block // remains intact; // 2. this code and derivative work are compiled and // linked with products from SourceBoost Technologies; // 3. the source code for the derivative work includes // prominent notice that the work is derivative. // // THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, // INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // APPLY TO THIS SOFTWARE. SOURCEBOOST TECHNOLOGIES SHALL // NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, // INCIDENTAL OR CONSEQUENTIAL DAMAGES, FOR ANY REASON // WHATSOEVER. // // Copyright(C) 2004-2008 Pavel Baranov // Copyright(C) 2004-2008 David Hobday // ///////////////////////////////////////////////////////////// // // Author: David Hobday // Date: 11/11/2006 // V1.00 11/11/2006 // Initial version. // // V1.01 18/02/2007 // Added sprintf32 function for 32bit values. // // // Auther: Neil Robinson 25-11-2008 // Added sprintf32f function for floats // unsigned char sprintf32f(char* buffer, const char *format, float val) { float_rounding_mode = float_round_down; unsigned char bi = 0, fi = 0; char c; while( 1 ) { c = format[fi++]; // read next string format character if ( !c ) goto end; // end of format string reached if( c != '%' // not format specifier || (c = format[fi++]) == '%' ) // %% sequence { buffer[ bi++ ] = c; // out character raw } else { unsigned char fillChar, fmatExp, signChar = 0; bit alignLeft = false; fillChar = ' '; // default fill character // process flags while( 1 ) { switch( c ) { case 0: goto end; // end of format string reached case '0': fillChar = '0'; break; case ' ': signChar = ' '; break; // show space in front of signed numbers when not negative case '+': signChar = '+'; break; // show sign on signed numbers case '-': alignLeft = true; break; default: goto processWidth; } c = format[fi++]; // read next string format character } processWidth: // Next character if valid digit indicates field width unsigned char fieldWidth = 0; while( c >= '0' && c <= '9' ) { fieldWidth *= 10; fieldWidth += c; fieldWidth -= '0'; c = format[fi++]; // read next string format character if ( !c ) goto end; // end of format string reached } if(c == '.') { c = format[fi++]; // read next string format character if ( !c ) goto end; // end of format string reached } unsigned char precision = 0; signed char preTmp = -1; while( c >= '0' && c <= '9' ) { if(preTmp == -1) preTmp = 0; preTmp *= 10; preTmp += c; preTmp -= '0'; c = format[fi++]; // read next string format character if ( !c ) goto end; // end of format string reached } if(preTmp == -1) precision = 6; else precision = (unsigned char)preTmp; unsigned char floatSignChar = 0; // Next character indicates the format switch( c ) { case 'f': { fmatExp = 0; if(float32_lt(val, 0) != 0) // Negative values must be adjusted to be positive { floatSignChar = '-'; val = float32_mul(val, -1.0); } } break; // fall through to next case intended default: goto end; // no radix specified - can't continue } long valFr = 0; long valIn = 0; long frMag = 1; for(unsigned char ct = 0; ct < precision; ++ct) { valFr *= 10; frMag *= 10; } valIn = (long)float32_to_int32(val); valFr = (long)float32_to_int32(float32_add(float32_mul(float32_sub(val, float32_from_int32((int32)valIn)), float32_from_int32(frMag)), 0.5)); frMag--; if((valIn == 0) && (valFr == 0)) floatSignChar = 0; if(floatSignChar == '-') signChar = floatSignChar; unsigned char digitWidth = 0; { // determine number of digits in the number unsigned long valx = (unsigned long)float32_to_int32(val); do { digitWidth++; valx /= 10; } while( valx != 0 ); } // sign takes extra space if( signChar != 0 ) digitWidth++; // precision takes extra space digitWidth += precision; // one for the decimal point if(precision > 0) digitWidth++; // limit digit width to prevent buffer overflow - not standard, but will prevent buffer overrun corruption unsigned char fillWidth = 0; if( fieldWidth > 0 ) { if( digitWidth > fieldWidth ) // limit number of digits digitWidth = fieldWidth; fillWidth = fieldWidth - digitWidth; } else { fieldWidth = digitWidth; fillWidth = 0; } if( fillWidth == 0 ) alignLeft = false; // alignment serves no purpose if no fill // we reverse fill string, so start at the end bi += fieldWidth; bit doFill = alignLeft; // if left aligning do fill first. unsigned char fracFlg = precision; while( digitWidth != 0 || fillWidth != 0 ) { bi--; if( doFill ) { c = fillChar; if( --fillWidth == 0 ) doFill = false; } else { if( --digitWidth == 0 && signChar ) // last digit and sign character c = signChar; // add sign character else if (frMag > 0) { c = (char)(valFr % 10 ); c += '0'; // convert to digit character 0-9 valFr /= 10; frMag /= 10; fracFlg = 0; } else if ((valFr == 0) && (precision > 0)) { if(fracFlg > 0) { c = '0'; fracFlg--; } else { c = '.'; valFr = -1; } } else { c = (char)(valIn % 10 ); c += '0'; // convert to digit character 0-9 valIn /= 10; } if( digitWidth == 0 ) doFill = true; } buffer[ bi ] = c; } bi += fieldWidth; } } end: buffer[ bi ] = 0; // null terminate return bi; } float atof(char* str) { if((str == 0) || (strlen(str) == 0)) return 0; int hl = 0; int fr = 0; float retVal = 0; char* pntPtr = strrchr(str,'.'); for(char ct = strlen(str) - 1; ct >=0; --ct) { if(str[ct] != '0') break; str[ct] = 0; } if(pntPtr != 0) { fr = atoi(pntPtr + 1); *pntPtr = 0; } hl = atoi(str); char foo[32]; if(pntPtr != 0) { *pntPtr = '.'; float pwr = 1.0; for(unsigned char ct = 0; ct < strlen(pntPtr + 1); ++ct) { pwr = float32_mul(pwr, 10.0); } retVal = float32_div(float32_from_int32((int32) fr), pwr); } if(hl < 0) { retVal = float32_sub(float32_from_int32((int32) hl), retVal); } else { retVal = float32_add(float32_from_int32((int32) hl), retVal); } return retVal; }
  13. Hi With reference to my post in the C++ section. Would it be possible to add a #PRAGMA type command to force a function to be located at a defined start location in memory? Somthing lic ORG in asm. I can bodge this using the linker. I can also use this be converting a function to hex and encoding it as a #pragma data command, but these are far from ideal. Thanks to Reynard for these comments and sugestions void func(int par) org 0x200 { // Function will start at address 0x200 nop; } OR #pragma funcorg <func_name> <starting_address>
  14. Neil

    Sprintf32 Bug?

    Hi All I think this shows a lib / compiler bug. If you run this code in the debuger (and on a real PIC18F) then the 32 bit function produces an error. sprintf32 gives 999 sprintf gives 9999 So, sprintf32 misses out one digit. It only seems to do this for numbers over 99. I have not looked at negative numbers Can this be confirmed as a bug? If so can it be fixed? Thanks Neil OS XPpro, BoostC++ 6.90 PIC18f8722 char buf[64]; char* bufP = buf; unsigned long tl = 9999; sprintf32(bufP, "%d", tl); unsigned int ti = 9999; sprintf(bufP, "%d", ti); I know I dot need bufP but this helps the debugger show the text string in the watch window. I have now compiled the sprintf32 code in libc and this works just fine for me.
  15. Hi All Well, I thought Id open up my last question in a hope that I get even more help. If I have a function void foobar() { nop(); } For example, how do I force it to be at FLASH ROM address 0x8000? Im thinking of the asm org 0x8000 command but in BoostC++. Can this be done? Is it a linker thing? I need to put a function in a safe block of FLASH so it is NOT erased as I do an on the fly re-program of the firmware. All thoughts welcome Neil
×
×
  • Create New...