Santiago, tried your signed math library, and it looks very good, thanks for sharing it with us! Posted here, as did not want to clutter up your contributors thread.
Maybe a sign thing going on with the signed_add function? Not really sure, it very likely is my output routine, so please take with a grain of salt. Looking at assembly makes my gears grind to a slow crawl. It occurs with value2 equal to result in your equation, with value2's of 0, -1, -2, -3, -4, -5 and the new result is -2, -1, 0, -1, -1, -3 ????
One suggestion is make two sets of equations, one for bytes, one for words. Then one would check the byte.7, and word_H.7 respectively for the sign bit. That gives a range +/-127 and +/-32,767 respectively. Having the +/-127 gives you binary radians, if my recollection is right.
Made up a routine to test your modules using an LCD, along with a button, and a state machine. It can be painful to look at others code, but will post it if you or others request.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Kent, I know nothing about this stuff. Is this the solution to the problem I was struggling with in the PID and A_D threads? The problem of dealing with negative numbers.
I solved the problem but it was pretty ugly! There must be a better way.
If not, what is the correct way of dealing with it? Thanks for all your help. Santiago is a smart fellow.
Everything about these PIC is a struggle for me as I missed out on the hexadecimal stuff by avoiding digital crap, and all the programming stuff by discovering spreadsheets.
These threads are an enormous help to learning this stuff. I have Soooooooo Farrrrrrr to go!
I think Great Cow is the best thing since sliced bread, or maybe the light bulb!!
Regards, Ed.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ed:
I did the functions for use it in my motors PID, but can be used (carefully) in any simple signed calculations.
I saw the way you solved signs in your filter, in that case i think your's is the best solution; in the case of PID, things can be complex and signed math can help a lot to keep a simple and clear code. I'm just testing it... still starting to work in my PID, that's why i didn't offer you this as a solution until i'm sure about it; but it could be great if you want to try it, just for testing the functions, any feedback will be apreciated.
Kent.. thought english is not my mother-tongue and sometimes is difficult for me understanding somethings...
About the problem you report it could be great when you post a piece of code where the problem happens, including variable declarations to see what is really happening. I'm very interested in finding bugs, then this will be very apreciated.
>One suggestion is make two sets of equations, one for bytes, one for words. Then one >would check the byte.7, and word_H.7 respectively for the sign bit. That gives a range >+/-127 and +/-32,767 respectively. Having the +/-127 gives you binary radians, if my >recollection is right.
Good idea!!.. i have to think in it... but this should require to re-write the complet math routines ( or not... it needs some thoughts...).
what i did in the signed functions is a very simple thing... is just a select case with all the possible combinations of signs, then doing standard add or substract low bytes in the proper order, and set or clear the first bit of the high byte as a sign flag... It stays in the easy side, can solve some basic calculations, but is not very eficient.
Anyway i will try to explain how to use the functions and what you can and cannot do:
One important thing is you cannot do standard math operations with the variables used in these functions... you can have erroneus results as bit0 of high byte is used as sign flag.
The variables are declared as word just to have a high byte to manage sign flag, but they are just byte (0-255) variables for the functions (not for GCBasic).
For example:
dim value1 as word
dim value2 as word
dim result as word
value1=2
value2=8
result=0
result = Signed_Sub(value1, value2) 'result = 2-8 = -6
Now result= 00000001 00000110
this is:
result = 00000110 = 6 'absolute value of the variable
result_H = 000000001 'sign flag is high = this is a negative number
But for GCBasic in terms of "word" value:
result= 00000001 00000110 = 262
if now you do "standard" math operation with this variable, for example:
dim my_variable as word
my_variable = result + 10
you will have:
my_variable = 262 + 10 = 272
But if you do this:
dim my_variable as byte
my_variable = result + 10
then you will have:
my_variable = 6 +10 = 16
When you want to "switch" to standard math you can do (for example):
if result_H = 1 then
result_H = 0
my_variable = 10 - result
End if
if result_H = 0 then my_variable = 10 + result
Then when using the resultant value you need to take in account that you cannot use it directly as a word variable, but you can use the absolute value in the low bit and the sign in the high bit.
For example you can take low bit to set the motor speed and high bit to set direction of spining...
You can take this values using byte variables, for example:
dim output as byte
dim sign as byte
output = result
sign = result_H
And then you can do standard math with "output" variable.
In order to solve this "problems" signed variables should be included in compiler's core... but i think this is not a child's play.
Keep sharing ideas...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
>I know nothing about this stuff. Is this the solution to the problem I was struggling >with in the PID and A_D threads? The problem of dealing with negative numbers.
Ed, not sure if the signed numbers is your solution or not. Have yet to have a play with your a-d filter or PID. In this regards, I am the student.
Have been spending efforts on a 2 axis accelerometer used for angle calculation. So, the joy of SIN lookup tables, of late. It's been ages since I've cracked a math book.
Santiago, don't worry about your English, your explanations and code are very clear.
Tracked down the piece of code that gives a hiccup. It has to do with the reuse of the signed_add function by the signed_sub function. First off, the signed_sub function appears fine.
In order for the signed_add function to work properly the following code needs to be looked at. The test condition is when the signed first_val is added to a positive second_val, and when the absolute first_val is less than the positive second_val. For instance try using:
value1 = -1
value2 = 2
result = Signed_Add(value1, value2) ;i.e. result = -1 + 2 = +1
;The returned value of result is -1 not +1 as you would expect.
Signed_Add function
...
...
general_sub:
MOVF second_val,W
SUBWF first_val,W
BTFSC STATUS,C
goto exit_general_sub
if Signed_Add_H.0 on then set Signed_Add_H.0 off 'toggle sign
;the following line of code needs to be commented out for signed_add to work
;but doing so busts the Signed_Sub function
;**************************************
'if Signed_Add_H.0 off then set Signed_Add_H.0 on
;**************************************
The functions just do the maths, but assigning negative values to variables is not possible, then this will not work:
value1 = -1
Take in account that these are just some external functions... the compiler doesn't know anything about signs...
in order to assign negative values to variables, authentic signed variables should be implemented in GCBasic compiler's core... that's still too much for me...
these signed functions are a tool to deal with math operations that could result in negative values, anyway what you try is possible:
to set initial negative values you can do this way:
____________________________________________________________
dim value1 as word
dim value2 as word
dim result as word
value1 = 10
value1_H = 1 'this set negative flag to value1
value2 = 20
result = Signed_Add(value1, value2)
____________________________________________________________
In this case result will be positive and there is no problem when you want to use this value, but you have to take in account that when result is a negative value you have to manage it properly...
For example i did some testing in order to control a motor with pwm, the motor controller is conected to PIC at PWM pin and PORTC.0 pin
I did the calculations with signed functions, and have a word variable called "result":
_________________________________________________________________________
dim result as word
dim output as byte 'BYTE VARIABLE
dim direction as byte
'i do signed calculations
........
.........
........
'Now i have the resultant value in "result" variable ( type: word)
'Now i proceed to pass the values to PWM and turn direction:
output = result 'here only the low byte of result is passed to "output" as output is a byte variable
direction = result_H 'here the high byte of result is passed to "direction" (just 1 or 0)
PORTC.0 = direction.0 'this will determine the turn direction of the motor
if direction.0 on then output = 255 - output 'if reverse turn then invert pwm
Note that the "flag bit" (result_H.0) is used to determine if the motor turns ahead or reverse
When in reverse turn, the "active" side of PWM is the low state (as PORTC.0=1) then inverting the signal is needed.
Note that for using the "result" value and sing i used two BYTE variables not word variables.
I hope this can be understood...
This functions are not the most easy to use but can be a useful tool; anyway any idea to improove it will be apreciated.
Anyway as external fuctions the capablities are very limited and far from real signed variables.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Santiago, sorry didn't mean -1 in the literal sense. My code is handling the negative sign in the value1_H.0 prior to the signed_add function, and then also after the returned value (result) of the signed_add function.
If you can hook up and LCD and use the code below, then it better explains, than my words to you. In the pressing of the state machine button input (pullup on input pin) you can toggle between the different signed math modules.
Perhaps there is an error in my code?, in which case, all apologies extended.
As previously noted in the signed_add function there is a discrepancy, when the absolute of the signed value (say value1) is less than an unsigned value (say value2). When value1 goes from signed 0, 1, 2, 3, 4, 5, 6..., and added to say a value2 of 4, the resultant goes from -4, -3, -2, -1, 0, -1, -2.........When in fact the resultant should be 4, 3, 2, 1, 0, -1, -2......... Please beg your pardon for the visual representation of the resultant numbers, but it seems easiest to describe this way to me.
You do not have to hook up the LCD example. Just try to use your flow of the code, and you will find that the when the absolute value of value1 is less than the unsigned value2 number, the Signed_Add_H.0 needs to be set "off" to represent a positive (unsigned) number. The addition of the following code makes it work.
general_sub:
;additional code to fix bug
absolute_first_val = first_val ;get lower byte of first_val
if absolute_first_val < second_val then
set Signed_Add_H.0 off
MOVF first_val,W
SUBWF second_val,W
goto exit_general_sub
end if
Here is my test code for your modules with an LCD, hope it helps.
'Test of Signed Math Library 2/21/09 by Santiago Glez
'Chip model
#chip 16f877a,20
#define Button PortE.2 ;Button pulled up by hardware
dir Button in
#define waitbutton wait 1 10ms
#define lcdwait wait 50 10ms
dim value1 as word
dim value2 as word
dim result as word
value2=4
result=0
counter = 0
Main:
Subtract:
ExitModule = False
counter += 1
For testnum1 = 0 to 127 ;keep operations less than byte
If Button Off then DebounceButton
If ExitModule = True Then goto Exit1
value1 = testnum1 + 256 ;make a negative value
result = Signed_Sub(value1, value2)
locate 0,0:Print "Subtract "
Output ;display on lcd
lcdwait
Next
Exit1:
Multiply:
ExitModule = False
counter += 1
For testnum2 = 0 to 63
If Button Off then DebounceButton
If ExitModule = True Then goto Exit2
value1 = testnum2 + 256 ;make negative value
result = Signed_Mul(value1, value2)
locate 0,0:Print "Multiply "
Output
lcdwait
Next
Exit2:
Addition:
ExitModule = False
counter += 1
For testnum3 = 0 to 127 ;keep operations less than byte
If Button Off then DebounceButton
If ExitModule = True Then goto Exit3
value1 = testnum3 + 256 ;make negative value
result = Signed_Add(value1, value2)
locate 0,0:Print "Addition "
Output ;display on lcd
lcdwait
Next
Exit3:
Division:
ExitModule = False
counter += 1
For testnum4 = 0 to 252 step 4 ;keep operations less than byte
If Button Off then DebounceButton
If ExitModule = True Then goto Exit4
value1 = testnum4 + 256 ;make negative value
result = Signed_Div(value1, value2)
locate 0,0:Print "Division "
Output ;display on lcd
lcdwait
Next
Exit4:
'Now result = 5, result_H = 1 (negative)
'Locate 1,0
'If result >= 10000 then PRINT "Calc ":Print result
'If result >= 1000 AND result < 10000 then Print "Calc ":PRINT result
'Next
Goto Main
Sub Output
Minus = False
If result.8 On Then
result = result - 256
If result >= 0 Then Minus = True
End if
If result >= 100 AND result < 1000 then NegSign:PRINT result
If result >= 10 AND result < 100 then Print " ":NegSign:PRINT result
If result < 10 AND result > 0 then Print " ":NegSign:PRINT result
If result = 0 Then Print " 0"
end sub
Sub NegSign
If Minus = True Then
Print "-"
Else
Print " "
End if
end sub
Sub DebounceButton
If Button Off then
ButtonCount = 0
Do While Button off
waitButton
ButtonCount += 1
Loop
If ButtonCount > 4 then ExitModule = True
End if
end sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Of course SourceForge Message algorithm messes with the code once again. I should put a request in for code tags, because it crushes blank spaces like its no tomorrow.
In the above code the LCD formatting is lost, so instead of using " " spaces I will use "b" spaces!!!
If result >= 100 AND result < 1000 then NegSign:PRINT result
If result >= 10 AND result < 100 then Print "b":NegSign:PRINT result
If result < 10 AND result > 0 then Print "bb":NegSign:PRINT result
If result = 0 Then Print "bbb0"
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ok Kent yopu are right!!.. there is an error in the code... thanks for finding it!!
I went too quickly when supposing "value1 = -1" was the problem and didn't test it properly.
The problem could be solved as you say, but there is already a routine that should do it... is not missing, but didn't work, the solution is just adding a "goto".
if Signed_Add_H.0 on then
set Signed_Add_H.0 off 'toggle sign
goto $+3 '..........................................<<<needed to jump over next "if"
End if
if Signed_Add_H.0 off then set Signed_Add_H.0 on
SUBLW 255 '.........................................<<<program will jump here
ADDLW 1
exit_general_sub:
MOVWF Signed_Add
goto exit_signed_add
__________________________________________________________________________
The BTFSC STATUS,C is for testing when the substracction result is < 0 , in that case program come in the toggle sign routine, if the substracction result is positive then goto exit_general_sub and nothing else is done. (BTFSC = Bit Test F Skip if Cero : if status,c bit is 0 then skip next instruction)
Then here was the problem:
if Signed_Add_H.0 on then set Signed_Add_H.0 off 'toggle sign
if Signed_Add_H.0 off then set Signed_Add_H.0 on
As you can see when the first "if" is true and Signed_Add_H.0 is toggled to off then the second "if" will be true and the bit will be toggled again... :(
what is needed is just jump over second "if" when first "if" is executed
Thanks for reporting the error...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I had a look to your test for signed math... it's a good way for testing a wide range of values in every function.
I noticed that you managed to keep result values in the 0-255 range, this is a cuestion that could be solved...
By now i aded some lines to set the Signed_Add_H.1 bit when the resultant value of the operation (add) is >255; i use this to set result to 255 when result > 255, but this bit can be used as the 9th bit (carry), then 0-511 values are available.
But this will be a problem when using result value as you did:
If result.8 On Then
result = result - 256
Still noy sure about how to mange >255 values, but i need it for PID.
Perhaps using high_byte.0 for "carry" and high_byte.1 for sign....
Still thinking how to implement this in Signed_Mul() function too...
With "b" i understand why this lines... :)
If result >= 100 AND result < 1000 then NegSign:PRINT result
If result >= 10 AND result < 100 then Print "b":NegSign:PRINT result
If result < 10 AND result > 0 then Print "bb":NegSign:PRINT result
If result = 0 Then Print "bbb0"
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Santiago, tried your signed math library, and it looks very good, thanks for sharing it with us! Posted here, as did not want to clutter up your contributors thread.
Maybe a sign thing going on with the signed_add function? Not really sure, it very likely is my output routine, so please take with a grain of salt. Looking at assembly makes my gears grind to a slow crawl. It occurs with value2 equal to result in your equation, with value2's of 0, -1, -2, -3, -4, -5 and the new result is -2, -1, 0, -1, -1, -3 ????
One suggestion is make two sets of equations, one for bytes, one for words. Then one would check the byte.7, and word_H.7 respectively for the sign bit. That gives a range +/-127 and +/-32,767 respectively. Having the +/-127 gives you binary radians, if my recollection is right.
Made up a routine to test your modules using an LCD, along with a button, and a state machine. It can be painful to look at others code, but will post it if you or others request.
Kent, I know nothing about this stuff. Is this the solution to the problem I was struggling with in the PID and A_D threads? The problem of dealing with negative numbers.
I solved the problem but it was pretty ugly! There must be a better way.
If not, what is the correct way of dealing with it? Thanks for all your help. Santiago is a smart fellow.
Everything about these PIC is a struggle for me as I missed out on the hexadecimal stuff by avoiding digital crap, and all the programming stuff by discovering spreadsheets.
These threads are an enormous help to learning this stuff. I have Soooooooo Farrrrrrr to go!
I think Great Cow is the best thing since sliced bread, or maybe the light bulb!!
Regards, Ed.
Hi kent... thanks for the feed-back!!
Ed:
I did the functions for use it in my motors PID, but can be used (carefully) in any simple signed calculations.
I saw the way you solved signs in your filter, in that case i think your's is the best solution; in the case of PID, things can be complex and signed math can help a lot to keep a simple and clear code. I'm just testing it... still starting to work in my PID, that's why i didn't offer you this as a solution until i'm sure about it; but it could be great if you want to try it, just for testing the functions, any feedback will be apreciated.
Kent.. thought english is not my mother-tongue and sometimes is difficult for me understanding somethings...
About the problem you report it could be great when you post a piece of code where the problem happens, including variable declarations to see what is really happening. I'm very interested in finding bugs, then this will be very apreciated.
>One suggestion is make two sets of equations, one for bytes, one for words. Then one >would check the byte.7, and word_H.7 respectively for the sign bit. That gives a range >+/-127 and +/-32,767 respectively. Having the +/-127 gives you binary radians, if my >recollection is right.
Good idea!!.. i have to think in it... but this should require to re-write the complet math routines ( or not... it needs some thoughts...).
what i did in the signed functions is a very simple thing... is just a select case with all the possible combinations of signs, then doing standard add or substract low bytes in the proper order, and set or clear the first bit of the high byte as a sign flag... It stays in the easy side, can solve some basic calculations, but is not very eficient.
Anyway i will try to explain how to use the functions and what you can and cannot do:
One important thing is you cannot do standard math operations with the variables used in these functions... you can have erroneus results as bit0 of high byte is used as sign flag.
The variables are declared as word just to have a high byte to manage sign flag, but they are just byte (0-255) variables for the functions (not for GCBasic).
For example:
dim value1 as word
dim value2 as word
dim result as word
value1=2
value2=8
result=0
result = Signed_Sub(value1, value2) 'result = 2-8 = -6
Now result= 00000001 00000110
this is:
result = 00000110 = 6 'absolute value of the variable
result_H = 000000001 'sign flag is high = this is a negative number
But for GCBasic in terms of "word" value:
result= 00000001 00000110 = 262
if now you do "standard" math operation with this variable, for example:
dim my_variable as word
my_variable = result + 10
you will have:
my_variable = 262 + 10 = 272
But if you do this:
dim my_variable as byte
my_variable = result + 10
then you will have:
my_variable = 6 +10 = 16
When you want to "switch" to standard math you can do (for example):
if result_H = 1 then
result_H = 0
my_variable = 10 - result
End if
if result_H = 0 then my_variable = 10 + result
Then when using the resultant value you need to take in account that you cannot use it directly as a word variable, but you can use the absolute value in the low bit and the sign in the high bit.
For example you can take low bit to set the motor speed and high bit to set direction of spining...
You can take this values using byte variables, for example:
dim output as byte
dim sign as byte
output = result
sign = result_H
And then you can do standard math with "output" variable.
In order to solve this "problems" signed variables should be included in compiler's core... but i think this is not a child's play.
Keep sharing ideas...
>I know nothing about this stuff. Is this the solution to the problem I was struggling >with in the PID and A_D threads? The problem of dealing with negative numbers.
Ed, not sure if the signed numbers is your solution or not. Have yet to have a play with your a-d filter or PID. In this regards, I am the student.
Have been spending efforts on a 2 axis accelerometer used for angle calculation. So, the joy of SIN lookup tables, of late. It's been ages since I've cracked a math book.
Santiago, don't worry about your English, your explanations and code are very clear.
Tracked down the piece of code that gives a hiccup. It has to do with the reuse of the signed_add function by the signed_sub function. First off, the signed_sub function appears fine.
In order for the signed_add function to work properly the following code needs to be looked at. The test condition is when the signed first_val is added to a positive second_val, and when the absolute first_val is less than the positive second_val. For instance try using:
value1 = -1
value2 = 2
result = Signed_Add(value1, value2) ;i.e. result = -1 + 2 = +1
;The returned value of result is -1 not +1 as you would expect.
Signed_Add function
...
...
general_sub:
MOVF second_val,W
SUBWF first_val,W
BTFSC STATUS,C
goto exit_general_sub
if Signed_Add_H.0 on then set Signed_Add_H.0 off 'toggle sign
;the following line of code needs to be commented out for signed_add to work
;but doing so busts the Signed_Sub function
;**************************************
'if Signed_Add_H.0 off then set Signed_Add_H.0 on
;**************************************
SUBLW 255
ADDLW 1
exit_general_sub:
MOVWF Signed_Add
goto exit_signed_add
...
...
Regards,
Kent
Ok Kent.. now i know what is the problem:
The functions just do the maths, but assigning negative values to variables is not possible, then this will not work:
value1 = -1
Take in account that these are just some external functions... the compiler doesn't know anything about signs...
in order to assign negative values to variables, authentic signed variables should be implemented in GCBasic compiler's core... that's still too much for me...
these signed functions are a tool to deal with math operations that could result in negative values, anyway what you try is possible:
to set initial negative values you can do this way:
____________________________________________________________
dim value1 as word
dim value2 as word
dim result as word
value1 = 10
value1_H = 1 'this set negative flag to value1
value2 = 20
result = Signed_Add(value1, value2)
____________________________________________________________
In this case result will be positive and there is no problem when you want to use this value, but you have to take in account that when result is a negative value you have to manage it properly...
For example i did some testing in order to control a motor with pwm, the motor controller is conected to PIC at PWM pin and PORTC.0 pin
I did the calculations with signed functions, and have a word variable called "result":
_________________________________________________________________________
dim result as word
dim output as byte 'BYTE VARIABLE
dim direction as byte
'i do signed calculations
........
.........
........
'Now i have the resultant value in "result" variable ( type: word)
'Now i proceed to pass the values to PWM and turn direction:
output = result 'here only the low byte of result is passed to "output" as output is a byte variable
direction = result_H 'here the high byte of result is passed to "direction" (just 1 or 0)
PORTC.0 = direction.0 'this will determine the turn direction of the motor
if direction.0 on then output = 255 - output 'if reverse turn then invert pwm
HPWM 1, 10, output
_______________________________________________________________________________
Note that the "flag bit" (result_H.0) is used to determine if the motor turns ahead or reverse
When in reverse turn, the "active" side of PWM is the low state (as PORTC.0=1) then inverting the signal is needed.
Note that for using the "result" value and sing i used two BYTE variables not word variables.
I hope this can be understood...
This functions are not the most easy to use but can be a useful tool; anyway any idea to improove it will be apreciated.
Anyway as external fuctions the capablities are very limited and far from real signed variables.
Santiago, sorry didn't mean -1 in the literal sense. My code is handling the negative sign in the value1_H.0 prior to the signed_add function, and then also after the returned value (result) of the signed_add function.
If you can hook up and LCD and use the code below, then it better explains, than my words to you. In the pressing of the state machine button input (pullup on input pin) you can toggle between the different signed math modules.
Perhaps there is an error in my code?, in which case, all apologies extended.
As previously noted in the signed_add function there is a discrepancy, when the absolute of the signed value (say value1) is less than an unsigned value (say value2). When value1 goes from signed 0, 1, 2, 3, 4, 5, 6..., and added to say a value2 of 4, the resultant goes from -4, -3, -2, -1, 0, -1, -2.........When in fact the resultant should be 4, 3, 2, 1, 0, -1, -2......... Please beg your pardon for the visual representation of the resultant numbers, but it seems easiest to describe this way to me.
You do not have to hook up the LCD example. Just try to use your flow of the code, and you will find that the when the absolute value of value1 is less than the unsigned value2 number, the Signed_Add_H.0 needs to be set "off" to represent a positive (unsigned) number. The addition of the following code makes it work.
general_sub:
;additional code to fix bug
absolute_first_val = first_val ;get lower byte of first_val
if absolute_first_val < second_val then
set Signed_Add_H.0 off
MOVF first_val,W
SUBWF second_val,W
goto exit_general_sub
end if
Here is my test code for your modules with an LCD, hope it helps.
'Test of Signed Math Library 2/21/09 by Santiago Glez
'Chip model
#chip 16f877a,20
#include <SignedMath.h>
#define LCD_IO 4
#define LCD_DB4 PORTD.4
#define LCD_DB5 PORTD.5
#define LCD_DB6 PORTD.6
#define LCD_DB7 PORTD.7
#define LCD_RS PORTA.1
#define LCD_RW PORTA.2
#define LCD_Enable PORTA.3
#define Button PortE.2 ;Button pulled up by hardware
dir Button in
#define waitbutton wait 1 10ms
#define lcdwait wait 50 10ms
dim value1 as word
dim value2 as word
dim result as word
value2=4
result=0
counter = 0
Main:
Subtract:
ExitModule = False
counter += 1
For testnum1 = 0 to 127 ;keep operations less than byte
If Button Off then DebounceButton
If ExitModule = True Then goto Exit1
value1 = testnum1 + 256 ;make a negative value
result = Signed_Sub(value1, value2)
locate 0,0:Print "Subtract "
Output ;display on lcd
lcdwait
Next
Exit1:
Multiply:
ExitModule = False
counter += 1
For testnum2 = 0 to 63
If Button Off then DebounceButton
If ExitModule = True Then goto Exit2
value1 = testnum2 + 256 ;make negative value
result = Signed_Mul(value1, value2)
locate 0,0:Print "Multiply "
Output
lcdwait
Next
Exit2:
Addition:
ExitModule = False
counter += 1
For testnum3 = 0 to 127 ;keep operations less than byte
If Button Off then DebounceButton
If ExitModule = True Then goto Exit3
value1 = testnum3 + 256 ;make negative value
result = Signed_Add(value1, value2)
locate 0,0:Print "Addition "
Output ;display on lcd
lcdwait
Next
Exit3:
Division:
ExitModule = False
counter += 1
For testnum4 = 0 to 252 step 4 ;keep operations less than byte
If Button Off then DebounceButton
If ExitModule = True Then goto Exit4
value1 = testnum4 + 256 ;make negative value
result = Signed_Div(value1, value2)
locate 0,0:Print "Division "
Output ;display on lcd
lcdwait
Next
Exit4:
'Now result = 5, result_H = 1 (negative)
'result = Signed_Mul(result, result) 'result = -5 * -5= 25
'Now result = 25, result_H = 0 (positive)
'Locate 1,0
'If result >= 10000 then PRINT "Calc ":Print result
'If result >= 1000 AND result < 10000 then Print "Calc ":PRINT result
'Next
Goto Main
Sub Output
Minus = False
If result.8 On Then
result = result - 256
If result >= 0 Then Minus = True
End if
If result >= 100 AND result < 1000 then NegSign:PRINT result
If result >= 10 AND result < 100 then Print " ":NegSign:PRINT result
If result < 10 AND result > 0 then Print " ":NegSign:PRINT result
If result = 0 Then Print " 0"
end sub
Sub NegSign
If Minus = True Then
Print "-"
Else
Print " "
End if
end sub
Sub DebounceButton
If Button Off then
ButtonCount = 0
Do While Button off
waitButton
ButtonCount += 1
Loop
If ButtonCount > 4 then ExitModule = True
End if
end sub
Of course SourceForge Message algorithm messes with the code once again. I should put a request in for code tags, because it crushes blank spaces like its no tomorrow.
In the above code the LCD formatting is lost, so instead of using " " spaces I will use "b" spaces!!!
If result >= 100 AND result < 1000 then NegSign:PRINT result
If result >= 10 AND result < 100 then Print "b":NegSign:PRINT result
If result < 10 AND result > 0 then Print "bb":NegSign:PRINT result
If result = 0 Then Print "bbb0"
Ok Kent yopu are right!!.. there is an error in the code... thanks for finding it!!
I went too quickly when supposing "value1 = -1" was the problem and didn't test it properly.
The problem could be solved as you say, but there is already a routine that should do it... is not missing, but didn't work, the solution is just adding a "goto".
Here is the solution:
general_sub:
MOVF second_val,W
SUBWF first_val,W
BTFSC STATUS,C
goto exit_general_sub
if Signed_Add_H.0 on then
set Signed_Add_H.0 off 'toggle sign
goto $+3 '..........................................<<<needed to jump over next "if"
End if
if Signed_Add_H.0 off then set Signed_Add_H.0 on
SUBLW 255 '.........................................<<<program will jump here
ADDLW 1
exit_general_sub:
MOVWF Signed_Add
goto exit_signed_add
__________________________________________________________________________
The BTFSC STATUS,C is for testing when the substracction result is < 0 , in that case program come in the toggle sign routine, if the substracction result is positive then goto exit_general_sub and nothing else is done. (BTFSC = Bit Test F Skip if Cero : if status,c bit is 0 then skip next instruction)
Then here was the problem:
if Signed_Add_H.0 on then set Signed_Add_H.0 off 'toggle sign
if Signed_Add_H.0 off then set Signed_Add_H.0 on
As you can see when the first "if" is true and Signed_Add_H.0 is toggled to off then the second "if" will be true and the bit will be toggled again... :(
what is needed is just jump over second "if" when first "if" is executed
Thanks for reporting the error...
Hi Kent...
I had a look to your test for signed math... it's a good way for testing a wide range of values in every function.
I noticed that you managed to keep result values in the 0-255 range, this is a cuestion that could be solved...
By now i aded some lines to set the Signed_Add_H.1 bit when the resultant value of the operation (add) is >255; i use this to set result to 255 when result > 255, but this bit can be used as the 9th bit (carry), then 0-511 values are available.
But this will be a problem when using result value as you did:
If result.8 On Then
result = result - 256
Still noy sure about how to mange >255 values, but i need it for PID.
Perhaps using high_byte.0 for "carry" and high_byte.1 for sign....
Still thinking how to implement this in Signed_Mul() function too...
With "b" i understand why this lines... :)
If result >= 100 AND result < 1000 then NegSign:PRINT result
If result >= 10 AND result < 100 then Print "b":NegSign:PRINT result
If result < 10 AND result > 0 then Print "bb":NegSign:PRINT result
If result = 0 Then Print "bbb0"