PDA

View Full Version : LCD serial backpacks



Archangel
- 4th November 2006, 08:42
Hi Everyone,
It seems as if, . . . the LCD serial backpack device must be the
Crown Jewels, of PICdome as I have been unable to wrestle suitable
code out of the internet. Posted below is a modified version of some code
I found somewhere, probably for a BS1, anyway I tweaked it some and it works after a fashion, but I think it needs something in the way of a buffer
and some code to make changes on the fly, like does the cursor blink or not
etc. . . I think it would be way cool to fashion a workable public domain
serial unit, so newbies and non-newbies have access without forking up $35 bucks for a serial LCD.

Anyone up to the challange? As I have been coding PIC micros only since 08/06, My coding skills are not there yet, but thanks to you all I am learning.
Joe




@ DEVICE pic16F628A, HS_OSC

@ DEVICE pic16F628A, WDT_ON
' Watchdog Timer

@ DEVICE pic16F628A, PWRT_ON
' Power-On Timer

@ DEVICE pic16F628A, MCLR_ON
' Master Clear Options (Internal)

@ DEVICE pic16F628A, BOD_OFF
' Brown-Out Detect

@ DEVICE pic16F628A, LVP_OFF
' Low-Voltage Programming

@ DEVICE pic16F628A, CPD_OFF
' Data Memory Code Protect
' Set to CPD_OFF for Development Copy
' Set to CPD_ON for Release Copy

@ DEVICE pic16F628A, PROTECT_OFF
' Program Code Protection
' Set to PROTECT_OFF for Development Copy
' Set to PROTECT_ON for Release Copy

trisb = %00000001
trisA = %11110011
include "modedefs.bas"
' Define LCD registers and bits
Define LCD_DREG PORTB
Define LCD_DBIT 4
Define LCD_RSREG PORTB
Define LCD_RSBIT 2
Define LCD_EREG PORTB
Define LCD_EBIT 3

DEFINE LCD_LINES 4 'Define using a 2 line LCD
DEFINE LCD_COMMANDUS 2000 'Define delay time between sending LCD commands
DEFINE LCD_DATAUS 50 'Define delay time between data sent.
DEFINE OSC 20

char Var byte ' Storage for serial character



CMCON = 7 ' PORTA is digital

Pause 100 ' Wait for LCD to startup
high PortA.2 ' power for backlight
low PortA.3 ' backlight ground

main:

Lcdout $FE, 1 ' Initialize and clear display
LCDOUT $FE, $0C

LCDOUT "My Flash Text"
pause 800
Lcdout $FE, 1,$FE, 2

goto loop


loop: Serin PORTB.1,N9600,char ' Get a char from serial input
Lcdout char ' Send char to display

Goto loop ' Do it all over again

End

sayzer
- 4th November 2006, 11:29
Hi Joe,

Howzit?

Could you give some more details?

I am not sure what you want to have is?


-------------------------------

Archangel
- 5th November 2006, 08:24
Sayzer,
Greetings !
Here is the Rub:
every time I or tons of others out there need a serial display, we have to stop what we are doing and order a preprogrammed chip, a kit, or an already assembled serial display at significant cost. A year from now I will likely be able to write enough code to handle this, for now NO. sometimes it is just better to connect the display via a serial connection, for instance, you homebrew a burgular alarm, you keep the alarm chip safely inside, and display can live outdoors. Nowhere have I been able to find code already written and available to home roll a suitable serial display and it really is agrivating to have to stop and order and wait for one when you need it. This seems to be the only PIC related everyday item where near zero code is in the public domain
The code I posted seems to work with a 2 X 16 display but I doubt it is suitable as is to use as a general purpose serial LCD adapter, I think it needs USART support to provide a data buffer so data doesn't get lost. Additionally
the LCDOUT routine is great for a finished project, but these push in wire type breadboards are so clumbsy as to make you waste too much time fiddling with connections, whereas a serial lcd is more convienent. I have seen in books authors who use shift registers to do this, curiously enough they were books about PICs * * * * So what I am looking for is a serial backpack device common to all who use this forum that we all get familiar with using so your code or Darrels, or Bruces, ETC does not have to be modified to work on as it seems every serial backpack out there uses different initialization routiens, and you still have to wait for and pay for every time you want one.
Thanks
Joe

BobK
- 6th November 2006, 14:42
Hi Joe S.

I really am trying to figure out how to offer some help to you. I too have had a problem using serial LCD's in the past. I have one from SEETRON, a 2x16 that has served me well in the past few years. I don't understand why it should take a "special" type of serial adaptor for every type of project though. The only difference between setups is the baud rate that I can see. You use either 2400 or 9600. The difference is on the PIC side. If you are going to do any serial data out, you really should use an external crystal or resonator. This is because the PIC's internal clock isn't always accurate for the higher baud rates. This fact has been stated many times in the past on the various forums here. Your PIC only needs the statement: "SEROUT GPIO.0,6,[72,72,58,77,77] 'Display HH:MM", for example, to get data to the display. Obviously, the PIC must be configured for the baud rate. (I took the statement from Paul Borgmeier's Easy Clock program). There is far less setup and PIC pin usage with a serial display than with a parallel display so I think that's why they are shown more than the parallel displays. As for someone specifying certain types of backpacks, it shouldn't matter. All you are doing is sending serial data out at a certain rate. Most backpacks have jumper selectable baud rates.

You should be able to buy a couple of backpacks, keep them in a parts drawer, then when you need one, plug in the LCD and away you go. I just bought 4 from a place called Wulfeden for a reasonable price and I have them available when I need them. I have been mostly been using 4 x 20 VFDs on a few larger projects. I bought a dozen of Melanie's Blue 2 x 16 LCDs last year and they are great for adding the backpack to. You don't need to solder the backpack to the LCD. Just use plugable headers. So If you go from parallel to serial you just plug in the backpack and away you go.

I hope this helps.

BobK

DynamoBen
- 6th November 2006, 15:52
I've made serial to parallel LCD backpacks before. When I did it the LCD, or in this case VFD, had an odd protocol and I was trying to standardize it. I located a serial protocol from another manufacturer as my model. (matrix orbital or crystal fontz) While it did work well I ended up not completing the code because the VFD got damaged.

The two commands I used were HSERIN (serial in), and LCDOut. Most of the code was taken up with a Select Case routine to convert incoming command codes to something the VFD could understand. The process was listen for serial commands, buffer incoming serial data, parse command codes, and send data to LCD/VFD. You already have a start on this with your code, now you need to add in the additional commands (see either another serial protocol or use the LCDOut information).

All that being said, if all you want is an inexpensive backpack or you want an idea of what a pic based on looks like try this:
http://www.sparkfun.com/commerce/product_info.php?products_id=258

Archangel
- 6th November 2006, 22:49
Hi All,
The serial adapter I currently use can be found at a reasonable price really, from
http://phanderson.com/lcd106/lcd107.html, 2.95 each in 100 qty, having said that, I still do not want to us them as I do not have confidence in any device I have not seen the code for, especially when it comes to embedding operations code into my applications for products I wish to sell to a manufacturer, additionally I do not care to have his test routine or splash screen on my application. For a gadget to use around the house, then sure, I will use them. I have seen 1 or 2 out there written in assembler or C, C++, I suppose I will continue to hammer on the listed code until I am satisfied it works as expected every time and always. Right now I waiting for an order of 4x20 displays from China.
JS

Archangel
- 6th November 2006, 23:05
As for someone specifying certain types of backpacks, it shouldn't matter.

BobK

Ahh not so . . the hitachi chip does display data the same regardless of who's backpack drives it, assuming the data doesnt get filtered first. The problem here is everyone who sells one of these has his/her own little initialization routines and that's what will trip me up, if I code for Anderson's unit and my customer finds a better deal on Seetron's display, now I get a nasty phone call. .I always try to put the fire out before it is lit. The best way to do that is control the code.
Thank You for your input (everyone!) and anyone who wants to ring in an opinion on this, I think that would be super. Im trying to get around the 8 track / vs cassette , vhs vs beta, why won't my Chevy wheels fit a Ford Scenerio. I can go buy basicly anybodys video card and put in my Computer p/c or mac, so I think the way to workable standards is through the public domain. My Opinion, for better or worse.
JS

Archangel
- 18th November 2006, 09:29
Ok enough of my whining, here is some workable code, thanks to Darrel Taylor, well mostly about 99 percent. He wrote it for something else, I added a monkey wrench and a screwdriver and it works for my needs, could it be better? Well you can judge for your self, it works good enough for my application as is
Thanks Once again Darrel for the post I extracated this code from.



@ DEVICE pic16F628A, HS_OSC

@ DEVICE pic16F628A, WDT_OFF
' Watchdog Timer

@ DEVICE pic16F628A, PWRT_ON
' Power-On Timer

@ DEVICE pic16F628A, MCLR_ON
' Master Clear Options (Internal)

@ DEVICE pic16F628A, BOD_OFF
' Brown-Out Detect

@ DEVICE pic16F628A, LVP_OFF
' Low-Voltage Programming

@ DEVICE pic16F628A, CPD_OFF
' Data Memory Code Protect
' Set to CPD_OFF for Development Copy
' Set to CPD_ON for Release Copy

@ DEVICE pic16F628A, PROTECT_OFF
' Program Code Protection
' Set to PROTECT_OFF for Development Copy
' Set to PROTECT_ON for Release Copy

trisb = %00000010
trisA = %11110011
include "modedefs.bas"
' Define LCD registers and bits
Define LCD_DREG PORTB
Define LCD_DBIT 4
Define LCD_RSREG PORTA
Define LCD_RSBIT 0
Define LCD_EREG PORTA
Define LCD_EBIT 1

DEFINE LCD_LINES 4 'Define using a 2 line LCD
DEFINE LCD_COMMANDUS 2000 'Define delay time between sending LCD commands
DEFINE LCD_DATAUS 50 'Define delay time between data sent.
DEFINE OSC 20

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_SPBRG 32 ' FOR 20MHZ 129 = 2400, 32=9600,25 @ 4 for 2400
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty)
TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full)
LED VAR PORTA.4

