Well, here's a crazy interaction. I have found that WORD values will not print properly to the LCD whenever a FOR loop employing a LONG variable appears elsewhere in the program. In fact, the loop works just fine, but its mere presence is enough to screw up the printing of a WORD value. (In the sample below, the garbage "////0" appears instead of 16000. No other data types cause this interaction. For emphasis, a LONG variable FOR loop seems to make WORD printing goofy. Remove the loop and the WORD prints properly.
Any ideas? Here's a demo, stripped to the bare essentials. (The FOR loop does nothing).
#chip 16F88, 8 ;PIC16F88 running at 8 MHz
#config mclr=off ;reset handled internally
#config osc=int ;use internal clock
#define LCD_IO 4 ;4-bit mode
#define LCD_RS PortB.2 ;pin 8 is LCD Register Select
#define LCD_Enable PortB.3 ;pin 9 is LCD Enable
#define LCD_DB4 PortB.4 ;DB4 on pin 10
#define LCD_DB5 PortB.5 ;DB5 on pin 11
#define LCD_DB6 PortB.6 ;DB6 on pin 12
#define LCD_DB7 PortB.7 ;DB7 on pin 13
#define LCD_NO_RW 1 ;ground the RW line on LCD
dim word1 as word
dim long1 as long
dir PortB out
word1 = 16000
print word1 ;* prints garbage
wait 2 S
for long1=100000 to 100010
I had a similar issue in my recent project. Hugh needs to review but he may have a fix ready. Be patient. I could create a hex file for you and send for your testing using the new code base I have. I cannot test as I have no LCD hardware.
Send me your email address. Obfuscated, of course.
I just posted a HEX file using the latest compiler. This may have a fix for your issue.
The file is in this folder. Use the following info to access the file.
I've done a bit of late evening programming, and have uploaded a very experimental build of the compiler to http://gcbasic.sourceforge.net/temp/gcbasic.zip - please try this out and see if it fixes the problem.
The problem is caused by the way that the compiler reuses some calculation variables, namely SysCalcTempA, SysCalcTempB and SysCalcTempX. It has some code that dynamically changes the type of these variables as it compiles the program, but this wasn't working properly. The variables were being set to Long by the condition checking code, but not being changed back to Word by the division code. Because of the way that these temporary variables share memory locations, leaving them as Long was overwriting some other variables in the division routine (SysDivMultA/B/X) with 0.
As a fix, I've created a new set of variables. Instead of SysCalcTempA/B/X, the division, multiplication and comparison routines now have SysByteTempA/B/X, SysWordTempA/B/X, SysIntegerTempA/B/X and SysLongTempA/B/X. This removes the need to change the type of the variable during compilation, which was a pretty dodgy hack anyway. These new variables all share the same memory locations as SysCalcTempA/B/X, so hopefully there won't be any nasty side effects of this change! (They also share locations with each other, SysCalcTempA = SysByteTempA = SysWordTempA = etc, SysCalcTempB = SysByteTempB = etc, etc)
Just tested it and WORD variables now print correctly. However, something has thrown off the printing of LONG variables now (which worked before). So, apparently there is a side effect in the change you made. Just to make sure I'm clear, the following variables print correctly on the LCD: BYTE, INTEGER and WORD. As far as I've seen so far, only LONG prints incorrectly. By the way, it looks like only one byte of the LONG is coming through, as a guess.
Thanks for checking this out, and thanks to Anobium for taking an interest, too.
I need a fix for this also.
if you have simple piece of code that shows the error, can you post? That would really help to ensure we are experiencing the same issues.
Hello Anobium and Hugh,
Okay, here is a little test code. It seems to me that PRINT is only getting the low byte of the LONG variable.
dir PortB out ;all outputs
for word1 = 65000 to 65010 ;word variable
print " " ;blank out previous
print word1 ;print word value
wait 500 mS
wait 2 S
for long1=100000 to 100010 ;long variable
print " " ;blank out previous
print long1 ;print long value
wait 500 mS
wait 2 S
A fix for that second problem is pretty easy, I will include it in an update soon. For now, open up include/lowlevel/lcd.h, and change line 194 from this:
Dim SysCalcTempX As Long
Dim SysCalcTempA As Long
That should fix the problem. I'll keep testing and see if there are any other similar problems!
Thanks so much, Hugh, for nailing this. Everything in my demo works correctly now: all the data types print correctly.
Really, thanks for your excellent service!
I ran the baseline code for 10 hours - no issues. Baseline is same code base with no changes to the use of LONGs.
I will recompile and test a version with the use of LONGs now.
In a new project, I have now seen another side-effect somewhere in the INTEGER routines. The relevant code is:
rh = 256[integer]values(1)+values(2)
copy = values(3) & 0x7F
cels = 256[integer]copy+values(4)
if values(3).7 = on then
cels = -cels
fahr = (18*cels+3205)/10
Obviously, rh, cels and fahr have been declared as type INTEGER here.
Somewhere in these few lines something is acting up. Please note that the program compiles and works properly with the previous official version of GCB. It acts up and gives unreasonable numbers for the unofficial fixed version Hugh described a few messages up.
Thanks for considering it,
I have an issue with IF statements. I have let Hugh know, same root cause is my guess.
Try to work around issue if you can whilst Hugh is trying to sort.
Log in to post a comment.
Sign up for the SourceForge newsletter:
You seem to have CSS turned off.
Please don't fill out this field.