im writing a slightly large program. the problem begins when the size of the program extends past 2k in size. im using proteus to simulate my program and when i run it i get errors like
"PC=0x0055 Attempt to read unimplemented memory location 0x0411 ignored"
and
"PC=0x0055 Attempt to write unimplemented memory location 0x0411 with 0x00 ignored"
my program works fine when the size is around 2kb, i increased the size of the program by setting the same variable, with the same value, about 20 times, which pushed the size of my program to around 2.3k in size, and i get these errors.
i have tried the program with and without "#option lcall" and i get the same results either way.
i dont think this is a problem with my code, because the only thing i change in the code is setting the variable multiple times with the same value.
im using the pic micro 16f1938, which has (i think) around 16k of program space, i would like to be able to use (most) of it, its doubtful ill need more than 4k of space for the program i am writing but im sure to need more than 2k.
any help would be appreciated
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
That looks more like the compiler is placing variables in unimplemented RAM.
In the 16F1938 DAT file there does seem to be an error in the FreeRAM allocation - the last block is listed as 620:34F. It should be 620:64F so try changing that.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I tried that, and theres no change. still getting errors when program goes over 2k.
the specific error im getting right now is
"PC=0x005a. Attempt to write unimplemented memory location 0x0412 with 0xF0 ignored."
and the error repeats every .001 seconds, with the only difference between the errors being the "PC=_____" value, some other values are
PC=0x005c PC=0x005E PC=0x0060
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Good job spotting that error with the RAM bank definitions, I will update the chip data!
I'm not sure what is causing that error. I'd guess that it's something to do with the bank selection code, but I can't say for sure. The PC = 0x55 is a good tip though. If you're using the assembler in GCBASIC, could you copy and paste the relevant section of the listing file? That will probably be called compiled.lst, and you can open it with Notepad. If you're using the assembler in GCBASIC, scroll down to the line that starts with "000055", then copy and paste it and the 10 lines before and after it.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
ive changed my code since my last post, but the results are very similar, still works fine under 2k, but now when over 2k this is the error i get
"PC=0x01D6 Attempt to read unimplemented memory location 0x0495 ignored"
and
"PC=0x01D6 Attempt to write unimplemented memory location 0x0495 with 0x01 ignored"
and that message repeats every .00001s until i end the simulation
here is my the section of my .lst file near the location of 01D6 (though there is no 01D6 in the .lst file anywhere"
That code looks ok at first glance. I thought that a banksel command might be missing, but it looks like there are banksel commands everywhere that there should be. They also appear to be selecting the correct bank. "BANKSEL SSPCON1" is setting the bank select register to 4, which seems to be correct because SSPCON1 is in bank 4.
As a quick test, I put this code into MPLAB SIM and ran it:
LIST p=16F1938, r=DEC
#include <P16F1938.inc>
ORG 0
banksel SSPCON1
bsf SSPCON1, SSPEN
goto $
END
It worked without any problems (selected bank 4, and then set SSPEN) and the hex code generated by MPASM matches that produced by GCBASIC's assembler. I'll have another look tomorrow and double check, but the problem may be in the simulator.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
well if it helps ill post here my full code, it is a possibility that the problem is with the simulator, this is the first chip ive had that had more than 2k program space so ive never had the chance to test this all out. i guess i could put the program on the chip itself and see if it works as expected but its just a lot easier to run it through the simulator instead of reprogramming the chip over and over. anyway, heres the full code.
;Chip Settings
#chip 16F1938,8
#config OSC=INTOSC, CLKOUTEN=OFF
;Defines (Constants)
#define I2C_MODE Master
#define I2C_DATA portc.4
#define I2C_CLOCK portc.3
#define current_address 240
#define slave_address 224
#define serial_register 1
#define ir_in portb.0
#define LCD_IO 4
#define LCD_RS PORTC.0
#define LCD_Enable PORTA.7
#define LCD_DB4 PORTA.3
#define LCD_DB5 PORTA.2
#define LCD_DB6 PORTA.1
#define LCD_DB7 PORTA.0
#define speaker portc.7
#define power_sw portc.5
#define reset_sw portb.1
#define LCD_NO_RW
#define remote_power 200
#define #option lcall
;Variables
Dim counter As byte
Dim temp As byte
Dim mem_temp As byte
Dim hold_counter As byte
Dim timer_temp As byte
Dim remote_temp As word
Dim remote_code As byte
Dim release_counter As byte
Dim zero_fill_temp As word
Dim i2c_register As byte
Dim i2c_buffer As byte
Dim serial_buffer As byte
Dim pc_power_var As bit
Dim timeout_counter As byte
Dim timer_var As byte
Dim menu_depth As byte
Dim red_var As byte
Dim green_var As byte
Dim blue_var As byte
Dim contrast_var As byte
Dim timeout_var As byte
Dim serial_passthru As byte
Dim display_var As string
Dim menu_selection(2)
Dim in_menu As bit
Dim temp_sensor(5)
Dim write_not_read As bit
Dim fan_mode(5)
Dim pulse_duty(5)
Dim temp_offset(5)
;Interrupt Handlers
On Interrupt SSP1Ready Call i2c_interrupt
'display_power_mode 0=timeout 1=always on
Set INTEDG Off
Set NOT_WPUEN Off
Set WPUB0 On
Set WPUB1 On
Set ACKDT On
Set SSPIF Off
SSPADD = current_address
Hi2cMode Slave
i2c_address = slave_address
remote_temp = 255
remote_code = 0
serial_buffer = 0
Set INTEDG Off
Set NOT_WPUEN Off
'ccp5
Dir porta.4 Out
'ccp4
'portb.0 out
'ccp3
Dir PORTC.6 Out
'ccp2
Dir PORTc.1 Out
'ccp1
Dir PORTC.2 Out
display_var = "LCD"
lcd_sub
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Print "LCD"
Do Forever
If release_counter<150 Then
release_counter = release_counter+1
End If
If release_counter=>150 Then
remote_temp = 255
End If
If remote_temp=255 Then
Set power_sw Off
End If
If remote_temp=remote_power Then
Set power_sw On
End If
If serial_buffer=109 Then
menu_init
currently_in_menu:
menu_start
menu_display
menu_fan
serial_buffer = 0
If menu_depth<3 and in_menu=1 Then
Goto currently_in_menu
End If
display_var = "LCD"
lcd_sub
serial_buffer = 0
End If
Loop
Sub mem_write
counter = 0
Do Until counter=>6
counter = counter+1
If counter=1 Then
mem_temp = red_var
End If
If counter=2 Then
mem_temp = green_var
End If
If counter=3 Then
mem_temp = blue_var
End If
If counter=4 Then
mem_temp = contrast_var
End If
If counter=5 Then
mem_temp = timeout_var
End If
If counter=6 Then
mem_temp = serial_passthru
End If
EPWrite counter, mem_temp
Loop
counter = 0
End Sub
Sub zero_fill
Wait 1 ms
zero_fill_temp = 1000
Do Until serial_buffer=>zero_fill_temp
zero_fill_temp = zero_fill_temp/10
If zero_fill_temp=1 Then
zero_fill_temp = 0
End If
HSerPrint "0"
Wait 1 ms
Loop
End Sub
Sub i2c_interrupt
If SSPSTAT.S=1 Then
If D_NOT_A=0 Then
Hi2cReceive i2c_address
End If
End If
Wait Until SSPIF=1
Set SSPIF Off
If i2c_address= current_address Then
Wait Until BF=1
Set SSPIF Off
Hi2cReceive i2c_register
Wait Until SSPSTAT.BF=1 or SSPSTAT.R_NOT_W=1
If BF=1 Then
Hi2cReceive i2c_buffer
Wait Until SSPSTAT.P=1
slave_receive
Exit Sub
End If
If R_NOT_W=1 Then
slave_send
Hi2cSend i2c_buffer
End If
End If
Wait Until SSPSTAT.P=1
End Sub
Sub master_receive
Set SSPEN Off
i2c_address = slave_address
I2CStart
I2CSend i2c_address
I2CSend i2c_register
I2CStop
Wait 1 ms
I2CStart
I2CSend (i2c_address+1)
I2CReceive i2c_buffer, ACK
I2CStop
menu_temp = i2c_buffer
Set SSPEN On
End Sub
Sub master_send
Set SSPEN Off
i2c_address = slave_address
I2CStart
I2CSend i2c_address
I2CSend i2c_register
I2CSend i2c_buffer
I2CStop
Set SSPEN On
End Sub
Sub slave_send
If i2c_register>=2 and i2c_register<=6 Then
'fan mode
End If
If i2c_register>=7 and i2c_register <=11 Then
'pulse duty
End If
If i2c_register>=12 and i2c_register <=16 Then
'temp offset
End If
If i2c_register>=18 and i2c_register <=22 Then
'temp sensors
End If
If i2c_register=23 Then
'error check
End If
If i2c_register=25 Then
'remote button
End If
End Sub
Sub slave_receive
If i2c_register=serial_register Then
'serial
serial_buffer = i2c_buffer
End If
If i2c_register>=2 and i2c_register<=6 Then
'fan mode
End If
If i2c_register>=7 and i2c_register <=11 Then
'pulse duty
End If
If i2c_register>=12 and i2c_register <=16 Then
'temp_offset
End If
If i2c_register=17 Then
'pc power
pc_power = i2c_buffer
End If
If i2c_register>=18 and i2c_register <=22 Then
temp_sensor(i2c_register-13) = i2c
End If
End Sub
Sub set_remote_bits
If counter>=5 and counter<=12 Then
Rotate remote_code Left simple
If Timer1>pulse_middle or PIR1.TMR1IF=1 Then
remote_code.0 = 0
Exit Sub
End If
remote_code.0 = 1
End If
If counter >12 Then
Rotate remote_temp Left simple
If Timer1>pulse_middle or TMR1IF=1 Then
remote_temp.0 = 0
Exit Sub
End If
remote_temp.0 = 1
End If
End Sub
Sub serial_sub
serial_buffer = HSerReceive
End Sub
Sub remote_sub
Set PIR1.TMR1IF Off
StartTimer 1
release_counter = 0
remote_code = 0
remote_temp = 0
counter = 0
Do Until counter>=22
counter = counter+1
Wait Until ir_in=1 or PIR1.TMR1IF=1
StopTimer 1
set_remote_bits
ClearTimer 1
StartTimer 1
counter = counter+1
Wait Until ir_in=0 or PIR1.TMR1IF=1
StopTimer 1
set_remote_bits
ClearTimer 1
StartTimer 1
Loop
StopTimer 1
Set PIR1.TMR1IF Off
If remote_code=144 or remote_code=16 Then
Exit Sub
End If
remote_temp = 999
End Sub
Sub mem_read
counter = 0
Do Until counter=>15
counter = counter+1
EPRead counter, mem_temp
If counter=1 Then
red_var = mem_temp
End If
If counter=2 Then
green_var = mem_temp
End If
If counter=3 Then
blue_var = mem_temp
End If
If counter=4 Then
contrast_var = mem_temp
End If
If counter=5 Then
timeout_var = mem_temp
End If
If counter=6 Then
serial_passthru = mem_temp
End If
Loop
counter = 0
End Sub
Sub power_sub
If pc_power_var=0 Then
If timeout_var<255 Then
timeout_counter = timeout_counter+1
If timeout_counter=>timeout_var Then
timeout_counter = timeout_var
HPWM 1, 40, 0
HPWM 2, 40, 0
HPWM 3, 40, 0
HPWM 5, 40, lcd_contrast
End If
End If
End If
If pc_power_var=1 Then
timeout_counter = 0
HPWM 1, 40, r_value
HPWM 2, 40, g_value
HPWM 3, 40, b_value
HPWM 5, 40, lcd_contrast
End If
End Sub
Sub menu_start
menu_top:
Wait Until serial_buffer>0
CLS
If serial_buffer=102 Then
menu_depth = menu_depth+1
End If
If serial_buffer=100 Then
menu_selection(menu_depth) = menu_selection(menu_depth)+1
End If
If serial_buffer=97 Then
menu_selection(menu_depth) = menu_selection(menu_depth)-1
End If
If menu_selection(1)>8 Then
menu_selection(1) = 1
End If
If menu_selection(1)=0 Then
menu_selection(1) = 8
End If
If menu_selection(1)=7 Then
If menu_depth=1 Then
Print "Save"
End If
If menu_depth=2 Then
Print "Saved"
Wait 1 s
in_menu = 0
End If
End If
If menu_selection(1)=8 Then
If menu_depth=1 Then
Print "Exit"
End If
If menu_depth=2 Then
in_menu = 0
End If
End If
End Sub
Sub startup_sub
End Sub
Sub lcd_sub
CLS
Print display_var
Locate 1, 0
End Sub
Sub menu_init
menu_depth = 1
in_menu = 1
menu_selection(1) = 1
menu_selection(2) = 1
CLS
Print "Menu"
Wait 1 s
End Sub
Sub menu_display
If menu_selection(1)=1 Then
'Display
If menu_depth=1 Then
Print "Display"
End If
If menu_depth=2 Then
If menu_selection(2)=0 Then
menu_selection(2) = 7
End If
If menu_selection(2)>7 Then
menu_selection(2) = 1
End If
If menu_selection(2)=1 Then
display_var = "Backlight Red"
lcd_sub
menu_temp = red_var
menu_up_down
red_var = menu_temp
End If
If menu_selection(2)=2 Then
display_var = "Backlight green"
lcd_sub
menu_temp = green_var
menu_up_down
green_var = menu_temp
End If
If menu_selection(2)=3 Then
display_var = "Backlight Blue"
lcd_sub
menu_temp = blue_var
menu_up_down
blue_var = menu_temp
End If
If menu_selection(2)=4 Then
display_var = "Contrast"
lcd_sub
menu_temp = contrast_var
menu_up_down
contrast_var = menu_temp
End If
If menu_selection(2)=5 Then
display_var = "Backlight Timeout"
lcd_sub
menu_temp = timeout_var
menu_up_down
timeout_var = menu_temp
End If
If menu_selection(2)=6 Then
display_var = "Serial Passthru"
lcd_sub
menu_temp = serial_passthru
If serial_buffer=119 or serial_buffer=115 Then
If menu_temp=0 Then
menu_temp = 1
Goto skip_passthru_0
End If
serial_passthru = 0
skip_passthru_0:
End If
serial_passthru = menu_temp
End If
If menu_selection(2)=7 Then
Print "Exit"
Goto skip_print_display
End If
Print menu_temp
skip_print_display:
End If
End If
End Sub
Sub menu_fan
If menu_selection(1)=>2 and menu_selection(1)<=6 Then
If menu_depth=1 Then
'fan1, fan2, fan3, fan4, fan5
Print "Fan"
Print menu_selection(1)-1
End If
If menu_depth=2 Then
If menu_selection(2)=0 Then
menu_selection(2) = 4
End If
If menu_selection(2)>4 Then
menu_selection(2) = 1
End If
If menu_selection(2)=1 Then
'mode
display_var = "Mode"
lcd_sub
i2c_register = menu_selection(1)
master_receive
menu_up_down
If menu_temp>4 Then
menu_temp = 1
End If
If menu_temp=0 Then
menu_temp = 4
End If
If menu_temp=1 Then
Print "Off"
End If
If menu_temp=2 Then
Print "On"
End If
If menu_temp=3 Then
Print "Temp"
End If
If menu_temp=4 Then
Print "Manual"
End If
i2c_buffer = menu_temp
End If
If menu_selection(2)=2 Then
'duty
display_var = "Duty"
lcd_sub
i2c_register = menu_selection(1)+5
master_receive
menu_up_down
Print menu_temp
i2c_buffer = menu_temp
End If
If menu_selection(2)=3 Then
'offset
display_var = "Temp Offset"
lcd_sub
i2c_register = menu_selection(1)+10
master_receive
menu_up_down
Print menu_temp
i2c_buffer = menu_temp
End If
If menu_selection(2)=4 Then
Print "Exit"
Goto skip_print_fan
End If
master_send
skip_print_fan:
End If
End If
End Sub
Sub menu_up_down
If serial_buffer=119 Then
menu_temp = menu_temp+1
End If
If serial_buffer=115 Then
menu_temp = menu_temp-1
End If
End Sub
Sub menu_stop
End Sub
the section of code repeating the lcd command are just to get it past the 2k size, without those repeated commands in the code i get no errors, but i will test the code on the hardware itself tonight and see if it works properly. ill post the results of my hardware tests here
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hugh, in case youre interested i have modified the LCD.C file to add support for lcd 8-bit mode, with all 8 pins customizable (in other words you dont have to use the bits of a port, you can use any pin for the lcds data pins).
you just have to put #define LCD_CUSTOM in the basic code, and for each lcd data pin like this
I modified this code because i couldnt use my entire portA (one of the pins was a HPWM which i wanted to use), and i didnt want to use portB (has the weak pull-ups so i wanna save that for inputs) and portC has the hardware I2C which i wanna use to talk to another pic micro.
so my only options were to use 4-bit mode, or to remap the pins for 8-bit mode
im not sure if anyone else will need to remap for 8-bit mode but in case anyone does here is the modified code. i also modified the HPWM code to add support for my additional PWM channels (my chip has 5 total but GCBASIC only had support for up to 3) if youd like that code too just ask. they are very simple modifications. just wanted to give something back to the community
' Liquid Crystal Display routines for Great Cow BASIC'Copyright(C)2006-2009HughConsidine,StefanoBonomi' This library is free software; you can redistribute it and/or'modifyitunderthetermsoftheGNULesserGeneralPublic' License as published by the Free Software Foundation; either'version2.1oftheLicense,or(atyouroption)anylaterversion.' This library is distributed in the hope that it will be useful,'butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU'LesserGeneralPublicLicenseformoredetails.' You should have received a copy of the GNU Lesser General Public'Licensealongwiththislibrary;ifnot,writetotheFreeSoftware' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA'********************************************************************************'IMPORTANT:'THISFILEISESSENTIALFORSOMEOFTHECOMMANDSINGCBASIC.DONOTALTERTHISFILE'UNLESS YOU KNOW WHAT YOU ARE DOING. CHANGING THIS FILE COULD RENDER SOME GCBASIC'COMMANDSUNUSABLE!'********************************************************************************'Credits:' 4 and 8 bit routines Hugh Considine'2bitroutinesStefanoBonomi' Testing Stefano Adami#startup InitLCD'I/OPorts#defineLCD_IO4'Number of pins used for LCD data bus (2, 4 or 8)'SubusedtowritetoLCD.CanbealteredtoallowcustomLCDinterfaces.#defineLCDWriteByteLCDNormalWriteByte#defineLCDReadByteLCDNormalReadByte#defineLCD_DBSysLCDTemp.0'Data bit. Used in 2-bit mode#define LCD_CB SysLCDTemp.0 'Clockbit.Usedin2-bitmode#defineLCD_DATA_PORTSysLCDTemp'Port to connect to LCD data bus. Used in 8-bit mode#define LCD_DB0 SysLCDTemp.0 'OutputbittointerfacewithLCDdatabus.UsedinCustommode#defineLCD_DB1SysLCDTemp.0'Output bit to interface with LCD data bus. Used in Custom mode#define LCD_DB2 SysLCDTemp.0 'OutputbittointerfacewithLCDdatabus.UsedinCustommode#defineLCD_DB3SysLCDTemp.0'Output bit to interface with LCD data bus. Used in Custom mode#define LCD_DB4 SysLCDTemp.0 'OutputbittointerfacewithLCDdatabus.Usedin4-bitmode#defineLCD_DB5SysLCDTemp.0'Output bit to interface with LCD data bus. Used in 4-bit mode#define LCD_DB6 SysLCDTemp.0 'OutputbittointerfacewithLCDdatabus.Usedin4-bitmode#defineLCD_DB7SysLCDTemp.0'Output bit to interface with LCD data bus. Used in 4-bit mode#define LCD_RS SysLCDTemp.1 'OutputbittocontrolLCDRegisterSelect.Usedasvariableby2-bitmode,andasapinin4and8bitmode.DONOTCHANGEFOR2-BITMODE.#defineLCD_RWSysLCDTemp.0'Output bit to select read/write#define LCD_Enable SysLCDTemp.0 'Outputbittoenable/disableLCD#defineLCD_RSTempSysLCDTemp.2'Misc Settings#define LCD_Write_Delay 8 10us#define FLASH 2'#defineLCD_NO_RW'Lines for bar graph#define LCD_BAR_EMPTY b'00010001'#define LCD_BAR_FULL 255Sub PUT (In LCDPutLine, In LCDPutColumn, In LCDChar) LOCATE LCDPutLine, LCDPutColumn Set LCD_RS on LCDWriteByte(LCDChar)End Sub'GETnotavailablein2-bitmodeFunctionGET(LCDPutLine,LCDPutColumn)LocateLCDPutLine,LCDPutColumnSetLCD_RSonGET=LCDReadByteEndFunction'LCDColumn is 0 to screen width-1, LCDLine is 0 to screen height-1Sub LOCATE (In LCDLine, In LCDColumn) Set LCD_RS Off If LCDLine > 1 Then LCDLine = LCDLine - 2 LCDColumn = LCDColumn + 20 End If LCDWriteByte(0x80 or 0x40 * LCDLine + LCDColumn) Wait 5 10usEnd SubSub CLS SET LCD_RS OFF 'ClearscreenLCDWriteByte(b'00000001')Wait2ms'Move to start of visible DDRAM LCDWriteByte(0x80) Wait 10 10usEnd Sub'Compatibilitywitholderprograms#defineLCDIntPrint#defineLCDWordPrint'String outputsub Print (PrintData As String) 'PrintLen=LEN(PrintData$)PrintLen=PrintData(0)IfPrintLen=0ThenExitSubSetLCD_RSOn'Write Data For SysPrintTemp = 1 To PrintLen LCDWriteByte PrintData(SysPrintTemp) NextEnd SubSub Print (In LCDValue) LCDValueTemp = 0 Set LCD_RS On IF LCDValue >= 100 Then LCDValueTemp = LCDValue / 100 LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) End If If LCDValueTemp > 0 Or LCDValue >= 10 Then LCDValueTemp = LCDValue / 10 LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) End If LCDWriteByte (LCDValue + 48)End SubSub Print (In LCDValue As Word) Dim SysCalcTempX As Word Set LCD_RS On LCDValueTemp = 0 If LCDValue >= 10000 then LCDValueTemp = LCDValue / 10000 [word] LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) Goto LCDPrintWord1000 End If If LCDValue >= 1000 then LCDPrintWord1000: LCDValueTemp = LCDValue / 1000 [word] LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) Goto LCDPrintWord100 End If If LCDValue >= 100 then LCDPrintWord100: LCDValueTemp = LCDValue / 100 [word] LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) Goto LCDPrintWord10 End If If LCDValue >= 10 then LCDPrintWord10: LCDValueTemp = LCDValue / 10 [word] LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) End If LCDWriteByte (LCDValue + 48)End SubSub Print (In LCDValueInt As Integer) Dim LCDValue As Word 'Ifsignbitison,print-signandthennegateIfLCDValueInt.15=OnThenLCDWriteChar("-")LCDValue=-LCDValueInt'Sign bit off, so just copy value Else LCDValue = LCDValueInt End If 'UsePrint(word)todisplayvaluePrintLCDValueEndSubsubLCDHex(InLCDValue)LCDValueTemp=0SetLCD_RSOnIFLCDValue>=0x10thenLCDValueTemp=LCDValue/0x10LCDValue=SysCalcTempXLCDHexValueTemp=LCDValueTempifLCDHexValueTemp>9thenLCDHexValueTemp=LCDHexValueTemp+7LCDWriteByte(LCDHexValueTemp+48)endifLCDHexValueTemp=LCDValueifLCDHexValueTemp>9thenLCDHexValueTemp=LCDHexValueTemp+7LCDWriteByte(LCDHexValueTemp+48)endsubsubLCDWriteChar(InLCDChar)setLCD_RSonLCDWriteByte(LCDChar)endsubfunctionLCDReady#IFDEFLCD_NO_RWWait10msLCDReady=TRUEexitfunction#ENDIF#IFNDEFLCD_NO_RW#IFNDEFLCD_CUSTOM#IFDEFLCD_IO2LCDReady=TRUEexitfunction#ENDIF#IFDEFLCD_IO4,8LCDReady=FALSELCD_RSTemp=LCD_RSSETLCD_RWONSETLCD_RSOFFWait510usSETLCD_EnableONwait510us#IFDEFLCD_IO4dirLCD_DB7INifLCD_DB7OFFTHENLCDReady=TRUE#ENDIF#IFDEFLCD_IO8dirLCD_DATA_PORTInifLCD_DATA_PORT.7OFFTHENLCDReady=TRUE#ENDIFSETLCD_EnableOFFwait2510usLCD_RS=LCD_RSTemp#ENDIF#ENDIF#IFDEFLCD_CUSTOMLCDReady=FALSELCD_RSTemp=LCD_RSSETLCD_RWONSETLCD_RSOFFWait510usSETLCD_EnableONwait510usDIRLCD_DB0OUTDIRLCD_DB1OUTDIRLCD_DB2OUTDIRLCD_DB3OUTDIRLCD_DB4OUTDIRLCD_DB5OUTDIRLCD_DB6OUTDIRLCD_DB7OUTifLCD_DB7OFFTHENLCDReady=TRUESETLCD_EnableOFFwait2510usLCD_RS=LCD_RSTemp#ENDIF#ENDIFendfunctionsubLCDNormalWriteByte(InLCDByte)#IFNDEFLCD_NO_RW#IFNDEFLCD_CUSTOM#IFDEFLCD_IO4,8waituntilLCDReadysetLCD_RWOFF'Write mode #ENDIF #ENDIF #IFDEF LCD_CUSTOM wait until LCDReady set LCD_RW OFF 'Writemode#ENDIF#ENDIF#IFNDEFLCD_CUSTOM#IFDEFLCD_IO2LCD2_NIBBLEOUTSwap4(LCDByte)'Swap byte; Most significant NIBBLE sent first LCD2_NIBBLEOUT LCDByte 'LessSignificantNIBBLEoutput#ENDIF#IFDEFLCD_IO4'Set pins to output DIR LCD_DB4 OUT DIR LCD_DB5 OUT DIR LCD_DB6 OUT DIR LCD_DB7 OUT 'WriteuppernibbletooutputpinssetLCD_DB4OFFsetLCD_DB5OFFsetLCD_DB6OFFsetLCD_DB7OFFifLCDByte.7ONTHENSETLCD_DB7ONifLCDByte.6ONTHENSETLCD_DB6ONifLCDByte.5ONTHENSETLCD_DB5ONifLCDByte.4ONTHENSETLCD_DB4ON'Pulse enable pin Wait 5 10us PULSEOUT LCD_Enable, 5 10us Wait 5 10us 'WritelowernibbletooutputpinssetLCD_DB4OFFsetLCD_DB5OFFsetLCD_DB6OFFsetLCD_DB7OFFifLCDByte.3ONTHENSETLCD_DB7ONifLCDByte.2ONTHENSETLCD_DB6ONifLCDByte.1ONTHENSETLCD_DB5ONifLCDByte.0ONTHENSETLCD_DB4ON'Pulse enable pin Wait 5 10us PULSEOUT LCD_Enable, 5 10us Wait 5 10us 'SetdatapinslowagainSETLCD_DB7OFFSETLCD_DB6OFFSETLCD_DB5OFFSETLCD_DB4OFF#ENDIF#IFDEFLCD_IO8'Set data port to output, and write a value to it DIR LCD_DATA_PORT out LCD_DATA_PORT = LCDByte 'PulseenablepinWait510usPULSEOUTLCD_Enable,510usWait510us'Clear port again, in case it is shared with something else LCD_DATA_PORT = 0 #ENDIF #ENDIF #IFDEF LCD_CUSTOM DIR LCD_DB0 OUT DIR LCD_DB1 OUT DIR LCD_DB2 OUT DIR LCD_DB3 OUT DIR LCD_DB4 OUT DIR LCD_DB5 OUT DIR LCD_DB6 OUT DIR LCD_DB7 OUT set LCD_DB0 OFF set LCD_DB1 OFF set LCD_DB2 OFF set LCD_DB3 OFF set LCD_DB4 OFF set LCD_DB5 OFF set LCD_DB6 OFF set LCD_DB7 OFF if LCDByte.7 ON THEN SET LCD_DB7 ON if LCDByte.6 ON THEN SET LCD_DB6 ON if LCDByte.5 ON THEN SET LCD_DB5 ON if LCDByte.4 ON THEN SET LCD_DB4 ON if LCDByte.3 ON THEN SET LCD_DB3 ON if LCDByte.2 ON THEN SET LCD_DB2 ON if LCDByte.1 ON THEN SET LCD_DB1 ON if LCDByte.0 ON THEN SET LCD_DB0 ON 'PulseenablepinWait510usPULSEOUTLCD_Enable,510usWait510ussetLCD_DB0OFFsetLCD_DB1OFFsetLCD_DB2OFFsetLCD_DB3OFFsetLCD_DB4OFFsetLCD_DB5OFFsetLCD_DB6OFFsetLCD_DB7OFF#ENDIFendsubSUBLCD2_NIBBLEOUT(InLCD2BYTE)'Set Data and Clock bits off SET LCD_DB OFF SET LCD_CB OFF 'ClearShiftRegisterWithsix0spriortoloadingFORLCDTemp=1TO6SETLCD_CBON' STROBE SET LCD_CB OFF '======NEXTSETLCD_DBON' First bit out to Shift register, always 1 for E gate SET LCD_CB ON 'STROBESETLCD_CBOFF' ====== IF LCD_RS OFF THEN SET LCD_DB OFF 'SecondbitoutequaltoR/SSETLCD_CBON' STROBE SET LCD_CB OFF '======'4 bits Data out to Shift register, starting from Nibble most significant bit FOR LCDTemp = 1 to 4 SET LCD_DB OFF IF LCD2Byte.3 ON THEN SET LCD_DB ON SET LCD_CB ON SET LCD_CB OFF ROTATE LCD2Byte LEFT NEXTSET LCD_DB ON 'LastpulseforNibbleoutput.NotforShiftregisterWAIT1MS' Put E pin on LCD to one through an AND operation SET LCD_DB OFF 'withthefirstbitoutputted(E)ENDSUBfunctionLCDNormalReadByte#IFDEFLCD_NO_RWLCDReadByte=0ExitFunction#ENDIF#IFNDEFLCD_NO_RWsetLCD_RWON'Read mode LCDReadByte = 0 #IFNDEF LCD_CUSTOM #IFDEF LCD_IO 4 'SetpinstoinputDIRLCD_DB4INDIRLCD_DB5INDIRLCD_DB6INDIRLCD_DB7IN'Read upper nibble from input pins SET LCD_Enable ON Wait LCD_Write_Delay if LCD_DB7 ON then SET LCDReadByte.7 ON if LCD_DB6 ON THEN SET LCDReadByte.6 ON if LCD_DB5 ON then SET LCDReadByte.5 ON if LCD_DB4 ON THEN SET LCDReadByte.4 ON SET LCD_Enable OFF Wait 2 10us 'ReadlowernibblefrominputpinsSETLCD_EnableONWaitLCD_Write_DelayifLCD_DB7ONthenSETLCDReadByte.3ONifLCD_DB6ONTHENSETLCDReadByte.2ONifLCD_DB5ONthenSETLCDReadByte.1ONifLCD_DB4ONTHENSETLCDReadByte.0ONSETLCD_EnableOFFWait210us#ENDIF#IFDEFLCD_IO8DIRLCD_DATA_PORT255SETLCD_EnableONWaitLCD_Write_DelayLCDReadByte=LCD_DATA_PORTSETLCD_EnableOFFWait210us#ENDIF#ENDIFIFDEFLCD_CUSTOM'Set pins to input DIR LCD_DB1 IN DIR LCD_DB2 IN DIR LCD_DB2 IN DIR LCD_DB3 IN DIR LCD_DB4 IN DIR LCD_DB5 IN DIR LCD_DB6 IN DIR LCD_DB7 IN SET LCD_Enable ON Wait LCD_Write_Delay if LCD_DB7 ON then SET LCDReadByte.7 ON if LCD_DB6 ON THEN SET LCDReadByte.6 ON if LCD_DB5 ON then SET LCDReadByte.5 ON if LCD_DB4 ON THEN SET LCDReadByte.4 ON if LCD_DB3 ON then SET LCDReadByte.3 ON if LCD_DB2 ON THEN SET LCDReadByte.2 ON if LCD_DB1 ON then SET LCDReadByte.1 ON if LCD_DB0 ON THEN SET LCDReadByte.0 ON SET LCD_Enable OFF Wait 2 10us #ENDIF #ENDIFend functionsub InitLCD #IFNDEF LCD_CUSTOM #IFDEF LCD_IO 2 SET LCD_DB OFF SET LCD_CB OFF DIR LCD_DB OUT DIR LCD_CB OUT WAIT 35 MS SET LCD_RS OFF LCD2_NIBBLEOUT 0X03 Wait 5 ms LCD2_NIBBLEOUT 0X03 WAIT 1 MS LCD2_NIBBLEOUT 0X03 WAIT 1 MS LCD2_NIBBLEOUT 0X02 WAIT 1 MS LCDWriteByte 0x28 WAIT 1 MS LCDWriteByte 0x08 WAIT 1 MS LCDWriteByte 0x01 WAIT 5 MS LCDWriteByte 0x06 WAIT 1 MS LCDWriteByte 0x0C WAIT 1 MS #ENDIF #IFDEF LCD_IO 4,8 DIR LCD_RS OUT #IFNDEF LCD_NO_RW DIR LCD_RW OUT #ENDIF DIR LCD_Enable OUT wait 10 ms Wait until LCDReady 'SetdatabuswidthSETLCD_RSOFF#ENDIF#IFDEFLCD_IO8LCDWriteByte(b'00111000')#ENDIF#IFDEFLCD_IO4DIRLCD_DB4OUTDIRLCD_DB5OUTDIRLCD_DB6OUTDIRLCD_DB7OUTsetLCD_RSOFF#IFNDEFLCD_NO_RWsetLCD_RWOFF#ENDIFsetLCD_DB4OFFsetLCD_DB5ONsetLCD_DB6OFFsetLCD_DB7OFFWait510usPulseOutLCD_Enable,510usWait5msLCDWriteByte(b'00101000')wait2510us#ENDIF#IFDEFLCD_IO4,8'Set Cursor movement SET LCD_RS OFF LCDWriteByte(b'00000110') wait 5 10us 'TurnoffcursorLCDWriteByte(b'00001100')wait510us'Clear screen CLS #ENDIF #ENDIF #IFDEF LCD_CUSTOM DIR LCD_RS OUT #IFNDEF LCD_NO_RW DIR LCD_RW OUT #ENDIF DIR LCD_Enable OUT wait 10 ms Wait until LCDReady 'SetdatabuswidthSETLCD_RSOFFLCDWriteByte(b'00111000')#ENDIFendsubsubLCDCursor(InLCDCRSR)'Can be ON, FLASH or OFF Set LCD_RW OFF LCDTemp = 12 '0or12IfLCDCRSR=ONThenLCDTemp=14'2 or 12 If LCDCRSR = FLASH Then LCDTemp = 15 '3or12'If LCDCRSR = OFF Then LCDTemp = 0 or 12 LCDWriteByte(LCDTemp) '(LCDTempor12)Wait510usendsub'Create a custom character in CGRAMsub LCDCreateChar (In LCDCharLoc, LCDCharData()) #IFNDEF LCD_CUSTOM 'Storeoldlocation#IFDEFLCD_IO4,8SetLCD_RSOffLCDLoc=LCDReadByteSetLCDLoc.7On#ENDIF'Select location Set LCD_RS Off LCDWriteByte (64 + LCDCharLoc * 8) wait 5 10us 'WritecharSetLCD_RSOnForLCDTemp=1to8LCDWriteByteLCDCharData(LCDTemp)wait510usNext'Restore location #IFDEF LCD_IO 2 set LCD_RS off LCDWriteByte(0x80) wait 5 10us #ENDIF #IFDEF LCD_IO 4,8 Set LCD_RS Off LCDWriteByte (LCDLoc) wait 5 10us #ENDIF #ENDIF #IFDEF LCD_CUSTOM 'StoreoldlocationSetLCD_RSOffLCDLoc=LCDReadByteSetLCDLoc.7On'Select location Set LCD_RS Off LCDWriteByte (64 + LCDCharLoc * 8) wait 5 10us 'WritecharSetLCD_RSOnForLCDTemp=1to8LCDWriteByteLCDCharData(LCDTemp)wait510usNext'Restore location Set LCD_RS Off LCDWriteByte (LCDLoc) wait 5 10us #ENDIFend sub'CreateagraphcharacterinCGRAMSubLCDCreateGraph(InLCDCharLoc,InLCDValue)#IFNDEFLCD_CUSTOM'Store old location #IFDEF LCD_IO 4,8 Set LCD_RS Off LCDLoc = LCDReadByte Set LCDLoc.7 On #ENDIF 'SelectlocationSetLCD_RSOffLCDWriteByte(64+LCDCharLoc*8)wait510us'Write char for graph Set LCD_RS On For LCDTemp = 8 to 1 If LCDTemp > LCDValue Then LCDWriteByte LCD_BAR_EMPTY Else LCDWriteByte LCD_BAR_FULL End If wait 5 10us Next 'Restorelocation#IFDEFLCD_IO2setLCD_RSoffLCDWriteByte(0x80)wait510us#ENDIF#IFDEFLCD_IO4,8SetLCD_RSOffLCDWriteByte(LCDLoc)wait510us#ENDIF#ENDIF#IFDEFLCD_CUSTOM'Store old location Set LCD_RS Off LCDLoc = LCDReadByte Set LCDLoc.7 On 'SelectlocationSetLCD_RSOffLCDWriteByte(64+LCDCharLoc*8)wait510us'Write char for graph Set LCD_RS On For LCDTemp = 8 to 1 If LCDTemp > LCDValue Then LCDWriteByte LCD_BAR_EMPTY Else LCDWriteByte LCD_BAR_FULL End If wait 5 10us Next 'RestorelocationSetLCD_RSOffLCDWriteByte(LCDLoc)wait510us#ENDIFEndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
i was missing some code in the init section to set the cursor movement, here is the corrected code which i have tested to work in a simulator
' Liquid Crystal Display routines for Great Cow BASIC'Copyright(C)2006-2009HughConsidine,StefanoBonomi' This library is free software; you can redistribute it and/or'modifyitunderthetermsoftheGNULesserGeneralPublic' License as published by the Free Software Foundation; either'version2.1oftheLicense,or(atyouroption)anylaterversion.' This library is distributed in the hope that it will be useful,'butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU'LesserGeneralPublicLicenseformoredetails.' You should have received a copy of the GNU Lesser General Public'Licensealongwiththislibrary;ifnot,writetotheFreeSoftware' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA'********************************************************************************'IMPORTANT:'THISFILEISESSENTIALFORSOMEOFTHECOMMANDSINGCBASIC.DONOTALTERTHISFILE'UNLESS YOU KNOW WHAT YOU ARE DOING. CHANGING THIS FILE COULD RENDER SOME GCBASIC'COMMANDSUNUSABLE!'********************************************************************************'Credits:' 4 and 8 bit routines Hugh Considine'2bitroutinesStefanoBonomi' Testing Stefano Adami#startup InitLCD'I/OPorts#defineLCD_IO4'Number of pins used for LCD data bus (2, 4 or 8)'SubusedtowritetoLCD.CanbealteredtoallowcustomLCDinterfaces.#defineLCDWriteByteLCDNormalWriteByte#defineLCDReadByteLCDNormalReadByte#defineLCD_DBSysLCDTemp.0'Data bit. Used in 2-bit mode#define LCD_CB SysLCDTemp.0 'Clockbit.Usedin2-bitmode#defineLCD_DATA_PORTSysLCDTemp'Port to connect to LCD data bus. Used in 8-bit mode#define LCD_DB0 SysLCDTemp.0 'OutputbittointerfacewithLCDdatabus.UsedinCustommode#defineLCD_DB1SysLCDTemp.0'Output bit to interface with LCD data bus. Used in Custom mode#define LCD_DB2 SysLCDTemp.0 'OutputbittointerfacewithLCDdatabus.UsedinCustommode#defineLCD_DB3SysLCDTemp.0'Output bit to interface with LCD data bus. Used in Custom mode#define LCD_DB4 SysLCDTemp.0 'OutputbittointerfacewithLCDdatabus.Usedin4-bitmode#defineLCD_DB5SysLCDTemp.0'Output bit to interface with LCD data bus. Used in 4-bit mode#define LCD_DB6 SysLCDTemp.0 'OutputbittointerfacewithLCDdatabus.Usedin4-bitmode#defineLCD_DB7SysLCDTemp.0'Output bit to interface with LCD data bus. Used in 4-bit mode#define LCD_RS SysLCDTemp.1 'OutputbittocontrolLCDRegisterSelect.Usedasvariableby2-bitmode,andasapinin4and8bitmode.DONOTCHANGEFOR2-BITMODE.#defineLCD_RWSysLCDTemp.0'Output bit to select read/write#define LCD_Enable SysLCDTemp.0 'Outputbittoenable/disableLCD#defineLCD_RSTempSysLCDTemp.2'Misc Settings#define LCD_Write_Delay 8 10us#define FLASH 2'#defineLCD_NO_RW'Lines for bar graph#define LCD_BAR_EMPTY b'00010001'#define LCD_BAR_FULL 255Sub PUT (In LCDPutLine, In LCDPutColumn, In LCDChar) LOCATE LCDPutLine, LCDPutColumn Set LCD_RS on LCDWriteByte(LCDChar)End Sub'GETnotavailablein2-bitmodeFunctionGET(LCDPutLine,LCDPutColumn)LocateLCDPutLine,LCDPutColumnSetLCD_RSonGET=LCDReadByteEndFunction'LCDColumn is 0 to screen width-1, LCDLine is 0 to screen height-1Sub LOCATE (In LCDLine, In LCDColumn) Set LCD_RS Off If LCDLine > 1 Then LCDLine = LCDLine - 2 LCDColumn = LCDColumn + 20 End If LCDWriteByte(0x80 or 0x40 * LCDLine + LCDColumn) Wait 5 10usEnd SubSub CLS SET LCD_RS OFF 'ClearscreenLCDWriteByte(b'00000001')Wait2ms'Move to start of visible DDRAM LCDWriteByte(0x80) Wait 10 10usEnd Sub'Compatibilitywitholderprograms#defineLCDIntPrint#defineLCDWordPrint'String outputsub Print (PrintData As String) 'PrintLen=LEN(PrintData$)PrintLen=PrintData(0)IfPrintLen=0ThenExitSubSetLCD_RSOn'Write Data For SysPrintTemp = 1 To PrintLen LCDWriteByte PrintData(SysPrintTemp) NextEnd SubSub Print (In LCDValue) LCDValueTemp = 0 Set LCD_RS On IF LCDValue >= 100 Then LCDValueTemp = LCDValue / 100 LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) End If If LCDValueTemp > 0 Or LCDValue >= 10 Then LCDValueTemp = LCDValue / 10 LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) End If LCDWriteByte (LCDValue + 48)End SubSub Print (In LCDValue As Word) Dim SysCalcTempX As Word Set LCD_RS On LCDValueTemp = 0 If LCDValue >= 10000 then LCDValueTemp = LCDValue / 10000 [word] LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) Goto LCDPrintWord1000 End If If LCDValue >= 1000 then LCDPrintWord1000: LCDValueTemp = LCDValue / 1000 [word] LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) Goto LCDPrintWord100 End If If LCDValue >= 100 then LCDPrintWord100: LCDValueTemp = LCDValue / 100 [word] LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) Goto LCDPrintWord10 End If If LCDValue >= 10 then LCDPrintWord10: LCDValueTemp = LCDValue / 10 [word] LCDValue = SysCalcTempX LCDWriteByte(LCDValueTemp + 48) End If LCDWriteByte (LCDValue + 48)End SubSub Print (In LCDValueInt As Integer) Dim LCDValue As Word 'Ifsignbitison,print-signandthennegateIfLCDValueInt.15=OnThenLCDWriteChar("-")LCDValue=-LCDValueInt'Sign bit off, so just copy value Else LCDValue = LCDValueInt End If 'UsePrint(word)todisplayvaluePrintLCDValueEndSubsubLCDHex(InLCDValue)LCDValueTemp=0SetLCD_RSOnIFLCDValue>=0x10thenLCDValueTemp=LCDValue/0x10LCDValue=SysCalcTempXLCDHexValueTemp=LCDValueTempifLCDHexValueTemp>9thenLCDHexValueTemp=LCDHexValueTemp+7LCDWriteByte(LCDHexValueTemp+48)endifLCDHexValueTemp=LCDValueifLCDHexValueTemp>9thenLCDHexValueTemp=LCDHexValueTemp+7LCDWriteByte(LCDHexValueTemp+48)endsubsubLCDWriteChar(InLCDChar)setLCD_RSonLCDWriteByte(LCDChar)endsubfunctionLCDReady#IFDEFLCD_NO_RWWait10msLCDReady=TRUEexitfunction#ENDIF#IFNDEFLCD_NO_RW#IFNDEFLCD_CUSTOM#IFDEFLCD_IO2LCDReady=TRUEexitfunction#ENDIF#IFDEFLCD_IO4,8LCDReady=FALSELCD_RSTemp=LCD_RSSETLCD_RWONSETLCD_RSOFFWait510usSETLCD_EnableONwait510us#IFDEFLCD_IO4dirLCD_DB7INifLCD_DB7OFFTHENLCDReady=TRUE#ENDIF#IFDEFLCD_IO8dirLCD_DATA_PORTInifLCD_DATA_PORT.7OFFTHENLCDReady=TRUE#ENDIFSETLCD_EnableOFFwait2510usLCD_RS=LCD_RSTemp#ENDIF#ENDIF#IFDEFLCD_CUSTOMLCDReady=FALSELCD_RSTemp=LCD_RSSETLCD_RWONSETLCD_RSOFFWait510usSETLCD_EnableONwait510usDIRLCD_DB0OUTDIRLCD_DB1OUTDIRLCD_DB2OUTDIRLCD_DB3OUTDIRLCD_DB4OUTDIRLCD_DB5OUTDIRLCD_DB6OUTDIRLCD_DB7OUTifLCD_DB7OFFTHENLCDReady=TRUESETLCD_EnableOFFwait2510usLCD_RS=LCD_RSTemp#ENDIF#ENDIFendfunctionsubLCDNormalWriteByte(InLCDByte)#IFNDEFLCD_NO_RW#IFNDEFLCD_CUSTOM#IFDEFLCD_IO4,8waituntilLCDReadysetLCD_RWOFF'Write mode #ENDIF #ENDIF #IFDEF LCD_CUSTOM wait until LCDReady set LCD_RW OFF 'Writemode#ENDIF#ENDIF#IFNDEFLCD_CUSTOM#IFDEFLCD_IO2LCD2_NIBBLEOUTSwap4(LCDByte)'Swap byte; Most significant NIBBLE sent first LCD2_NIBBLEOUT LCDByte 'LessSignificantNIBBLEoutput#ENDIF#IFDEFLCD_IO4'Set pins to output DIR LCD_DB4 OUT DIR LCD_DB5 OUT DIR LCD_DB6 OUT DIR LCD_DB7 OUT 'WriteuppernibbletooutputpinssetLCD_DB4OFFsetLCD_DB5OFFsetLCD_DB6OFFsetLCD_DB7OFFifLCDByte.7ONTHENSETLCD_DB7ONifLCDByte.6ONTHENSETLCD_DB6ONifLCDByte.5ONTHENSETLCD_DB5ONifLCDByte.4ONTHENSETLCD_DB4ON'Pulse enable pin Wait 5 10us PULSEOUT LCD_Enable, 5 10us Wait 5 10us 'WritelowernibbletooutputpinssetLCD_DB4OFFsetLCD_DB5OFFsetLCD_DB6OFFsetLCD_DB7OFFifLCDByte.3ONTHENSETLCD_DB7ONifLCDByte.2ONTHENSETLCD_DB6ONifLCDByte.1ONTHENSETLCD_DB5ONifLCDByte.0ONTHENSETLCD_DB4ON'Pulse enable pin Wait 5 10us PULSEOUT LCD_Enable, 5 10us Wait 5 10us 'SetdatapinslowagainSETLCD_DB7OFFSETLCD_DB6OFFSETLCD_DB5OFFSETLCD_DB4OFF#ENDIF#IFDEFLCD_IO8'Set data port to output, and write a value to it DIR LCD_DATA_PORT out LCD_DATA_PORT = LCDByte 'PulseenablepinWait510usPULSEOUTLCD_Enable,510usWait510us'Clear port again, in case it is shared with something else LCD_DATA_PORT = 0 #ENDIF #ENDIF #IFDEF LCD_CUSTOM DIR LCD_DB0 OUT DIR LCD_DB1 OUT DIR LCD_DB2 OUT DIR LCD_DB3 OUT DIR LCD_DB4 OUT DIR LCD_DB5 OUT DIR LCD_DB6 OUT DIR LCD_DB7 OUT set LCD_DB0 OFF set LCD_DB1 OFF set LCD_DB2 OFF set LCD_DB3 OFF set LCD_DB4 OFF set LCD_DB5 OFF set LCD_DB6 OFF set LCD_DB7 OFF if LCDByte.7 ON THEN SET LCD_DB7 ON if LCDByte.6 ON THEN SET LCD_DB6 ON if LCDByte.5 ON THEN SET LCD_DB5 ON if LCDByte.4 ON THEN SET LCD_DB4 ON if LCDByte.3 ON THEN SET LCD_DB3 ON if LCDByte.2 ON THEN SET LCD_DB2 ON if LCDByte.1 ON THEN SET LCD_DB1 ON if LCDByte.0 ON THEN SET LCD_DB0 ON 'PulseenablepinWait510usPULSEOUTLCD_Enable,510usWait510ussetLCD_DB0OFFsetLCD_DB1OFFsetLCD_DB2OFFsetLCD_DB3OFFsetLCD_DB4OFFsetLCD_DB5OFFsetLCD_DB6OFFsetLCD_DB7OFF#ENDIFendsubSUBLCD2_NIBBLEOUT(InLCD2BYTE)'Set Data and Clock bits off SET LCD_DB OFF SET LCD_CB OFF 'ClearShiftRegisterWithsix0spriortoloadingFORLCDTemp=1TO6SETLCD_CBON' STROBE SET LCD_CB OFF '======NEXTSETLCD_DBON' First bit out to Shift register, always 1 for E gate SET LCD_CB ON 'STROBESETLCD_CBOFF' ====== IF LCD_RS OFF THEN SET LCD_DB OFF 'SecondbitoutequaltoR/SSETLCD_CBON' STROBE SET LCD_CB OFF '======'4 bits Data out to Shift register, starting from Nibble most significant bit FOR LCDTemp = 1 to 4 SET LCD_DB OFF IF LCD2Byte.3 ON THEN SET LCD_DB ON SET LCD_CB ON SET LCD_CB OFF ROTATE LCD2Byte LEFT NEXTSET LCD_DB ON 'LastpulseforNibbleoutput.NotforShiftregisterWAIT1MS' Put E pin on LCD to one through an AND operation SET LCD_DB OFF 'withthefirstbitoutputted(E)ENDSUBfunctionLCDNormalReadByte#IFDEFLCD_NO_RWLCDReadByte=0ExitFunction#ENDIF#IFNDEFLCD_NO_RWsetLCD_RWON'Read mode LCDReadByte = 0 #IFNDEF LCD_CUSTOM #IFDEF LCD_IO 4 'SetpinstoinputDIRLCD_DB4INDIRLCD_DB5INDIRLCD_DB6INDIRLCD_DB7IN'Read upper nibble from input pins SET LCD_Enable ON Wait LCD_Write_Delay if LCD_DB7 ON then SET LCDReadByte.7 ON if LCD_DB6 ON THEN SET LCDReadByte.6 ON if LCD_DB5 ON then SET LCDReadByte.5 ON if LCD_DB4 ON THEN SET LCDReadByte.4 ON SET LCD_Enable OFF Wait 2 10us 'ReadlowernibblefrominputpinsSETLCD_EnableONWaitLCD_Write_DelayifLCD_DB7ONthenSETLCDReadByte.3ONifLCD_DB6ONTHENSETLCDReadByte.2ONifLCD_DB5ONthenSETLCDReadByte.1ONifLCD_DB4ONTHENSETLCDReadByte.0ONSETLCD_EnableOFFWait210us#ENDIF#IFDEFLCD_IO8DIRLCD_DATA_PORT255SETLCD_EnableONWaitLCD_Write_DelayLCDReadByte=LCD_DATA_PORTSETLCD_EnableOFFWait210us#ENDIF#ENDIFIFDEFLCD_CUSTOM'Set pins to input DIR LCD_DB1 IN DIR LCD_DB2 IN DIR LCD_DB2 IN DIR LCD_DB3 IN DIR LCD_DB4 IN DIR LCD_DB5 IN DIR LCD_DB6 IN DIR LCD_DB7 IN SET LCD_Enable ON Wait LCD_Write_Delay if LCD_DB7 ON then SET LCDReadByte.7 ON if LCD_DB6 ON THEN SET LCDReadByte.6 ON if LCD_DB5 ON then SET LCDReadByte.5 ON if LCD_DB4 ON THEN SET LCDReadByte.4 ON if LCD_DB3 ON then SET LCDReadByte.3 ON if LCD_DB2 ON THEN SET LCDReadByte.2 ON if LCD_DB1 ON then SET LCDReadByte.1 ON if LCD_DB0 ON THEN SET LCDReadByte.0 ON SET LCD_Enable OFF Wait 2 10us #ENDIF #ENDIFend functionsub InitLCD #IFNDEF LCD_CUSTOM #IFDEF LCD_IO 2 SET LCD_DB OFF SET LCD_CB OFF DIR LCD_DB OUT DIR LCD_CB OUT WAIT 35 MS SET LCD_RS OFF LCD2_NIBBLEOUT 0X03 Wait 5 ms LCD2_NIBBLEOUT 0X03 WAIT 1 MS LCD2_NIBBLEOUT 0X03 WAIT 1 MS LCD2_NIBBLEOUT 0X02 WAIT 1 MS LCDWriteByte 0x28 WAIT 1 MS LCDWriteByte 0x08 WAIT 1 MS LCDWriteByte 0x01 WAIT 5 MS LCDWriteByte 0x06 WAIT 1 MS LCDWriteByte 0x0C WAIT 1 MS #ENDIF #IFDEF LCD_IO 4,8 DIR LCD_RS OUT #IFNDEF LCD_NO_RW DIR LCD_RW OUT #ENDIF DIR LCD_Enable OUT wait 10 ms Wait until LCDReady 'SetdatabuswidthSETLCD_RSOFF#ENDIF#IFDEFLCD_IO8LCDWriteByte(b'00111000')#ENDIF#IFDEFLCD_IO4DIRLCD_DB4OUTDIRLCD_DB5OUTDIRLCD_DB6OUTDIRLCD_DB7OUTsetLCD_RSOFF#IFNDEFLCD_NO_RWsetLCD_RWOFF#ENDIFsetLCD_DB4OFFsetLCD_DB5ONsetLCD_DB6OFFsetLCD_DB7OFFWait510usPulseOutLCD_Enable,510usWait5msLCDWriteByte(b'00101000')wait2510us#ENDIF#IFDEFLCD_IO4,8'Set Cursor movement SET LCD_RS OFF LCDWriteByte(b'00000110') wait 5 10us 'TurnoffcursorLCDWriteByte(b'00001100')wait510us'Clear screen CLS #ENDIF #ENDIF #IFDEF LCD_CUSTOM DIR LCD_RS OUT #IFNDEF LCD_NO_RW DIR LCD_RW OUT #ENDIF DIR LCD_Enable OUT wait 10 ms Wait until LCDReady 'SetdatabuswidthSETLCD_RSOFFLCDWriteByte(b'00111000')'Set Cursor movement SET LCD_RS OFF LCDWriteByte(b'00000110') wait 5 10us 'TurnoffcursorLCDWriteByte(b'00001100')wait510us'Clear screen CLS #ENDIFend subsub LCDCursor(In LCDCRSR) 'CanbeON,FLASHorOFFSetLCD_RWOFFLCDTemp=12'0 or 12 If LCDCRSR = ON Then LCDTemp = 14 '2or12IfLCDCRSR=FLASHThenLCDTemp=15'3 or 12 'IfLCDCRSR=OFFThenLCDTemp=0or12LCDWriteByte(LCDTemp)'(LCDTemp or 12) Wait 5 10usend sub'CreateacustomcharacterinCGRAMsubLCDCreateChar(InLCDCharLoc,LCDCharData())#IFNDEFLCD_CUSTOM'Store old location #IFDEF LCD_IO 4,8 Set LCD_RS Off LCDLoc = LCDReadByte Set LCDLoc.7 On #ENDIF 'SelectlocationSetLCD_RSOffLCDWriteByte(64+LCDCharLoc*8)wait510us'Write char Set LCD_RS On For LCDTemp = 1 to 8 LCDWriteByte LCDCharData(LCDTemp) wait 5 10us Next 'Restorelocation#IFDEFLCD_IO2setLCD_RSoffLCDWriteByte(0x80)wait510us#ENDIF#IFDEFLCD_IO4,8SetLCD_RSOffLCDWriteByte(LCDLoc)wait510us#ENDIF#ENDIF#IFDEFLCD_CUSTOM'Store old location Set LCD_RS Off LCDLoc = LCDReadByte Set LCDLoc.7 On 'SelectlocationSetLCD_RSOffLCDWriteByte(64+LCDCharLoc*8)wait510us'Write char Set LCD_RS On For LCDTemp = 1 to 8 LCDWriteByte LCDCharData(LCDTemp) wait 5 10us Next 'RestorelocationSetLCD_RSOffLCDWriteByte(LCDLoc)wait510us#ENDIFendsub'Create a graph character in CGRAMSub LCDCreateGraph(In LCDCharLoc, In LCDValue) #IFNDEF LCD_CUSTOM 'Storeoldlocation#IFDEFLCD_IO4,8SetLCD_RSOffLCDLoc=LCDReadByteSetLCDLoc.7On#ENDIF'Select location Set LCD_RS Off LCDWriteByte (64 + LCDCharLoc * 8) wait 5 10us 'WritecharforgraphSetLCD_RSOnForLCDTemp=8to1IfLCDTemp>LCDValueThenLCDWriteByteLCD_BAR_EMPTYElseLCDWriteByteLCD_BAR_FULLEndIfwait510usNext'Restore location #IFDEF LCD_IO 2 set LCD_RS off LCDWriteByte(0x80) wait 5 10us #ENDIF #IFDEF LCD_IO 4,8 Set LCD_RS Off LCDWriteByte (LCDLoc) wait 5 10us #ENDIF #ENDIF #IFDEF LCD_CUSTOM 'StoreoldlocationSetLCD_RSOffLCDLoc=LCDReadByteSetLCDLoc.7On'Select location Set LCD_RS Off LCDWriteByte (64 + LCDCharLoc * 8) wait 5 10us 'WritecharforgraphSetLCD_RSOnForLCDTemp=8to1IfLCDTemp>LCDValueThenLCDWriteByteLCD_BAR_EMPTYElseLCDWriteByteLCD_BAR_FULLEndIfwait510usNext'RestorelocationSetLCD_RSOffLCDWriteByte(LCDLoc)wait510us#ENDIFEndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
i have tested the software on the actual chip itself. this confirms that the issues arent from the simulator i am using. the software works fine on the chip, until i add extra lines in the code (setting the same variable to the same value multiple times). as soon as the code is over 2k in size the software no longer seems to be running at all on the chip
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
i looked more closely at my datasheet. an error im getting from the simulator "attempt to read unimplemented memory location 0x049b" made me look at the memory location 0x049b, which is in bank 9. that location is shaded grey on the data sheet with a - there. is gcbasic trying to access a memory location that isnt accessible on my chip?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
another thing ive noticed is the PCLATH never seems to change when run in the simulator, am i wrong or shouldnt the PCLATH be changing when reaching other memory pages. also the error im getting now is saying it cant read/write to "unimplemented memory location" 0x049c, according to the datasheet this location is in the general purpose register, so it seems its having a problem with ram? i mean i dont really know, i dont speak assembly language but i can make educated guesses
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
ok, i know im making this forum post a mile long, however ive made some new discoveries. i made a much simpler program, which just simply clears an lcd, prints "Hello World" on an lcd, then waits 1 second. it does that about 40-50 times, which fills the first page of the program memory, then i go to a sub routine that does the same thing (clears the lcd, prints "Hello World" on it, then waits 1 second) and i set it to do that about 40-50 times. the program size ends up being 2968 bytes, which is over the 2k size barrier. this simple program runs just fine in the simulator, no errors or problems. so im thinking something else is causing my issues in me less simple program. maybe it could be the math (possibly a problem with math spanning multiple pages?) or i guess it could be a problem with my variable arrays? i mean im trying to track this problem down but it feels like i keep hitting a wall.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
im getting unimplemented memory location again, this time i know what it is claiming is unimplemented. this spacific problem is this instruction "BSF Unimplemented" and the PC is 00FB
the part that its saying is unimplemented is "0000FB 1513 BSF CCP3CON,CCP1M2"
so it seems to be thinking "CCP3CPM,CCP1M1" is unimplemented. i think this is because its not BANKSEL'ing the CCP3CON. here is a small snippet of the .lst file
The assembler in GCBASIC is seeing "PAGESEL", and then using movlb (bank select) instead of movlp (page select). The giveaway is in the list file there - 0x0020 is BANKSEL 0, not PAGESEL $. Without pagesels, the code is probably not even running in the right order. I will upload a fix shortly.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
im writing a slightly large program. the problem begins when the size of the program extends past 2k in size. im using proteus to simulate my program and when i run it i get errors like
"PC=0x0055 Attempt to read unimplemented memory location 0x0411 ignored"
and
"PC=0x0055 Attempt to write unimplemented memory location 0x0411 with 0x00 ignored"
my program works fine when the size is around 2kb, i increased the size of the program by setting the same variable, with the same value, about 20 times, which pushed the size of my program to around 2.3k in size, and i get these errors.
i have tried the program with and without "#option lcall" and i get the same results either way.
i dont think this is a problem with my code, because the only thing i change in the code is setting the variable multiple times with the same value.
im using the pic micro 16f1938, which has (i think) around 16k of program space, i would like to be able to use (most) of it, its doubtful ill need more than 4k of space for the program i am writing but im sure to need more than 2k.
any help would be appreciated
That looks more like the compiler is placing variables in unimplemented RAM.
In the 16F1938 DAT file there does seem to be an error in the FreeRAM allocation - the last block is listed as 620:34F. It should be 620:64F so try changing that.
The same error appears in the dat files for -
16F1829
16F1847
16F1939
16F1947
generated on 15/2/2012 for anyone using those chips.
I tried that, and theres no change. still getting errors when program goes over 2k.
the specific error im getting right now is
"PC=0x005a. Attempt to write unimplemented memory location 0x0412 with 0xF0 ignored."
and the error repeats every .001 seconds, with the only difference between the errors being the "PC=_____" value, some other values are
PC=0x005c PC=0x005E PC=0x0060
Good job spotting that error with the RAM bank definitions, I will update the chip data!
I'm not sure what is causing that error. I'd guess that it's something to do with the bank selection code, but I can't say for sure. The PC = 0x55 is a good tip though. If you're using the assembler in GCBASIC, could you copy and paste the relevant section of the listing file? That will probably be called compiled.lst, and you can open it with Notepad. If you're using the assembler in GCBASIC, scroll down to the line that starts with "000055", then copy and paste it and the 10 lines before and after it.
ive changed my code since my last post, but the results are very similar, still works fine under 2k, but now when over 2k this is the error i get
"PC=0x01D6 Attempt to read unimplemented memory location 0x0495 ignored"
and
"PC=0x01D6 Attempt to write unimplemented memory location 0x0495 with 0x01 ignored"
and that message repeats every .00001s until i end the simulation
here is my the section of my .lst file near the location of 01D6 (though there is no 01D6 in the .lst file anywhere"
ENDIF81
0001CC 3002 MOVLW 2
000000 0020 BANKSEL HI2CCURRENTMODE
0001CE 0225 SUBWF HI2CCURRENTMODE,W
0001CF 1D03 BTFSS STATUS, Z
0001D0 29D6 GOTO ENDIF82
000000 0024 BANKSEL SSPCON1
0001D2 1195 BCF SSPCON1,SSPM3
0001D3 1515 BSF SSPCON1,SSPM2
0001D4 1495 BSF SSPCON1,SSPM1
0001D5 1415 BSF SSPCON1,SSPM0
ENDIF82
000000 0024 BANKSEL SSPCON1
0001D7 1695 BSF SSPCON1,SSPEN
000000 0020 BANKSEL STATUS
0001D9 0008 RETURN
That code looks ok at first glance. I thought that a banksel command might be missing, but it looks like there are banksel commands everywhere that there should be. They also appear to be selecting the correct bank. "BANKSEL SSPCON1" is setting the bank select register to 4, which seems to be correct because SSPCON1 is in bank 4.
As a quick test, I put this code into MPLAB SIM and ran it:
LIST p=16F1938, r=DEC
#include <P16F1938.inc>
ORG 0
banksel SSPCON1
bsf SSPCON1, SSPEN
goto $
END
It worked without any problems (selected bank 4, and then set SSPEN) and the hex code generated by MPASM matches that produced by GCBASIC's assembler. I'll have another look tomorrow and double check, but the problem may be in the simulator.
well if it helps ill post here my full code, it is a possibility that the problem is with the simulator, this is the first chip ive had that had more than 2k program space so ive never had the chance to test this all out. i guess i could put the program on the chip itself and see if it works as expected but its just a lot easier to run it through the simulator instead of reprogramming the chip over and over. anyway, heres the full code.
the section of code repeating the lcd command are just to get it past the 2k size, without those repeated commands in the code i get no errors, but i will test the code on the hardware itself tonight and see if it works properly. ill post the results of my hardware tests here
Hugh, in case youre interested i have modified the LCD.C file to add support for lcd 8-bit mode, with all 8 pins customizable (in other words you dont have to use the bits of a port, you can use any pin for the lcds data pins).
you just have to put #define LCD_CUSTOM in the basic code, and for each lcd data pin like this
#define LCD_DB0 portX.X
#define LCD_DB1 portX.X
#define LCD_DB2 portX.X
#define LCD_DB3 portX.X
#define LCD_DB4 portX.X
#define LCD_DB5 portX.X
#define LCD_DB6 portX.X
#define LCD_DB7 portX.X
I modified this code because i couldnt use my entire portA (one of the pins was a HPWM which i wanted to use), and i didnt want to use portB (has the weak pull-ups so i wanna save that for inputs) and portC has the hardware I2C which i wanna use to talk to another pic micro.
so my only options were to use 4-bit mode, or to remap the pins for 8-bit mode
im not sure if anyone else will need to remap for 8-bit mode but in case anyone does here is the modified code. i also modified the HPWM code to add support for my additional PWM channels (my chip has 5 total but GCBASIC only had support for up to 3) if youd like that code too just ask. they are very simple modifications. just wanted to give something back to the community
i was missing some code in the init section to set the cursor movement, here is the corrected code which i have tested to work in a simulator
i have tested the software on the actual chip itself. this confirms that the issues arent from the simulator i am using. the software works fine on the chip, until i add extra lines in the code (setting the same variable to the same value multiple times). as soon as the code is over 2k in size the software no longer seems to be running at all on the chip
i looked more closely at my datasheet. an error im getting from the simulator "attempt to read unimplemented memory location 0x049b" made me look at the memory location 0x049b, which is in bank 9. that location is shaded grey on the data sheet with a - there. is gcbasic trying to access a memory location that isnt accessible on my chip?
another thing ive noticed is the PCLATH never seems to change when run in the simulator, am i wrong or shouldnt the PCLATH be changing when reaching other memory pages. also the error im getting now is saying it cant read/write to "unimplemented memory location" 0x049c, according to the datasheet this location is in the general purpose register, so it seems its having a problem with ram? i mean i dont really know, i dont speak assembly language but i can make educated guesses
actually my mistake, 49c is an unimplemented area of the memory. so what i dont get is where, and why is it trying to read from 49c
ok, i know im making this forum post a mile long, however ive made some new discoveries. i made a much simpler program, which just simply clears an lcd, prints "Hello World" on an lcd, then waits 1 second. it does that about 40-50 times, which fills the first page of the program memory, then i go to a sub routine that does the same thing (clears the lcd, prints "Hello World" on it, then waits 1 second) and i set it to do that about 40-50 times. the program size ends up being 2968 bytes, which is over the 2k size barrier. this simple program runs just fine in the simulator, no errors or problems. so im thinking something else is causing my issues in me less simple program. maybe it could be the math (possibly a problem with math spanning multiple pages?) or i guess it could be a problem with my variable arrays? i mean im trying to track this problem down but it feels like i keep hitting a wall.
im getting unimplemented memory location again, this time i know what it is claiming is unimplemented. this spacific problem is this instruction "BSF Unimplemented" and the PC is 00FB
the part that its saying is unimplemented is "0000FB 1513 BSF CCP3CON,CCP1M2"
so it seems to be thinking "CCP3CPM,CCP1M1" is unimplemented. i think this is because its not BANKSEL'ing the CCP3CON. here is a small snippet of the .lst file
Ok, I have found the bug!
The assembler in GCBASIC is seeing "PAGESEL", and then using movlb (bank select) instead of movlp (page select). The giveaway is in the list file there - 0x0020 is BANKSEL 0, not PAGESEL $. Without pagesels, the code is probably not even running in the right order. I will upload a fix shortly.
I've now uploaded an updated version of GCBASIC to http://gcbasic.sourceforge.net/newfiles/update-nochipdata.zip - please try that and see if it fixes the bug!
perfect! thanks so much for your time it works perfect now