OERR VAR RCSTA.1 ' Alias OERR (USART Overrun Error Flag)
CREN VAR RCSTA.4 ' Alias CREN (USART Continuous Receive Enable)
buffer_size CON 64 ' Sets the size of the ring buffer, set up from 32
buffer VAR BYTE[buffer_size]' Array variable for holding received characters
index_in VAR BYTE ' Pointer - next empty location in buffer
index_out VAR BYTE ' Pointer - location of oldest character in buffer
bufchar VAR BYTE ' Stores the character retrieved from the buffer
i VAR BYTE ' loop counter
Col VAR BYTE ' Stores location on LCD for text wrapping
errflag VAR BYTE ' Holds error flags
index_in = 0
index_out = 0
i = 0
col = 1

'RxData var byte
CMCON = 7 ' PORTA is digital
Pause 100 ' Wait for LCD to startup
high PortA.2 ' power for backlight
low PortA.3 ' backlight ground
INTCON = %11000000 ' Enable interrupts
ON INTERRUPT GoTo serialin ' Declare interrupt handler routine
PIE1.5 = 1 ' Enable interrupt on USART
pause 1500
lcdout $FE,1
lcdout $FE,2
LCDOUT "Your Text Goes Here"
PAUSE 2000

' * * * * * * * * * * * * * Main program starts here - blink an LED at 1Hz
' I removed some code here, it seems to require what's left
loop:
For i = 0 to 10 ' Delay for .02 seconds (10*2mS)
Pause 2 ' Use a short pause within a loop
Next i ' instead of one long pause

For i = 0 to 10 ' Delay for .02 seconds (10*2mS)
Pause 2 ' Use a short pause within a loop
Next i ' instead of one long pause


display: ' dump the buffer to the LCD
IF errflag Then error ' Handle error if needed
IF index_in = index_out Then loop ' loop if nothing in buffer

GoSub getbuf ' Get a character from buffer
LCDOut bufchar ' Send the character to LCD


IF col > 20 Then ' Check for end of line
col = 1 ' Reset LCD location
LCDOut $fe,$c0,REP " "\20 ' Clear line-2 of LCD
LCDOut $FE,2 ' Tell LCD to return home
EndIF

GoTo display ' Check for more characters in buffer



' Subroutines

Disable ' Don't check for interrupts in this section

getbuf: ' move the next character in buffer to bufchar
index_out = (index_out + 1) ' Increment index_out pointer (0 to 63)
' Reset pointer if outside of buffer
IF index_out > (buffer_size-1) Then index_out = 0
bufchar = buffer[index_out] ' Read buffer location
Return


error: ' Display error message if buffer has overrun
IF errflag.1 Then ' Determine the error
LCDOut $FE,$c0,"Clearing Display Buffer" ' Display buffer error on
' line-2 and 3 Buff overrun
Else
LCDOut $FE,$D4,"USART Overrun" ' Display usart error on line-4
EndIF

LCDOut $fe,2 ' Send the LCD cursor back to line-1 home
For i = 2 to col ' Loop for each column beyond 1
LCDOut $fe,$14 ' Move the cursor right to the right column
Next i ' $14 = 20 DEC.

errflag = 0 ' Reset the error flag
CREN = 0 ' Disable continuous receive to clear overrun flag
CREN = 1 ' Enable continuous receive

GoTo display ' Errors cleared, time to work.


' * * * * * * * * * * * * * * * Interrupt handler

serialin: ' Buffer the character received
IF OERR Then usart_error ' Check for USART errors
index_in = (index_in + 1) ' Increment index_in pointer (0 to 63)
IF index_in > (buffer_size-1) Then index_in = 0 'Reset pointer if outside of buffer
IF index_in = index_out Then buffer_error ' Check for buffer overrun
HSerin [buffer[index_in]] ' Read USART and store character to next empty location
IF RCIF Then serialin ' Check for another character while we're here

Resume ' Return to program

buffer_error:
errflag.1 = 1 ' Set the error flag for software
' Move pointer back to avoid corrupting the buffer. MIN insures that it ends up within the buffer.
index_in = (index_in - 1) MIN (buffer_size - 1)
HSerin [buffer[index_in]] ' Overwrite the last character stored (resets the interrupt flag)
usart_error:
errflag.0 = 1 ' Set the error flag for hardware

Resume ' Return to program


End


As I gain coding experience I will revisit this code unless someone else does so first ;-)
JS

Oh, what I really like about this is you use the standard formatting commands as used with LCDOUT, no funky commands.

Darrel Taylor
- 18th November 2006, 18:02
Hi Joe,

Glad you got it working!
That must have been a really old one.
It doesn't look familiar at all.

mister_e
- 18th November 2006, 19:17
That's what i thought when i saw...

ON INTERRUPT GoTo ....

;)

Archangel
- 18th November 2006, 20:33
Hi Joe,

Glad you got it working!
That must have been a really old one.
It doesn't look familiar at all.
Hmmmmm, it must have been the screwdriver . . .
JS

Darrel Taylor
- 19th November 2006, 01:34
That's what i thought when i saw...

ON INTERRUPT GoTo ....

;)

That's right!
Nobody uses ON INTERRUPT anymore!! errr, uhhh... :)
<br>

Archangel
- 20th November 2006, 05:11
That's right!
Nobody uses ON INTERRUPT anymore!! errr, uhhh... :)
<br>
That's because they use . . . assembler . . . or D_T_Interrupts?

Darrel Taylor
- 20th November 2006, 05:25
Exactly!

And even with assembly, they still use DT_INTS

Well, at least 5 or so of them do. :)

BTW, it would make your backpack more responsive. Fewer dropped characters, and faster baud rates. Just a suggestion.
<br>

Archangel
- 20th November 2006, 08:44
Exactly!

BTW, it would make your backpack more responsive. Fewer dropped characters, and faster baud rates. Just a suggestion.
<br>
Hi Darrel,
I don't have a firm grasp on "ON INTERRUPT" yet, but I put in a few hours each day, Playing(WORKING) with PBP and this forum and I will get there. You just learn a little slower after 50. I am thinking about your bargraphs too, still I'm thinking with only 4 months of experience at this, not too bad,I can look at my earliest programs and see the progress, <h4>You all have been a tremendus resource, the brain trust here truly amazing.</h4> In my world I have to learn things over and over in order to retain it, I make little code snippet files and then study them to see how things work, change things to see how the outputted behavior changes, all very interesting all very time consuming. It looks as if assembler is simpler in syntax but 100 times more tedious, as you have to guide it through every move, how long have you been doing this? anyway, I will visit and revisit DT_INTS and try to figure how to implement it into the backpack. I still have to learn how to use eprom too . . . so much to learn, so many posts to study . . . are we havin' fun yet ? ....You bet! Thanks Darrel,
JS

