Blue April - RC6502 Project Space
Re: Blue April - RC6502 Project Space
Michael wrote:
Perhaps you could just use CB2 plus two port pins and bit-bang the driver and enjoy using the LCD 8-bit interface mode?
"The key is not to let the hardware sense any fear." - Radical Brad
Re: Blue April - RC6502 Project Space
I am still having some trouble with this. I wired it up like Garth's example:

And I can verify that the '595 is working, by replacing the LCD with some LEDs, and the delay loops are long enough that I can actually see the bytes changing. I suspect the problem might have to do with this:
From an old thread.
With the control signals on bits 0 and 1 of the SR, they appear instantly, along with the nibble of data, when I pulse the 595. I am thinking that I will have to do something like this, in order to send, say 00111100 to the LCD:
In other words, send 6 bytes per byte of data, along withe accompanying 16 clock delays for the SR. That seems like a fair bit of extra steps / delays; before I try it that way I want to make sure I have the concept right.
And I can verify that the '595 is working, by replacing the LCD with some LEDs, and the delay loops are long enough that I can actually see the bytes changing. I suspect the problem might have to do with this:
GARTHWILSON wrote:
Be sure to leave E down after every read or write, and only change the RS and R/W bits when E is down, and never at the same time with raising or lowering E.
With the control signals on bits 0 and 1 of the SR, they appear instantly, along with the nibble of data, when I pulse the 595. I am thinking that I will have to do something like this, in order to send, say 00111100 to the LCD:
Code: Select all
High nibble send:
0011 0000
| || |
+----++----+
0011 0001 <- Enable bit
| || |
+----++----+
0011 0000
| || |
+----++----+
Low nibble send:
1100 0000
| || |
+----++----+
1100 0001 <- Enable bit
| || |
+----++----+
1100 0000
| || |
+----++----+
"The key is not to let the hardware sense any fear." - Radical Brad
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Blue April - RC6502 Project Space
Paganini wrote:
I wired it up like Garth's example:

