wackazong Posted September 28, 2008 Report Share Posted September 28, 2008 Hi,I have a strange bug using an ASM function in a C applikation: When I call the ASM function, random values get written into the variable RAM. I would be very glad if somebody could have a look a the header and main file, I cannot find the problem...The header file/* */ #ifndef _KNOEPFLI_ASM_H #define _KNOEPFLI_ASM_H ///////////////////////////////////////////////////////////////////////////// // Prototypes ///////////////////////////////////////////////////////////////////////////// extern unsigned char KNOEPFLI_Interpolate(unsigned char step, unsigned char val1, unsigned char val2) __wparam; #endif /* _KNOEPFLI_ASM_H */ The main file radix dec #include <mios.h> #include <mios_vectors.inc> #include <macros.h> ; ========================================================================== ; Define constants ; ========================================================================== ; ========================================================================== ; Import/Export Labels ; ========================================================================== ; export labels global _KNOEPFLI_Interpolate ; (for C, ) ; ========================================================================== ; Declare variables ; ========================================================================== accessram udata pca9635_StepCounter res 1 pca9635_Temp res 1 ; ========================================================================== ; Start code section and include driver code ; ========================================================================== KNOEPFLI_ASM CODE ; ========================================================================== ;; -------------------------------------------------------------------------- ;; FUNCTION: KNOEPFLI_Interpolate ;; C_DECLARATION: void KNOEPFLI_Interpolate(unsigned char step, unsigned char val1, unsigned char val2) ;; DESCRIPTION: Testing the interpolation algorithm: interpolate between value 1 and value 2 in ;; 16 steps and return the corresponding step value. ;; ;; C IN: step number in step (through WREG, using __wparam) ;; value 1 in val1 ;; value 2 in val2 ;; ;; C OUT: interpolated value as unsigned char (through WREG __wparam) ;; ;; USES: MIOS_PARAMETER3 ;; -------------------------------------------------------------------------- _KNOEPFLI_Interpolate KNOEPFLI_Interpolate ;save step value in variable movwf pca9635_StepCounter movff FSR0L, FSR2L ; get other arguments from stack movff PREINC2, MIOS_PARAMETER1 movff PREINC2, MIOS_PARAMETER2 ;find out if we have to swap the values ;move MIOS_PARAMETER1 into W movf MIOS_PARAMETER2, W ;compare, skip the swap if MIOS_PARAMETER2 > MIOS_PARAMETER1 cpfsgt MIOS_PARAMETER1 rgoto pca9635_interpolate_NoSwap ;we just swap the values and invert the step counter ;using a temporary variable movff MIOS_PARAMETER1, pca9635_Temp movff MIOS_PARAMETER2, MIOS_PARAMETER1 movff pca9635_Temp, MIOS_PARAMETER2 ;invert the step counter and delete the upper nibble (for four bit counter) comf pca9635_StepCounter, F movlw 0x0f andwf pca9635_StepCounter, F pca9635_interpolate_NoSwap ;now find the difference between MIDI_PARAMETER1 and MIDI_PARAMETER2 ;load MIDI_PARAMETER1 into W movf MIOS_PARAMETER1, W ;subtract W from MIOS_PARAMETER2, store result in W subwf MIOS_PARAMETER2, W ;add 1 for rounding errors addlw 1 ;now divide this value by the number of steps ;because the next operation is a floating point 16bit calculaton, we leave it ;as it is and take away the decimals later ;to get the result in the upper byte PRODH, shift the step ;counter four to the left (for 4-bit counter) rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F rlncf pca9635_StepCounter, F ;therefore, multiply the difference with the number of steps mulwf pca9635_StepCounter ;now we just need to get the high byte movf PRODH, W ;add the MIOS_PARAMETER1 (the low value) addwf MIOS_PARAMETER1, W return ; ========================================================================== END When I run the function, another array in my program gets values written into it, and I don't know why. Any tips for how to debug something like this?The array that gets written into is passed as the first parameter value (not the array, but one part of it, of course, like array ).Thanks, ALEXander. Quote Link to comment Share on other sites More sharing options...
TK. Posted September 28, 2008 Report Share Posted September 28, 2008 The variables are probably not located in the ACCESS bank -> use SET_BSR to select the bank, add ", BANKED" after instructions which are accessing the variables.Under http://svnmios.midibox.org/listing.php?repname=svn.mios&path=%2Ftrunk%2Fmodules%2F you will find several programming examples, e.g. http://svnmios.midibox.org/filedetails.php?repname=svn.mios&path=%2Ftrunk%2Fmodules%2Fblm%2Fblm.inc (search for BANKED)Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
wackazong Posted September 29, 2008 Author Report Share Posted September 29, 2008 Ups, doesn't the line accessram udata tell the linker to put these variables into the accessram?I will check the .map file. Quote Link to comment Share on other sites More sharing options...
TK. Posted September 29, 2008 Report Share Posted September 29, 2008 No, you would have to write "udata_acs" instead of "udata"However, there is no reason why not using BANKED memory range. It won't really have an impact on the performance of your function.Best Regards, Thorsten. Quote Link to comment Share on other sites More sharing options...
wackazong Posted September 29, 2008 Author Report Share Posted September 29, 2008 OK, then that was it. However, I did it in C now, does not really slow down anything..... Still learning... :)At least now i get a smooth interpolation between 0 and 32 steps (which is 33 steps in total).Best, ALEXander..///////////////////////////////////////////////////////////////////////////// // Interpolate ///////////////////////////////////////////////////////////////////////////// unsigned char KNOEPFLI_Interpolate32(unsigned char step, unsigned char value1, unsigned char value2) { unsigned char swap, diff; //send out value2 if step is the max value if( step == 32 ) { return value2; }; //send out value1 if step i 0 if( step == 0 ) { return value1; }; //invert the interpolation if value1 > value2 if( value1 > value2 ) { //swap the values swap = value2; value2 = value1; value1 = swap; //--step because we are counting from 0 to 32, not to 31 --step; //invert the step counter step = ~step; //clear the upper three bits step &= 0x1f; }; //get the difference diff = value2 - value1; //divide it through the total number of steps (>>5) and multiply it with step (gives an integer) then get the high byte, //shift the step counter three to the left to make it 8bit, store it in PRODL PRODL = step << 3; //store diff in PRODH PRODH = diff; //do the multiplication in assembler __asm movf _PRODL, W mulwf _PRODH, 0 __endasm; //add the lower value return value1 + PRODH; } Quote Link to comment Share on other sites More sharing options...
stryd_one Posted September 29, 2008 Report Share Posted September 29, 2008 Crosspost 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.