Darrel Taylor
- 20th November 2006, 10:42
>> You just learn a little slower after 50.

Oh No! I better hurry up and learn more, I've only got 3 years left. :)

>> ... with only 4 months of experience at this ...

Well, for only 4 months, you're doing pretty good.

>> ... how long have you been doing this? anyway

PicBasic Pro - about 5 years
Programming - Umm, one month after the first TRS-80 hit the market, I guess that makes it about oh 28 years.<hr>

I know DT_INTS looks intimidating at the begining, but it's really not that bad, and you don't need to learn assembly language to use it. But I can understand why you might not want to try it out. The biggest obstacle is that you have to be using MPASM.

So whenever you get around to DT_INTS, you can come back to this thread and try out this program.
It's your backpack program modified for Instant Interrupts.
I've highlighted most of the changes (red is added, blue is removed).
Tested it on a 16F877A
;---- Config settings for MPASM ----------------------------------------------
@ __config _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _LVP_OFF & _CP_OFF

trisb = %00000010
trisA = %11110011
;include "modedefs.bas"

;----Added by DT--------------------------------------------------------------
INCLUDE "DT_INTS-14.bas"
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RX_INT, _serialin, PBP, no
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE RX_INT ; enable external (INT) interrupts
;-----------------------------------------------------------------------------

' Define LCD registers and bits
Define LCD_DREG PORTB
Define LCD_DBIT 4
Define LCD_RSREG PORTA
Define LCD_RSBIT 0
Define LCD_EREG PORTA
Define LCD_EBIT 1

DEFINE LCD_LINES 4 'Define using a 2 line LCD
DEFINE LCD_COMMANDUS 2000 'Define delay time between sending LCD commands
DEFINE LCD_DATAUS 50 'Define delay time between data sent.
DEFINE OSC 20

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_SPBRG 32 ' FOR 20MHZ 129 = 2400, 32=9600,25 @ 4 for 2400
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty)
TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full)
LED VAR PORTA.4

OERR VAR RCSTA.1 ' Alias OERR (USART Overrun Error Flag)
CREN VAR RCSTA.4 ' Alias CREN (USART Continuous Receive Enable)
buffer_size CON 64 ' Sets the size of the ring buffer, set up from 32
buffer VAR BYTE[buffer_size]' Array variable for holding received characters
index_in VAR BYTE ' Pointer - next empty location in buffer
index_out VAR BYTE ' Pointer - location of oldest character in buffer
bufchar VAR BYTE ' Stores the character retrieved from the buffer
i VAR BYTE ' loop counter
Col VAR BYTE ' Stores location on LCD for text wrapping
errflag VAR BYTE ' Holds error flags
index_in = 0
index_out = 0
i = 0
col = 1

'RxData var byte
CMCON = 7 ' PORTA is digital
Pause 100 ' Wait for LCD to startup
high PortA.2 ' power for backlight
low PortA.3 ' backlight ground
;INTCON = %11000000 ' Enable interrupts
;ON INTERRUPT GoTo serialin ' Declare interrupt handler routine
;PIE1.5 = 1 ' Enable interrupt on USART
pause 1500
lcdout $FE,1
lcdout $FE,2
LCDOUT "Your Text Goes Here"
PAUSE 2000

' * * * * * * * * * * * * * Main program starts here - blink an LED at 1Hz
' I removed some code here, it seems to require what's left
loop:
For i = 0 to 10 ' Delay for .02 seconds (10*2mS)
Pause 2 ' Use a short pause within a loop
Next i ' instead of one long pause

For i = 0 to 10 ' Delay for .02 seconds (10*2mS)
Pause 2 ' Use a short pause within a loop
Next i ' instead of one long pause


display: ' dump the buffer to the LCD
IF errflag Then error ' Handle error if needed
IF index_in = index_out Then loop ' loop if nothing in buffer

GoSub getbuf ' Get a character from buffer
LCDOut bufchar ' Send the character to LCD


IF col > 20 Then ' Check for end of line
col = 1 ' Reset LCD location
LCDOut $fe,$c0,REP " "\20 ' Clear line-2 of LCD
LCDOut $FE,2 ' Tell LCD to return home
EndIF

GoTo display ' Check for more characters in buffer



' Subroutines

;Disable ' Don't check for interrupts in this section

getbuf: ' move the next character in buffer to bufchar
@ INT_DISABLE RX_INT
index_out = (index_out + 1) ' Increment index_out pointer (0 to 63)
' Reset pointer if outside of buffer
IF index_out > (buffer_size-1) Then index_out = 0
bufchar = buffer[index_out] ' Read buffer location
@ INT_ENABLE RX_INT
Return


error: ' Display error message if buffer has overrun
IF errflag.1 Then ' Determine the error
LCDOut $FE,$c0,"Clearing Display Buffer" ' Display buffer error on
' line-2 and 3 Buff overrun
Else
LCDOut $FE,$D4,"USART Overrun" ' Display usart error on line-4
EndIF

LCDOut $fe,2 ' Send the LCD cursor back to line-1 home
For i = 2 to col ' Loop for each column beyond 1
LCDOut $fe,$14 ' Move the cursor right to the right column
Next i ' $14 = 20 DEC.

errflag = 0 ' Reset the error flag
CREN = 0 ' Disable continuous receive to clear overrun flag
CREN = 1 ' Enable continuous receive

GoTo display ' Errors cleared, time to work.


' * * * * * * * * * * * * * * * Interrupt handler

serialin: ' Buffer the character received
IF OERR Then usart_error ' Check for USART errors
index_in = (index_in + 1) ' Increment index_in pointer (0 to 63)
IF index_in > (buffer_size-1) Then index_in = 0 'Reset pointer if outside of buffer
IF index_in = index_out Then buffer_error ' Check for buffer overrun
HSerin [buffer[index_in]] ' Read USART and store character to next empty location
IF RCIF Then serialin ' Check for another character while we're here
;resume
@ INT_RETURN ; Return to program

buffer_error:
errflag.1 = 1 ' Set the error flag for software
' Move pointer back to avoid corrupting the buffer. MIN insures that it ends up within the buffer.
index_in = (index_in - 1) MIN (buffer_size - 1)
HSerin [buffer[index_in]] ' Overwrite the last character stored (resets the interrupt flag)
usart_error:
errflag.0 = 1 ' Set the error flag for hardware
;resume
@ INT_RETURN ; Return to program


End

Hope you can use it some day,

skimask
- 26th November 2006, 04:17
Ok enough of my whining, here is some workable code, thanks to Darrel Taylor, well mostly about 99 percent. He wrote it for something else, I added a monkey wrench and a screwdriver and it works for my needs, could it be better? Well you can judge for your self, it works good enough for my application as is
Thanks Once again Darrel for the post I extracated this code from.
..........................
.........................
.......................
....................
..................
...............
............
..........
......
.......
........
.........
.........
..........
End

As I gain coding experience I will revisit this code unless someone else does so first ;-)
JS

Oh, what I really like about this is you use the standard formatting commands as used with LCDOUT, no funky commands.



I must've missed something in the translation here....
I've been basically working on the same type of thing for a couple of weeks now, and I think I might be shooting myself in the foot or something trying to figure this out...

How are you passing the lcdout 'commands'? i.e. lcdout $fe, 01 to clear the display and things like that?

If my guess is right, like me, you are basically replacing 'lcdout' with 'serout' on the main board, and this code is to read everything coming the serial port, and sending it out, character by character using a single 'lcdout'.

And if I'm reading this right, PBPro knows that if you send an '$FE', the next character down the line, whether it's in the same statement or not, will be an lcd 'command'.

Maybe that's where I'm tripping myself up. I'm trying to split data and commands apart at the lcd end of things...

Why did MeLabs pick $FE as the 'command' character anyways? Why not $FF or $CD or whatever?

Darrel Taylor
- 26th November 2006, 05:46
Hi Jeremy,


