We're already familiar with these chips, from our multiple servo controller board from back in May.
The idea is to store strings of text in these chips, then simply set a pointer (to tell the PIC where to start reading from) and get the microcontroller to read the text back and display it on the LCD.
We did look at I2C and other serial eeprom alternatives (at �1.20 each these Atmel chips are quite expensive for eeprom and at 4Mbit, are much bigger than we're ever going to need!) but most other (non-Flash) chips run at 100kz, or 400khz at best (yes, that's kilohertz, not Mhz). This will obviously make drawing text on the LCD run really slowly which is something we're keen to avoid.
These little Atmels can work up to 20Mhz. Which by happy coincidence is how fast the master chip will be running anyway, so hopefully we won't lose too much time reading and displaying text to the screen.
We wired our Flash eeprom chip up to PORTD on an 18F4550 (using RD.0-RD.3) and hacked some code together to read and write data to/from the chip. Amazingly, it worked first time!
AllDigital
Config PORTC = Output
Config PORTD = Output
Config PORTD.2 = Input
configuration:
Symbol enablepin = PORTC.0
Symbol clockpin = PORTC.1
Symbol datapin = PORTC.2
declarations:
Dim tmp As Byte
Dim i As Byte
Dim lcdi As Byte
Dim lcdbyte As Byte
Dim lcdbytetosend As Byte
Dim rs As Bit
Dim flag As Byte
Dim mask As Byte
Dim pageaddr As Word
Dim byteaddr As Byte
Dim byteswritten As Word
Dim bytesread As Word
Dim streamwrite As Bit
Dim streamread As Bit
init:
WaitMs 200
Define SPI_CS_REG = PORTD
Define SPI_CS_BIT = 0
Define SPI_SCK_REG = PORTD
Define SPI_SCK_BIT = 1
Define SPI_SDI_REG = PORTD
Define SPI_SDI_BIT = 2
Define SPI_SDO_REG = PORTD
Define SPI_SDO_BIT = 3
SPIPrepare
Gosub initialiselcd
Gosub initialiseeeprom
pageaddr = 1
byteaddr = 0
Gosub readanddisplaydata
loop:
pageaddr = 1
Gosub readanddisplaydata
WaitMs 4000
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
byteaddr = byteaddr + 16
If byteaddr > 60 Then byteaddr = 0
WaitMs 1000
Goto loop
End
writelcdnibble:
Low enablepin
Low clockpin
If rs = 1 Then High datapin Else Low datapin
Gosub toggleclockpin
'shift in 4 bits
mask = 8
For lcdi = 1 To 4
flag = lcdbyte And mask
If flag = 0 Then Low datapin Else High datapin
Gosub toggleclockpin
mask = ShiftRight(mask, 1)
Next lcdi
'now strobe the clock one more time because ST+SC are tied
Gosub toggleclockpin
'toggle the enable pin to "flush" the data into the lcd
Low datapin
High enablepin
Low enablepin
Return
toggleclockpin:
'toggle the clock pin
High clockpin
Low clockpin
Return
writelcddata:
rs = 1
Gosub senddatatolcd
Return
writelcdcommand:
rs = 0
Gosub senddatatolcd
Return
senddatatolcd:
lcdbyte = ShiftRight(lcdbytetosend, 4)
Gosub writelcdnibble
lcdbyte = lcdbytetosend And 15
Gosub writelcdnibble
Return
initialiselcd:
For i = 1 To 3
WaitMs 50
lcdbytetosend = 0x20
Gosub writelcdcommand
Next i
WaitMs 50
lcdbytetosend = 0x28 '4 bits, 2 lines, 5x7 font
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x0c 'display on, no cursors
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x06 'entry mode auto-increment
Gosub writelcdcommand
WaitMs 50
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
'send a space character to the display to test
WaitMs 50
lcdbytetosend = 32
Gosub writelcddata
Return
initialiseeeprom:
Gosub set256pagesize
Gosub chiperase
pageaddr = 1
byteaddr = 0
WaitMs 100
Gosub startstreamwrite
For i = 0 To 63
tmp = LookUp("Blood Bowl Griff Oberwald Varag Ghoulchew The Mighty Zug "), i
SPISend tmp
Next i
Gosub endstreamwrite
Return
startstreamread:
streamread = 1
SPICSOn
SPISend 0xe8 'stream read (legacy mode)
SPISend pageaddr.HB
SPISend pageaddr.LB
SPISend byteaddr
SPISend 0x00 'four don't care bytes
SPISend 0x00
SPISend 0x00
SPISend 0x00
bytesread = 0
Return
endstreamread:
SPICSOff
streamread = 0
Return
startstreamwrite:
SPICSOff
SPICSOn
SPISend 0x82 '0x82 'write THROUGH buffer1 command
SPISend pageaddr.HB '5 don't care bits + 11 address bits
SPISend pageaddr.LB 'is the same as sending page address as hb/lb
SPISend byteaddr 'last eight bits are buffer start byte
byteswritten = 0
streamwrite = 1
WaitMs 5
Return
endstreamwrite:
SPICSOff 'this causes the flash buffer to automatically get written to memory
WaitMs 5
streamwrite = 0
Return
set256pagesize:
SPICSOn
SPISend 0x3d
SPISend 0x2a
SPISend 0x80
SPISend 0xa6
SPICSOff
Return
chiperase:
SPICSOn
SPISend 0xc7
SPISend 0x94
SPISend 0x80
SPISend 0x9a
SPICSOff
WaitMs 100
Return
readanddisplaydata:
lcdbytetosend = 0x01 'clear screen
Gosub writelcdcommand
Gosub startstreamread
For i = 1 To 16
SPIReceive lcdbytetosend
'for testing
tmp = byteaddr + i
Write tmp, lcdbytetosend
Gosub writelcddata
Next i
Gosub endstreamread
Return
Note that in the initialiseeeprom routine we actually blank the Flash chip and write some data to it. In the final version of this code, we'll transfer data to Flash eeprom via a USB connection, but read it back just the same. Although this is just a basic test, it proves the idea of us storing character/player information in eeprom and calling it up and displaying it on a character-based LCD. All with just a few extra wires from the master microcontroller.
[photo or video goes here]
Note that in this example we're using a rather tiny 2x16 character LCD (because we had some hanging around). We've got our fingers crossed that Santa will bring some larger 4x20 displays, like the one below which uses the same Hitachi 44780 controller chip, so the code should work for both.
With four lines of twenty characters, we can split player names over two lines (to allow really long forenames/surnames) and write player stats (MA, ST, AG, AV) on a single line - each stat (0-9) would take up four characters (XX-digit-space) so the output could look something like
GRIFF
OBERWALD
MA4 ST5 AG8 AV9
OBERWALD
MA4 ST5 AG8 AV9
Or, if we can get the player's name on a single line, something like:
GRIFF OBERWALD
MA ST AG AV
4 5 8 9
MA ST AG AV
4 5 8 9
No comments:
Post a Comment