Quote:
In other words, send 6 bytes per byte of data, along withe accompanying 16 clock delays for the SR. That seems like a fair bit of extra steps / delays; before I try it that way I want to make sure I have the concept right.
Right. These displays have few enough characters though that it will still appear to be instant, which would not be the case if it were 132 columns of 43, 50, or 60 lines and you had to change it all at once!
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Blue April - RC6502 Project Space
GARTHWILSON wrote:
I guess I shouldn't have reduced it so much, losing some of the resolution and making it kind of hard to read. It's a scan of the page in the 3x5" loose-leaf ring binder quick-reference guide I keep on the workbench. It was not originally intended for anyone else's eyes.
Quote:
Right. These displays have few enough characters though that it will still appear to be instant, which would not be the case if it were 132 columns of 43, 50, or 60 lines and you had to change it all at once!
Quote:
16 clocks is only about four instructions' worth though, so the added delay to get there isn't much. Five NOPs might do it, six definitely would, or find an instruction with more cycles that doesn't do any damage, like rotate an unused RAM byte.
"The key is not to let the hardware sense any fear." - Radical Brad
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Blue April - RC6502 Project Space
Paganini wrote:
I made a subroutine called "wait_16." Leventhal says jsr is 6 clocks and rts is six clocks, so I just filled in two nops.
Code: Select all
STA SR
JSR <to an empty subroutine>
ORA #1
STA SRhttp://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Blue April - RC6502 Project Space
I did get it working using the VIA shift register... kindasorta. The shift register was working properly, latching data, etc., and the LCD would initialize, but not reliably. My particular one seems to be extra fussy about the timing loops - probably because it's a cheap Chinese knockoff. I decided to go back to using the the VIA's output port (but now in 4-bit mode) so I could check the busy flag. That's where it is now. I don't consider the serial excursion to be wasted time even though I ended up abandoning that path; I gained a good basic understanding of how to use the 6522's shift register; it seems like there are plenty of interesting things to do with it so that it's almost a waste only to use it to drive the LCD!
I do have a question about how the 'pla' instruction works though. Right now I'm doing:
To check the busy flag in bit 7. I wasn't sure if the cmp instruction is necessary; it looks like pla does set the N flag, but the (exceedingly confusing) diagram in Leventhal seemed to suggest that it does it based on the value of the SP (maybe to be used for testing for stack overflows and other such errors?), not the value pulled off the stack. So, I added the cmp just to be safe.
I do have a question about how the 'pla' instruction works though. Right now I'm doing:
Code: Select all
pla
cmp #$FF
bmi etc
"The key is not to let the hardware sense any fear." - Radical Brad
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Blue April - RC6502 Project Space
Paganini (do you play violin?), for reliable LCD initialization, be sure to write the function set three times, and if you can't poll the busy bit, wait the prescribed amount of time after each write. Both of these are shown in my sample code at http://wilsonminesco.com/6502primer/LCDcode.asm . Most instructions take 10 HD44780 controller clock cycles to process, except the "clear display" and "home cursor" instructions which take 410. The clock is typically in the range of 100-250kHz, which puts the time per cycle in the range of 4-10µs; so 10 cycles may be as long as 100µs, and 410 cycles may be as long as 4.1ms. You should wait at least 15ms after power-up before starting the initialization procedure. Observing these delays, I've never had any timing problems, regardless of LCD brand.
PLA's flag results do reflect the contents of what you pulled off the stack, not the contents of the stack pointer.
PLA's flag results do reflect the contents of what you pulled off the stack, not the contents of the stack pointer.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Blue April - RC6502 Project Space
GARTHWILSON wrote:
Paganini (do you play violin?)
GARTHWILSON wrote:
for reliable LCD initialization, be sure to write the function set three times, and if you can't poll the busy bit, wait the prescribed amount of time after each write. Both of these are shown in my sample code at http://wilsonminesco.com/6502primer/LCDcode.asm . Most instructions take 10 HD44780 controller clock cycles to process, except the "clear display" and "home cursor" instructions which take 410. The clock is typically in the range of 100-250kHz, which puts the time per cycle in the range of 4-10µs; so 10 cycles may be as long as 100µs, and 410 cycles may be as long as 4.1ms. You should wait at least 15ms after power-up before starting the initialization procedure. Observing these delays, I've never had any timing problems, regardless of LCD brand.
GARTHWILSON wrote:
PLA's flag results do reflect the contents of what you pulled off the stack, not the contents of the stack pointer.
"The key is not to let the hardware sense any fear." - Radical Brad
Fun with Delay Loops
I can now poll the LCD busy signal during normal operation, but I still need to observe the mandated delays during LCD initialization. The shortest delay I need is 100uS, which I calculate to be 400 clocks, since I'm running at 4Mhz.
I figured that 1ms is ten of those, so I made a parent subroutine that is basically the same idea, except with 10 iterations instead of 75:
I make that 4075 clocks, which is 1ms + an extra 18.75 uS, which is fine since we want "at least" 1 ms delay. I did exactly the same thing for 4ms (called DELAY_1ms 4 times) and for 40ms (calledDELAY_4ms 10 times). I will refrain from including them, since they are literally the same subroutines, copy/pasted with the labels and magic numbers changed. Each one picks up a few extra microseconds beyond spec from saving / restoring the X register, and so on. Again this seems fine, since we want "at least," and everything seems to be working.
HOWEVER.
Having four special purpose nested subroutines does not seem to me like an elegant solution to this problem. The roughly 50 bytes they occupy is not that big of a ROM cost, but since I've only got 28kb, I expect that things are going to get crowded as I keep adding features.
Since I have two index register that, in combination, can count up to $FFFF, I feel intuitively that I should be able to create one general purpose delay function that simply accepts a parameter telling it what to count to. The (one single page) section about delay loops in Leventhal does something like this, but it is hard-coded for 1Mhz, and the algebra he uses produces constants for faster clocks that are larger than what can be stored in a single byte. I have not tried too hard to invent this subroutine, because I bet that at some point in the last 50 years someone has already done it, and that someone here on these forums knows where to find it.
Code: Select all
; jsr DELAY_100us 6 clocks
DELAY_100us:
txa ; 2 clocks (392)
pha ; 3 clocks (389)
ldx #75 ; Magic number! 2 clocks (387)
delay100us:
dex ; 2 clocks per loop
bne delay100us ; + 3 clocks per loop = 5 clocks per loop * 75 = 375
pla ; 4 clocks (383)
tax ; 2 clocks (381)
rts ; 6 clocks (375
Code: Select all
; jsr DELAY_1ms ; 6 clocks
DELAY_1ms:
txa ; 2 clocks
pha ; 3 clocks
ldx #10 ; 2 clocks
delay1ms:
jsr DELAY_100us ; 400 clocks per loop
dex ; 2 clocks per loop
bne delay1ms ; + 3 clocks per loop = 405 clocks per loop * 10 = 4050
pla ; 4 clocks
tax ; 2 clocks
rts ; 6 clocks
HOWEVER.
Having four special purpose nested subroutines does not seem to me like an elegant solution to this problem. The roughly 50 bytes they occupy is not that big of a ROM cost, but since I've only got 28kb, I expect that things are going to get crowded as I keep adding features.
Since I have two index register that, in combination, can count up to $FFFF, I feel intuitively that I should be able to create one general purpose delay function that simply accepts a parameter telling it what to count to. The (one single page) section about delay loops in Leventhal does something like this, but it is hard-coded for 1Mhz, and the algebra he uses produces constants for faster clocks that are larger than what can be stored in a single byte. I have not tried too hard to invent this subroutine, because I bet that at some point in the last 50 years someone has already done it, and that someone here on these forums knows where to find it.
"The key is not to let the hardware sense any fear." - Radical Brad
Re: Fun with Delay Loops
Paganini wrote:
HOWEVER.
Having four special purpose nested subroutines does not seem to me like an elegant solution to this problem. The roughly 50 bytes they occupy is not that big of a ROM cost, but since I've only got 28kb, I expect that things are going to get crowded as I keep adding features.
Since I have two index register that, in combination, can count up to $FFFF, I feel intuitively that I should be able to create one general purpose delay function that simply accepts a parameter telling it what to count to. The (one single page) section about delay loops in Leventhal does something like this, but it is hard-coded for 1Mhz, and the algebra he uses produces constants for faster clocks that are larger than what can be stored in a single byte. I have not tried too hard to invent this subroutine, because I bet that at some point in the last 50 years someone has already done it, and that someone here on these forums knows where to find it.
Having four special purpose nested subroutines does not seem to me like an elegant solution to this problem. The roughly 50 bytes they occupy is not that big of a ROM cost, but since I've only got 28kb, I expect that things are going to get crowded as I keep adding features.
Since I have two index register that, in combination, can count up to $FFFF, I feel intuitively that I should be able to create one general purpose delay function that simply accepts a parameter telling it what to count to. The (one single page) section about delay loops in Leventhal does something like this, but it is hard-coded for 1Mhz, and the algebra he uses produces constants for faster clocks that are larger than what can be stored in a single byte. I have not tried too hard to invent this subroutine, because I bet that at some point in the last 50 years someone has already done it, and that someone here on these forums knows where to find it.
So for "at least" delays where you don't need to be precise, busy-waiting like this is probably not the best approach; but you could just use one index register like this to make an easy-to-use configurable delay similar to what you're already doing:
Code: Select all
LDX #4
JSR delay_Xms
...
.delay_Xms
JSR delay_1ms
DEX
BNE delay_Xms
RTS
Re: Blue April - RC6502 Project Space
(crossed in the post, but here we go anyway...)
Floobydust posted a delay routine here
viewtopic.php?p=29795#p29795
which could surely be adapted. You can use two nested loops easily enough, counting in X and Y, and you can add NOPs to the innermost loop for a coarse slowdown. You can even have three loops if you bring A into play.
There's also a topic
Delay routines
which might be of interest.
As George suggests, if you have a timer, you might well use that in preference. Although I think counting is conceptually simpler.
Floobydust posted a delay routine here
viewtopic.php?p=29795#p29795
which could surely be adapted. You can use two nested loops easily enough, counting in X and Y, and you can add NOPs to the innermost loop for a coarse slowdown. You can even have three loops if you bring A into play.
There's also a topic
Delay routines
which might be of interest.
As George suggests, if you have a timer, you might well use that in preference. Although I think counting is conceptually simpler.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Blue April - RC6502 Project Space
Paganini, I play cello, and Dr Jefyll and BigDumbDinosaur here play bass.
I see you have a TXA, PHA above, later followed by PLA, TAX. Are you limited to the NMOS instruction set? The CMOS 65c02 lets you push and pull X and Y directly, with PHX, PLX, PHY, and PLY. I summarized the differences at http://wilsonminesco.com/NMOS-CMOSdif/ . However, since you're not using X for actual indexing, you could leave X alone and just use A as the loop counter, again if you have a CMOS 65c02, using DEA (DEcrement Accumulator).
From the programming tips page of my 6502 primer:
The 15ms came from a quick-reference card I keep in my 3x5" QR ring binder on the workbench. It agrees with other things in a data sheet I have in the file cabinet, but I've always gone longer for that delay since it's on boot-up and waiting for example one-eighth of a second is not going to be significant. I guess the 1/8 second came from the fact that the first time we used this kind of LCDs at work, we had a 1/8-second delay for something else, so we just used it. So I never actually tried 15ms. Your 40 sure won't hurt anything.
I see you have a TXA, PHA above, later followed by PLA, TAX. Are you limited to the NMOS instruction set? The CMOS 65c02 lets you push and pull X and Y directly, with PHX, PLX, PHY, and PLY. I summarized the differences at http://wilsonminesco.com/NMOS-CMOSdif/ . However, since you're not using X for actual indexing, you could leave X alone and just use A as the loop counter, again if you have a CMOS 65c02, using DEA (DEcrement Accumulator).
Quote:
I'd like to share my delay loops code in the next post. It's working, but I want to make sure I haven't violated any best practices, and maybe it could be improved. Can't really make it run faster (hah!) but maybe I can make it smaller...
From the programming tips page of my 6502 primer:
- Need a slick delay? Take this one from Bruce Clark. The delay is 9*(256*A+Y)+8 cycles (plus 12 more for JSR & RTS if you make it a subroutine). This assumes that the BCS does not cross a page boundary.
He writes: "A and Y are the high and low bytes (respectively) of a 16-bit value; multiply that 16-bit value by 9, then add 8 and you get the cycle count. So the delay can range from 8 to 589832 cycles, with a resolution of 9 cycles. One of the nice things about this code is that it's easy to figure out what values to put in A and Y when you want a delay of, e.g. (approximately) 10000 cycles." Here's the same thing with my structure macros (the resulting machine code being identical):Code: Select all
loop: CPY #1 DEY SBC #0 BCS loop
There's more at http://6502org.wikidot.com/software-delay . In fact, that wiki, although not very big, has a lot of great resources for this kind of thing. Check out also the source code repository on 6502.org.Code: Select all
BEGIN CPY #1 DEY SBC #0 UNTIL_CARRY_CLEAR
Quote:
except it seems to need that first delay to be 40ms as described here rather than 15
The 15ms came from a quick-reference card I keep in my 3x5" QR ring binder on the workbench. It agrees with other things in a data sheet I have in the file cabinet, but I've always gone longer for that delay since it's on boot-up and waiting for example one-eighth of a second is not going to be significant. I guess the 1/8 second came from the fact that the first time we used this kind of LCDs at work, we had a 1/8-second delay for something else, so we just used it. So I never actually tried 15ms. Your 40 sure won't hurt anything.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
- BigDumbDinosaur
- Posts: 9426
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Blue April - RC6502 Project Space
Paganini wrote:
GARTHWILSON wrote:
Paganini (do you play violin?)
Me playing a violin (or a viola, for that matter) would be akin to a grizzly bear filleting a fish. I don't have the hands for it, so the closest I can get is to play a “violin on steroids,” which is my wife’s description of the double bass.
GARTHWILSON wrote:
Paganini, I play cello, and Dr Jefyll and BigDumbDinosaur here play bass.
Speaking of which, there is a video on U-Toobe of Jeff and his pal floating down a river on a boat while playing some tunes. Unfortunately, I don't seem to have the link to it. There aren't any videos of me floating down a river, but there is one of my jazz trio making like a garage band during COVID lockdown. It was our first try at playing “Laura,” the “first try” aspect being painfully audible at times.
Dunno if any video exists of Garth playing his ’cello.
x86? We ain't got no x86. We don't NEED no stinking x86!
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Blue April - RC6502 Project Space
BigDumbDinosaur wrote:
Me playing a violin (or a viola, for that matter) would be akin to a grizzly bear filleting a fish. I don't have the hands for it, so the closest I can get is to play a “violin on steroids,” which is my wife’s description of the double bass. 
Quote:
but there is one of my jazz trio making like a garage band
Quote:
Dunno if any video exists of Garth playing his ’cello.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Blue April - RC6502 Project Space
GARTHWILSON wrote:
Paganini, I play cello, and Dr Jefyll and BigDumbDinosaur here play bass.
GARTHWILSON wrote:
I see you have a TXA, PHA above, later followed by PLA, TAX. Are you limited to the NMOS instruction set?
BigDumbDinosaur wrote:
There aren't any videos of me floating down a river, but there is one of my jazz trio making like a garage band during COVID lockdown. It was our first try at playing “Laura,” the “first try” aspect being painfully audible at times.
Thanks everyone for all the material on delays. I like the idea of doing it with a timer, for not the least reason that I have no idea how those VIA timers work, and this seems like a good opportunity to learn. In the long term (once I get some basic I/O up and running on this thing) my plan for Blue April is to go through the XINU book and make a little multitasking OS. I will no doubt need those VIA timers to implement something resembling a RTC when I do that. I'll combine my subroutines into one of the snazzy seedable ones from up-thread first so I have a working backup.
"The key is not to let the hardware sense any fear." - Radical Brad