And if I'm reading this right, PBPro knows that if you send an '$FE', the next character down the line, whether it's in the same statement or not, will be an lcd 'command'.

You got it.

When PBP see's a $FE, it sets FLAGS.0 (LCDCDFLAG).
Which means that the next character is a command. And then when sending the next char, it sets the RS pin LOW.

And, while of no use but an example, if you were to do this...
FLAGS.0 = 1
LCDOUT 1It would do a Clear Screen.


Why did MeLabs pick $FE as the 'command' character anyways? Why not $FF or $CD or whatever?

For the HD44780's Character Table, The last 2 characters $FE and $FF are "all pixels OFF" and "all pixels ON" respectively. And, since "all pixels OFF" is the same thing as a Space, it's likely to assume that $FE will never be used to display a character. So it's available to initiate the Command sequence.

So all you really need to do for a backpack is, make sure that you don't miss any incomming data, and pass it all on to the LCDOUT command.

But, there can be some advantage to separating the Clear Screen and Home commands, like you've been doing.
They take the longest to execute (1.6-4.5ms) depending on the display. But LCD_COMMANDUS delays the same amount no matter which command is supplied. Commands like moving the cursor to a new location may only take between 40-120us (same as LCD_DATAUS), but LCDOUT will still wait the full LCD_COMMANDUS time (usually 2000us).

For a backpack, if you reduce the LCD_COMMANDUS time, and detect the Clear Screen and Home to add a longer pause. It can increase the speed to a point where you don't even need to buffer the data up to 9600 baud.

Archangel
- 26th November 2006, 08:26
How are you passing the lcdout 'commands'? i.e. lcdout $fe, 01 to clear the display and things like that?

If my guess is right, like me, you are basically replacing 'lcdout' with 'serout' on the main board, and this code is to read everything coming the serial port, and sending it out, character by character using a single 'lcdout'.

Hi Skimask,
That was the whole point of the endever, to use the standard commands common to lcdout, so as not to have several different codes to control how the lcd prints to screen. It seems most makers of these things have their own little routines, I started with:

serin N2400.PortB.7,char
lcdout char

I saw the core code in a post of Darrel's using Hserin
and knew it would work so I started cutting and sewing,
Darrel took it and added his instant interrupts, i snipped
out some more of the unneeded stuff and am still working
on all the bells and whistles. I like it better than all the
others I've seen, because it uses unmolested, lcdout type code.
JS

skimask
- 26th November 2006, 21:38
Hi Skimask,
That was the whole point of the .......................
things have their own little routines, I started with:

serin N2400.PortB.7,char
lcdout char

I saw the core code in a post of Darrel's.............
seen, because it uses unmolested, lcdout type code.
JS


I get what you're cooking...I hope :)
LCDOut is a familiar command, why mess with it? Replace it with SerOut, and you're done.
My master plan includes throwing a few buttons on the unit and using a 4 wire hookup (v+, gnd, tx, rx, maybe an RJ11 phone connector).
If my figuring is right, I'm going to throw in a bit of code that looks for a double $fe (or whatever) and that'll be my signal to send back a code if any keys are pressed. Using an equivalent to an LCDIn command might be a bit trickier (not by much), but that'll come later...

The only big thing left to do is to find a dozen or so LCDs with backlights. ebay maybe? :)
JDG

Archangel
- 26th November 2006, 22:40
I get what you're cooking...I hope :)
LCDOut is a familiar command, why mess with it? Replace it with SerOut, and you're done.
My master plan includes throwing a few buttons on the unit and using a 4 wire hookup (v+, gnd, tx, rx, maybe an RJ11 phone connector).
If my figuring is right, I'm going to throw in a bit of code that looks for a double $fe (or whatever) and that'll be my signal to send back a code if any keys are pressed. Using an equivalent to an LCDIn command might be a bit trickier (not by much), but that'll come later...

The only big thing left to do is to find a dozen or so LCDs with backlights. ebay maybe? :)
JDG
Hi skimask,
Yeah well partly, it is much easier to put a display in a difficult place if you only need to run 3 wires to it, whereas you may have 20 or so going to your main p/c board and it might be real inconveinient to run 20 to your display. I have bought LCD displays from sure electronics on ebay and thay are cheap. I did have one fail though, I think from ESD.
http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=7617627971
for larger order check his store: http://stores.ebay.com/Sure-Electronics

skimask
- 27th November 2006, 00:06
Hi skimask,
Yeah well partly, it is much easier to put a display in a difficult place if you only need to run 3 wires to it, whereas you may have 20 or so going to your main p/c board and it might be real inconveinient to run 20 to your display. I have bought LCD displays from sure electronics on ebay and thay are cheap. I did have one fail though, I think from ESD.
http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=7617627971
for larger order check his store: http://stores.ebay.com/Sure-Electronics


Ain't that the truth!
On every one of my little projects up until the last few, I've always had to design in a method for control and display, and always at the expense of pins, which could be better used for something else. So, on the last few, I built up a control/display module with 4 wires running to it using various LCDs/LEDs and switches/keypads laying around. For each different type of LCD, I have to modify the code to handle it, not to mention mount the thing up. I'm getting tired of that now also.
It's about time I'm making this standardized module, with a standard LCD, in a standard mount, with standard buttons, using a standard 'library' to run it, and connect it with a standard cable.

You want to go in and buy up a bunch of LCDs in bulk and save some $$$?

Archangel
- 27th November 2006, 10:05
You want to go in and buy up a bunch of LCDs in bulk and save some $$$? Sorry, no can do, I got a couple of extras right now ,no space, no bucks.
JS

skimask
- 28th November 2006, 01:17
Oh well...

Any other takers? 16x2 (or whatever, I'm up for ideas) LCDs in some sort of a quantity buy, split the savings amongst a few of us?

JDG

websmith
- 11th December 2006, 12:08
That code with interupts and all is pretty hot, but going back to the very first question all he wanted to do was emulate a serial LCD, ie PIC is doing nothing else. I knocked this up yesterday and it works, and doesn't miss anything, very simple - like me! Go on eat me alive!

A back space key tells pic next char is a command - see commands in the select case area
A double back space makes it spit out a pangram back at you.


DEFINE LCD_DREG PORTC 'DATA PORT
DEFINE LCD_DBIT 4 'STARTING BIT (0 OR 4)
DEFINE LCD_RSREG PORTC 'REGISTER SELECT PORT
DEFINE LCD_RSBIT 1 'REGISTER SELECT BIT
DEFINE LCD_RWREG PORTC 'READ/WRITE SELECT PORT
DEFINE LCD_RWBIT 2 'READ/WRITE SELECT BIT
DEFINE LCD_EREG PORTC 'ENABLE PORT
DEFINE LCD_EBIT 0 'ENABLE BIT
DEFINE LCD_BITS 4 'BUS SIZE (4 OR 8)
DEFINE LCD_LINES 2 'LINES IN DIPLAY
DEFINE LCD_COMMANDUS 2000 'CMD DELAY TIME IN uS
DEFINE LCD_DATAUS 50 'Data DELAY TIME IN uS
define Osc 4
'************************************************* ***********
ADCON1 = 7 'disable A/d work digital
TRISB = %00000000 'unused port b set to o/p
TRISA = %00000000 ' PortA outputs
TRISC = %00000000 ' PortC outputs
OPTION_REG.7 = 0 ' Enable PORTB pull-ups

'T2400 con 16780 '2400bd, driven, inverted, no parity
T2400 con 396 '2400bd, driven, true, no parity
'will need to use rs232 inverter
comsout var PORTA.0
comsin var PORTA.1
datarray var byte[1] 'incoming array on rs232
'************************************************* ***********
start:
Pause 500 ' Wait for LCD to startup
Lcdout $FE, $0C 'turn cursor off


Lcdout $fe, 1 ' Clear LCD screen
Lcdout $fe, 2 ' go home
Lcdout "GPL PIC System"
Lcdout $FE, $C0 'move cursor to begin of line 2
Lcdout "Serial in at ",DEC T2400

Pause 1000 ' Wait 1 second
Lcdout $fe, 1 ' Clear LCD screen
'************************************************* ***********
main: while 1 'forever loop
serin2 comsin, T2400, [ datarray[0]] 'get a char
if datarray[0] = 8 then 'next byte is a LCD command after BS received
serin2 comsin, T2400, [ datarray[0]]
select case datarray[0]
case 48 '0 = Clear LCD screen
Lcdout $fe, 1
case 49 '1 = move cursor to begin of line 1
Lcdout $fe, 2
case 50 '2 = move cursor to begin of line 2
Lcdout $fe, $C0
case 51 '3 = move cursor to begin of line 3
Lcdout $fe, $94
case 52 '4 = move cursor to begin of line 4
Lcdout $fe, $D4
case 8 'BS again so transmit a pangram
gosub send
case else 'do nothing
end select
else
Lcdout str datarray\1 'show 1 char to LCd
endif
wend

send: serout2 comsout,T2400,["How quickly daft jumping zebras vex",13,10]
return
'************************************************* ***********

END
'************************************************* ***********

Archangel
- 12th December 2006, 09:42
Go on eat me alive!


THERE ALWAYS MULTIPLE WAYS OF DOING ANYTHING. There is nothing wrong with brewing an alternative, I will study your code and learn something from it, therefore I am grateful for your post. Thank You, JS

nomad
- 21st October 2007, 02:09
hey joe! almost started singing that hendrix song. lol. Did you ever finish polishing off the bells and whistles? i'm a newbie and already tired of all the display wires, which keep getting pulled out of the breadboard! weeeeeeee

Archangel
- 21st October 2007, 02:25
hey joe! almost started singing that hendrix song. lol. Did you ever finish polishing off the bells and whistles?
Ya' Know, it works really well as is, after Darrel converted it to instant interrupts, and I have been doing everything but. What I intend to add is really just some unimportant fluff anyway, take the code off Darrel's post #16, it works quite well as is.
JS

flipper_md
- 13th October 2008, 04:02
Nice to find some code already made for serial LCD, I just burned the backpack on my cool Serial LCD :eek:

no prob, I had 4 LCDs waiting for me to drive them with a16F628

I just tried the code with INstant interupt, which took me an hour to setup the whole thing to compile(not bad actually), but now I see only stranges characters appearing on the LCD.

like I send "b" char, and the dipslay will do '

do I need to create a map of matching characters, or is there a tweak to get the correct display?

in attached picture, I've sent AAAAAAAAAAAAaaaaaaaaaa using the serial communicator from Mecanique,
it displayed ___________________000000000000000 on the LCD?


it's driven by a 16F628a, running at 20mhz
Display is 4x20 from Orient Display, saying it's requiring a S6A0069 and is compatible with HD44780 4/8bit.
http://character-lcd-lcds.shopeio.com/inventory/details.asp?id=939&cat=Lcds&sub=Character%20Lcd

I've blanked all define to run from default except for
DEFINE LCD_LINES 4
because I ain't know how to tweaks all the parameters.
Started to play with other defines but not luck yet.

maybe the answer is in there?

Archangel
- 13th October 2008, 10:13
Nice to find some code already made for serial LCD, I just burned the backpack on my cool Serial LCD :eek:

no prob, I had 4 LCDs waiting for me to drive them with a16F628

I just tried the code with INstant interupt, which took me an hour to setup the whole thing to compile(not bad actually), but now I see only stranges characters appearing on the LCD.

like I send "b" char, and the dipslay will do '

do I need to create a map of matching characters, or is there a tweak to get the correct display?

in attached picture, I've sent AAAAAAAAAAAAaaaaaaaaaa using the serial communicator from Mecanique,
it displayed ___________________000000000000000 on the LCD?


it's driven by a 16F628a, running at 20mhz
Display is 4x20 from Orient Display, saying it's requiring a S6A0069 and is compatible with HD44780 4/8bit.
http://character-lcd-lcds.shopeio.com/inventory/details.asp?id=939&cat=Lcds&sub=Character%20Lcd

I've blanked all define to run from default except for
DEFINE LCD_LINES 4
because I ain't know how to tweaks all the parameters.
Started to play with other defines but not luck yet.

maybe the answer is in there?You have to send the data true, if you send it inverted for some reason then invert it again with a transistor to get true. If you change the defines for the LCD this code will work with the PC boards sold by wulfden too.
here is a snippet to give you an idea of how to format your code
serout PortB.4,T9600,[254,128,"9600 baud line 1 T~"] '128 so as not to add space
serout PortB.4,T9600,[254,192,"9600 baud line 2~"]
pause 100

flipper_md
- 13th October 2008, 18:52
well, for some esoteric reasons the thing started to work by itself after a few restart... this I hate :p
I noticed one time i've got one capacitor disconnected on the Xtal... and it seems the PIC woulndt bother?? replugged it live and it kept working.


since I was sending data from a PC, I assume it was regular RS232.
Tried to get data from my PIC heartbeat system(which is using N9600) and as you said this format is not ok as is, text was garbaged. I'll need a max232 one day to invert signal.

In the little time I had to play with the thing, I wondered how I could send data to drive other functions, else than display text?
Can I do custom characters?
clear screen? etc

Another weird thing is that the LCD believe it's second line is the 3rd, when I send a long text. It start filling 1st, then 3rd, then 2nd, and finally 4th one?

anyways I was just sooooo happy to see some text scrolling :)


BUT, this morning it doesn't wan't to behave again, showing garbage text with the same steup! arg :/
I suspect power problem from my regulator, although it's rated for 1amp.
it's running way too hot when I plug the backlight of this 4lines monster. I guess this may cause some power problems.
Actually, this is what fried my other LCD! PLugged in too many things, the regulator busted and started shooting 10V or so...smoke show B]

for now I just keep doing short tests.

thanks for the infos!

flipper_md
- 14th October 2008, 07:00
hummm

some more testing led me to find that disconnecting the usual ground/Power capacitor can help the whole thing to work?!
Also switched to a new regulator but this haven't changed anything.

I couln't get back to have correct display yet. only garbage and ghosts...

I ran a quick test with regular LCDOUT prg and this do work ok. Even the Lines were accesibles in correct order.
I suspect USART sync problems, which I couldn't resolve in other projects :/
How come it is supposed to be the performant solution and 10times more buggy than the software Serin??

And now this thing wants to play PacMan with me!!:cool:
All the ghost appeared by themself!

http://www.flipperdesign.com/images/inky_pinky_lcd.jpg

Archangel
- 14th October 2008, 09:25
well, for some esoteric reasons the thing started to work by itself after a few restart... this I hate :p
I noticed one time i've got one capacitor disconnected on the Xtal... and it seems the PIC woulndt bother?? replugged it live and it kept working.


since I was sending data from a PC, I assume it was regular RS232.
Tried to get data from my PIC heartbeat system(which is using N9600) and as you said this format is not ok as is, text was garbaged. I'll need a max232 one day to invert signal.

In the little time I had to play with the thing, I wondered how I could send data to drive other functions, else than display text?
Can I do custom characters?
clear screen? etc

Another weird thing is that the LCD believe it's second line is the 3rd, when I send a long text. It start filling 1st, then 3rd, then 2nd, and finally 4th one?

anyways I was just sooooo happy to see some text scrolling :)


BUT, this morning it doesn't wan't to behave again, showing garbage text with the same steup! arg :/
I suspect power problem from my regulator, although it's rated for 1amp.
it's running way too hot when I plug the backlight of this 4lines monster. I guess this may cause some power problems.
Actually, this is what fried my other LCD! PLugged in too many things, the regulator busted and started shooting 10V or so...smoke show B]

for now I just keep doing short tests.

thanks for the infos!
Ok this thing is written to display with the same commands as used with LCDOUT, so line 1 is 2, line 2 is $C0 or 192, line 3 is $94 or 148, line 4 is $D4 or 212. The LCD we all use having 4 lines are really 2 lines cut in half and displayed as 4 with line 3 being the second half of line 1 and line 4 being the second half of line 2. Put a .01 &micro;F cap on the lcd power terminals. PC COM Port outputs serial data iinverted and must be flipped for use by MAX232 or even a lousey old transistor. Have you tried sending data from another PIC? Just to be sure which post in this thread are you using the code from ? should be post 16.
Oh it likes to boot up with the serial in pin in the HI state and herserin likes to Idle High as well. I have hooked this up to my computer with a max232 and sent large text files and not overrun the buffer, I say this because it did not go to buffer overrun and always ended with the ending text in the file, it went by WAY too fast to read. I think the little Ghosts are 60 hz due to open input on the PIC.

flipper_md
- 15th October 2008, 07:11
thanks Joe

I will have to try some more when some free time appears!

flipper_md
- 20th September 2009, 00:40
well,
f-i-n-a--l-l--y went back into this and made it work, but I think it was a bad component somewhere causing problem (my regulator used to run very hot, and now it's not warm at all!)
Oh mysteries

flipper_md
- 20th September 2009, 23:51
added some code into the Instant Interrupt version, to get control of HPWM for the backlight of the LCD. Running a 16F628A @ 20Mhz
Here is the *working* version ...so far

I made it to behave like my other LCDs, so to control the backlight it wants to see code like:
$14$FF 'full power
$14$00 'off

I also upped a little program that I use to test the LCD.
http://www.flipperdesign.com/FlipLCD_control.rar


getbuf: ' move the next character in buffer to bufchar
@ INT_DISABLE RX_INT

index_out = (index_out + 1) ' Increment index_out pointer (0 to 63)
' Reset pointer if outside of buffer
IF index_out > (buffer_size-1) Then index_out = 0
bufchar = buffer[index_out] ' Read buffer location

if skipLCDComm>0 then
skipLCDComm=skipLCDComm-1
endif
;Routine for buffering LCD commands
if (GrabBkLt=1) then
; WE have signal to watch for value for LCD backlight next
; LCDOut $FE,$94,"BACKLIGHT set:<",#bufchar,">" ; for debug only

HPWM 1,bufchar ,1250 ; Setting Pulse Mod to desired value
' Observe minimum FREQ for given OSC speed. 20Mhz is 1221Hz
' Next set bufchar to a null char, so I wont be seen/displayed
bufchar = 24
Low LedPort ; Debug only
GrabBkLt=0 ; All is done, signal to close the loop
;Re-Enable Int and go back up, to skip displaying this char
@ INT_ENABLE RX_INT
goto display
endif
;Following will trigger the routine up here on the next chr received
; but if skip if $fe has been called 2 shots ago
if (bufchar=20) and (skipLCDComm=0) then ; 14h, trigger for special LCD command
HIGH LedPort ; Debug only
GrabBkLt=1 ; Signal to get the value of backlight level
;Re-Enable Int and go back up, to skip displaying this char
@ INT_ENABLE RX_INT
goto display
endif
;Prevent value of 14h to be trapped for other command, we memorize previous call of $FE (254)
if bufchar=254 then
skipLCDComm=2 ;
endif

@ INT_ENABLE RX_INT
Return

Darrel Taylor
- 21st September 2009, 00:23
Ah ha, enhancements ... :)

Small problem though ...
getbuf: is a Subroutine.

Jumping out of a subroutine to the main loop with ...
goto displayis going to cause some stack problems.

Try using RETURN at each of those goto's.
<br>

flipper_md
- 21st September 2009, 01:59
oh! poor stack :)
I will look into options to do it another way.

stack seemed to survive so far. LOL

thanks for the tip Darrel

timseven
- 29th September 2009, 01:20
Darrel sir, I am new on this forum and also programming PICs. I was looking for exactly what you have done here. I wonder first if I could use your programming on a 16F628 pic second, on what pin of which port should I connect the input to that 16F628 that will drive the parallel LCD and third, where should I find the two include “DT_INTS-14.bas and the ReEnterPBP.bas programs that the pbp compiler is asking for. Sorry for these silly questions but I really would like to learn. Thanks.



>> You just learn a little slower after 50.

Oh No! I better hurry up and learn more, I've only got 3 years left. :)

>> ... with only 4 months of experience at this ...

Well, for only 4 months, you're doing pretty good.

>> ... how long have you been doing this? anyway

PicBasic Pro - about 5 years
Programming - Umm, one month after the first TRS-80 hit the market, I guess that makes it about oh 28 years.<hr>

I know DT_INTS looks intimidating at the begining, but it's really not that bad, and you don't need to learn assembly language to use it. But I can understand why you might not want to try it out. The biggest obstacle is that you have to be using MPASM.

So whenever you get around to DT_INTS, you can come back to this thread and try out this program.
It's your backpack program modified for Instant Interrupts.
I've highlighted most of the changes (red is added, blue is removed).
Tested it on a 16F877A
;---- Config settings for MPASM ----------------------------------------------
@ __config _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _LVP_OFF & _CP_OFF

trisb = %00000010
trisA = %11110011
;include "modedefs.bas"

;----Added by DT--------------------------------------------------------------
INCLUDE "DT_INTS-14.bas"
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler RX_INT, _serialin, PBP, no
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE RX_INT ; enable external (INT) interrupts
;-----------------------------------------------------------------------------

' Define LCD registers and bits
Define LCD_DREG PORTB
Define LCD_DBIT 4
Define LCD_RSREG PORTA
Define LCD_RSBIT 0
Define LCD_EREG PORTA
Define LCD_EBIT 1

DEFINE LCD_LINES 4 'Define using a 2 line LCD
DEFINE LCD_COMMANDUS 2000 'Define delay time between sending LCD commands
DEFINE LCD_DATAUS 50 'Define delay time between data sent.
DEFINE OSC 20

DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_SPBRG 32 ' FOR 20MHZ 129 = 2400, 32=9600,25 @ 4 for 2400
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty)
TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full)
LED VAR PORTA.4

OERR VAR RCSTA.1 ' Alias OERR (USART Overrun Error Flag)
CREN VAR RCSTA.4 ' Alias CREN (USART Continuous Receive Enable)
buffer_size CON 64 ' Sets the size of the ring buffer, set up from 32
buffer VAR BYTE[buffer_size]' Array variable for holding received characters
index_in VAR BYTE ' Pointer - next empty location in buffer
index_out VAR BYTE ' Pointer - location of oldest character in buffer
bufchar VAR BYTE ' Stores the character retrieved from the buffer
i VAR BYTE ' loop counter
Col VAR BYTE ' Stores location on LCD for text wrapping
errflag VAR BYTE ' Holds error flags
index_in = 0
index_out = 0
i = 0
col = 1

'RxData var byte
CMCON = 7 ' PORTA is digital
Pause 100 ' Wait for LCD to startup
high PortA.2 ' power for backlight
low PortA.3 ' backlight ground
;INTCON = %11000000 ' Enable interrupts
;ON INTERRUPT GoTo serialin ' Declare interrupt handler routine
;PIE1.5 = 1 ' Enable interrupt on USART
pause 1500
lcdout $FE,1
lcdout $FE,2
LCDOUT "Your Text Goes Here"
PAUSE 2000

' * * * * * * * * * * * * * Main program starts here - blink an LED at 1Hz
' I removed some code here, it seems to require what's left
loop:
For i = 0 to 10 ' Delay for .02 seconds (10*2mS)
Pause 2 ' Use a short pause within a loop
Next i ' instead of one long pause

For i = 0 to 10 ' Delay for .02 seconds (10*2mS)
Pause 2 ' Use a short pause within a loop
Next i ' instead of one long pause


display: ' dump the buffer to the LCD
IF errflag Then error ' Handle error if needed
IF index_in = index_out Then loop ' loop if nothing in buffer

GoSub getbuf ' Get a character from buffer
LCDOut bufchar ' Send the character to LCD


IF col > 20 Then ' Check for end of line
col = 1 ' Reset LCD location
LCDOut $fe,$c0,REP " "\20 ' Clear line-2 of LCD
LCDOut $FE,2 ' Tell LCD to return home
EndIF

GoTo display ' Check for more characters in buffer



' Subroutines

;Disable ' Don't check for interrupts in this section

getbuf: ' move the next character in buffer to bufchar
@ INT_DISABLE RX_INT
index_out = (index_out + 1) ' Increment index_out pointer (0 to 63)
' Reset pointer if outside of buffer
IF index_out > (buffer_size-1) Then index_out = 0
bufchar = buffer[index_out] ' Read buffer location
@ INT_ENABLE RX_INT
Return


error: ' Display error message if buffer has overrun
IF errflag.1 Then ' Determine the error
LCDOut $FE,$c0,"Clearing Display Buffer" ' Display buffer error on
' line-2 and 3 Buff overrun
Else
LCDOut $FE,$D4,"USART Overrun" ' Display usart error on line-4
EndIF

LCDOut $fe,2 ' Send the LCD cursor back to line-1 home
For i = 2 to col ' Loop for each column beyond 1
LCDOut $fe,$14 ' Move the cursor right to the right column
Next i ' $14 = 20 DEC.

errflag = 0 ' Reset the error flag
CREN = 0 ' Disable continuous receive to clear overrun flag
CREN = 1 ' Enable continuous receive

GoTo display ' Errors cleared, time to work.


' * * * * * * * * * * * * * * * Interrupt handler

serialin: ' Buffer the character received
IF OERR Then usart_error ' Check for USART errors
index_in = (index_in + 1) ' Increment index_in pointer (0 to 63)
IF index_in > (buffer_size-1) Then index_in = 0 'Reset pointer if outside of buffer
IF index_in = index_out Then buffer_error ' Check for buffer overrun
HSerin [buffer[index_in]] ' Read USART and store character to next empty location
IF RCIF Then serialin ' Check for another character while we're here
;resume
@ INT_RETURN ; Return to program

buffer_error:
errflag.1 = 1 ' Set the error flag for software
' Move pointer back to avoid corrupting the buffer. MIN insures that it ends up within the buffer.
index_in = (index_in - 1) MIN (buffer_size - 1)
HSerin [buffer[index_in]] ' Overwrite the last character stored (resets the interrupt flag)
usart_error:
errflag.0 = 1 ' Set the error flag for hardware
;resume
@ INT_RETURN ; Return to program


End

Hope you can use it some day,

timseven
- 29th September 2009, 23:50
I am new on this forum and also on programming PICs. I was looking for a program that helps me turn my parallel LCD into a serial. That’s what Mr. Darrel Taylor’s program does on “LCD Serial backpacks post #16. I wonder first if I could use his program on a 16F628 because the compiler doesn’t like it as is. Second, on what pin of which port should I connect the serial input on that 16F628 that will drive the parallel LCD. Sorry for these silly questions but I really would like to learn how to do that. Thanks.

Darrel Taylor
- 30th September 2009, 01:12
I am new on this forum and also on programming PICs. I was looking for a program that helps me turn my parallel LCD into a serial. That’s what Mr. Darrel Taylor’s program does on “LCD Serial backpacks post #16. I wonder first if I could use his program on a 16F628 because the compiler doesn’t like it as is. Second, on what pin of which port should I connect the serial input on that 16F628 that will drive the parallel LCD. Sorry for these silly questions but I really would like to learn how to do that. Thanks.
It'll work on a 628.
Check out this thread

Instant Interrupts - Revisited
http://www.picbasic.co.uk/forum/showthread.php?t=3251

The first post shows where to get the files.
And the rest of the thread will answer many questions.

hth,

timseven
- 30th September 2009, 04:11
Thank you sir.

timseven
- 30th September 2009, 22:52
Well, after I read a group of posts I started to understand what your interest of introducing these new interrupts was. I am not very familiar with interrupts but I want to take advantage of this new approach. First I did was to try to play with your Blink program and at compilation time (16F628) I got an error: “Variable wsave3 position request 416 beyond Ram_End 335” I have look every where for an explanation of this error with no luck. Please, advice.

Darrel Taylor
- 30th September 2009, 23:33
There is a section in the DT_INTS-14.bas file that has to be adjusted for the chip you are compiling for.
I wish I could make it automatic, but there's no way to do that.

For a 16F628, it doesn't have any General Purpose RAM in BANK3. So you have to comment out the wsave3 variable in this section.
wsave var byte $20 SYSTEM ' location for W if in bank0
;wsave var byte $70 SYSTEM ' alternate save location for W
' if using $70, comment out wsave1-3

' --- IF any of these three lines cause an error ?? ----------------------------
' Comment them out to fix the problem ----
' -- It depends on which Chip you are using, as to which variables are needed --
wsave1 var byte $A0 SYSTEM ' location for W if in bank1
wsave2 var byte $120 SYSTEM ' location for W if in bank2
;wsave3 var byte $1A0 SYSTEM ' location for W if in bank3
' ------------------------------------------------------------------------------


The 628 also has Access RAM at address $70 which can be accessed from any bank.
So commenting everything and uncommenting the $70 variable will work too.
Either way will work ... take your pick.

;wsave var byte $20 SYSTEM ' location for W if in bank0
wsave var byte $70 SYSTEM ' alternate save location for W
' if using $70, comment out wsave1-3

' --- IF any of these three lines cause an error ?? ----------------------------
' Comment them out to fix the problem ----
' -- It depends on which Chip you are using, as to which variables are needed --
;wsave1 var byte $A0 SYSTEM ' location for W if in bank1
;wsave2 var byte $120 SYSTEM ' location for W if in bank2
;wsave3 var byte $1A0 SYSTEM ' location for W if in bank3
' ------------------------------------------------------------------------------

timseven
- 30th September 2009, 23:54
I'll report to you. Thanks

timseven
- 1st October 2009, 01:23
Well, beautiful. I comment out the 3 wsaves and everything came out as planned. I tested the 628 on my breadboard and the led blinked as expected. After that triumph I load your Serialin (I called Parallel to Serial) program and compiled it. I got one error only
“Error [118] C:\program~1\mecanic~1\mcs\parallel~3 asm 200:Overwriting previous address contents(2007)” As always I try to find that error on the posts and I did but I don’t understand how to fix it. Thanks.

Darrel Taylor
- 1st October 2009, 02:01
I got one error only
“Error [118] C:\program~1\mecanic~1\mcs\parallel~3 asm 200:Overwriting previous address contents(2007)”

I think you've found just about every possible problem. :)

With the following advice from mister_e, I'm sure you'll reach the finish line.

http://www.picbasic.co.uk/forum/showthread.php?p=6775#post6775
<br>

timseven
- 1st October 2009, 04:15
I got it!!! It complied perfectly and now comes the hardware test. I’ll do the setup and let you know how it worked. I think the worse part is over. I thank you and indirectly to Melanie, Steve and many others that post their problems and solution in this forum. I want to learn all about these unique interrupts from the bottom up. I’ll be around here for some time. TimSeven

Darrel Taylor
- 1st October 2009, 04:23
Great, and don't forget Joe S.

It's his serial backpack program. :)
<br>

flipper_md
- 1st October 2009, 04:40
while it's alive..

Darrel, i've made changes as per your recommandation,
So, the skipchar label down here take care of characters not to be sent to LCD.
that works!


and then I had the *brilliant* idea to add something else...which failed.

I know we're, but not sure why.


Next I wanted to disable interrupt while I do my little LED dance at start, and send some message on the LCD.

It seems like the code will stop at > ; @ INT_ENABLE RX_INT; this seem buggy...

Do you see why I couldn't disable/enable INterrupts at start, or at that specific place?

I taught maybe i should put this in a sub routine?




; @ INT_DISABLE RX_INT ; Ignore input at initialisation

HIGH LedPort ' Some visual sign of life for the PIC
Pause 500
LOW LedPort
pause 50

lcdout $FE,1 'LCD INIT
lcdout $FE,2
LCDOUT "LCD SERIAL - READY"
PAUSE 300 ' Timeout for LCD to settle

; @ INT_ENABLE RX_INT ; this seem buggy...

' * * * * Main program starts here * * * * * * * *

loop:
For i = 0 to 10 ' Delay for .02 seconds (10*2mS)
Pause 2 ' Use a short pause within a loop
Next i ' instead of one long pause

For i = 0 to 10 ' Delay for .02 seconds (10*2mS)
Pause 2 ' Use a short pause within a loop
Next i ' instead of one long pause

skipachar: ; Will come back here if a char has to be skipped
skipchar=0 ; reset the flag so next char could be displayed

display: ' dump the buffer to the LCD
IF errflag Then error ' Handle error if needed
IF index_in = index_out Then
goto loop ' loop if nothing in buffer
endif

GoSub getbuf ' Get a character from buffer

if skipchar=1 then skipachar ; with goto up there, skipping display of the last read char

LCDOut bufchar ' Send the character to LCD

IF col > 20 Then ' Check for end of line
col = 1 ' Reset LCD location
LCDOut $fe,$c0,REP " "\20 ' Clear line-2 of LCD
LCDOut $FE,2 ' Tell LCD to return home
EndIF

if ShowRTC=1 then
LCDOut $FE,$D4,"RTC ACTIVED"
EndIF

GoTo display ' Check for more characters in buffer



' Subroutines

;Disable ' Don't check for interrupts in this section

getbuf: ' move the next character in buffer to bufchar
@ INT_DISABLE RX_INT

index_out = (index_out + 1) ' Increment index_out pointer (0 to 63)
' Reset pointer if outside of buffer
IF index_out > (buffer_size-1) Then index_out = 0
bufchar = buffer[index_out] ' Read buffer location

if skipLCDComm>0 then
skipLCDComm=skipLCDComm-1
endif
;Routine for buffering LCD commands
if (GrabBkLt=1) then
; WE have signal to watch for value for LCD backlight next
; LCDOut $FE,$94,"BACKLIGHT set:<",#bufchar,">" ; for debug only

HPWM 1,bufchar ,1250 ; Setting Pulse Mod to desired value
' Observe minimum FREQ for given OSC speed. 20Mhz is 1221Hz
Low LedPort ; Debug only
GrabBkLt=0 ; All is done, signal to close the loop
skipchar=1 ; to skip displaying this char in main loop
endif
;Following will trigger the routine up here on the next chr received
; but if skip if $fe has been called 2 shots ago
if (bufchar=20) and (skipLCDComm=0) then ; 14h, trigger for special LCD command
HIGH LedPort ; Debug only
GrabBkLt=1 ; Signal to get the value of backlight level
skipchar=1 ; ;to skip displaying this char in main loop
endif
;Prevent value of 14h to be trapped for other command, we memorize previous call of $FE (254)
if bufchar=254 then
skipLCDComm=2 ;
endif

@ INT_ENABLE RX_INT
Return

Darrel Taylor
- 1st October 2009, 10:29
flipper_MD,

Are you a doctor, cause I've got this pain in my ...
Oh ... you're probably a porpoise doctor :(

Ummm no, I don't really see a reason for problems disabling at that point.

The closest thing to a problem I can see is that the GrabBkLt command will take over 3ms to display the LCD data ... 2ms for the command and 20+ chars at 50us delay = 1ms.

3ms by itself shouldn't be a problem, and it should only happen infrequently, but it's the closest thing to a problem I can see at first glance.

What are the symptoms?

flipper_md
- 1st October 2009, 21:25
Apparently, It will lock the PIC from receiving commands, if external data is received before it enter the main loop.

Visually, It will flash the LED, show "LCD Serial - READY", but stop there and not respond.


may I suggest Dr Pepper ?
Sugar is food for the brain :)

timseven
- 1st October 2009, 23:48
Yes Mr. Taylor I can't forget Joe S. as this backpack originator, I am sorry.

Well, I am almost there. I had some lines modified to the program to adapt it to my hardware. I modified:
DEFINE LCD_LINES from 4 to 2. ‘My LCD is 2X20
DEFINE OSC from 20 TO 4 ‘My 628 is 4 Mhz
DEFINE HSER_SPBRG from 32 to 25 ‘My 628 is 4 Mhz
The rest is unchanged.
When I turned it on I got the “Your text goes here” message and then over it a second later I got “Clearing display buffer” error. It’s something else that I need to change on the program to prevent the buffer to overrun? Thanks.

Darrel Taylor
- 2nd October 2009, 01:18
Change TXSTA to ...
DEFINE HSER_TXSTA 24h

9600 baud at 4Mhz needs the BRGH bit set to 1 with SPBRG = 25.
<br>

timseven
- 2nd October 2009, 02:44
I did the change on “DEFINE HSER_TXSTA from 20H to 25H and tested with same error. I restored all the DEFINES back to its original values (DEFINE OSC 20, DEFINE HSER_TXSTA 20H, DEFINE HSER_SPBRG 32) and used this time a 628-20 Mhz chip. I got the same error “Cleaning Display Buffer”. Any suggestion?

Darrel Taylor
- 2nd October 2009, 03:06
Maybe it was just a typo, but TXSTA should have been changed to 24h, not 25h. But it probably wouldn't matter.

And when you say "and used this time a 628-20 Mhz chip"...
Do you mean that you used a 16F628 with a 20Mhz crystal and two 15-33pf capacitors?
<br>

flipper_md
- 2nd October 2009, 03:24
Tim,

are you sending data to the screen to see if the message will clear out?

I always see the clearing display message at start, but everything works fine when I send data (without my silly Disabled Interrupt trial..of course:cool:).

timseven
- 2nd October 2009, 03:43
Yes, was a typo I mean 24h. Yes, I used a 16F628-20 Mhz. I changed the crystal but not the caps, sorry. Mr. Flipper_ND, when I received the error I thought I shouldn’t go on, but I think that you got a point there, I’ll. First I’ll do the test with the two 15-33 pf caps in place and next test sending some data. I’ll report to both of you. Thanks.

timseven
- 2nd October 2009, 21:49
Let me report to both of you: I changed the caps and same error. I send the serial data and received it but unreadable and there is no clear screen neither. The program I am using reads as:
PAUSE 1000
SEROUT PORTB.1, 4, [254, 1] ‘Clear the screen
SEROUT PORTB.1, 4, [“ABCDE”]
END
I don’t know why but the PBP 2.50A compiler doesn’t accept
SEROUT PORTB.1, N2400, [254, 1]. (Bad Expression) doesn’t like the N2400. I don’t know if there is a distinction between the N2400 and the 4 alone.
I have spent hours investigating the hardware and the software for any error but find nothing bad. There may be a test program to check the backpack program.
BTW, To be able to write and compile this four lines “text sending serial program” I had to restore the 16F628 .INC file back to it’s original text. (Take the (;) out).
Any ideas of what may I doing wrong? Thanks.

Darrel Taylor
- 2nd October 2009, 22:04
The standard USART requires "TRUE" levels.
N2400 is "Inverted".

Use mode 0 (T2400).

And to use the N2400, T2400 T9600 etc.

INCLUDE "modedefs.bas"

timseven
- 3rd October 2009, 03:09
I did the Include "modedefs.bas" and also sent all kind of modes from 0 to 11 with different characters on the display but none of them good. What I thought would be the simplest trouble shooting became the hardest for me. I don’t know what to do next. Thanks

Darrel Taylor
- 3rd October 2009, 03:17
I don’t know what to do next.Me neither. :o
<br>

timseven
- 3rd October 2009, 04:16
Thank you any ways. I'll keep reading post about it and see what ideas comes up. Thanks to all of you. TimSeven.

flipper_md
- 3rd October 2009, 05:05
Hi Guys

I was having trouble the other days with serial stuff and Bruce(rentron) pointed me at using PIC to PIC for testing.
So I setted up a cute 12F683 running it's internal 8mhz osc (then you plug only Power+Ground, it's running), and have a little program sending:
- TRUE 9600 on one pin with serout,
- INVERTED 9600 on another with serout,
- and debug at 38400 on another one, constantly in a loop.
Validate that your computer can see the data(with a max232) and then you should be able to use it to feed directly a PIC.

um, let me grab that proggie

timseven
- 6th October 2009, 23:17
Hi, everything is working fine. I got the backpack working perfectly as I always wanted. I am very thankful mainly to Joe s. the promoter and secondly to Steve , Melanie and Mr. Darrel who perfected the program and gave me so much help. I apologize to all because to my bad English, I am from the Caribbean and English is my second language. This serial backpack will serve for my experimental board. I was using a parallel 2X20 but too many pins were required. Now I only need one pin. Thanks to all of you again. This forum, it's great place to learn !!!

Archangel
- 30th October 2009, 04:42
Stay Tuned for an update. I figured out how to give this multiple baud rate and still use the USART, I have to get a new ISP first though as I am not internet enabled at home right now.

flipper_md
- 15th November 2009, 04:43
ok, i'm tuned now. where to??? :D

I must say I did tried running at higher speed and from the experiments, I concluded that 19,2 kBaud was about the fastest I could run without troubles.
57K gave very odd results...

Archangel
- 30th December 2010, 05:51
Someone promoted this thread to an article. I promised some additions and if you go to the article I have posted the code for this backpack <b> with selectable baud rate</b> and it still employs the hardware USART. The article is here: http://www.picbasic.co.uk/forum/content.php?r=171-LCD-serial-backpacks