Full Version : Seiko-Epson G1216B1N000 Graphic LCD Drive (ASM)
avr >>ASSMBLER ROUTINES >>Seiko-Epson G1216B1N000 Graphic LCD Drive (ASM)


AVR_Admin- 04-28-2006
Circuit and firmware to support Seiko-Epson G1216B1N000 dot graphics display
by Dick Cappel

A serial interface and bias supply for the Seiko-Epson G1216N000 using an AT90S2313 because there just aren't enough applications examples for this display on the web.


I was looking for an LCD display that I could use to display waveforms on the workbench. The selection criteria for the display module itself was straight forward:

1. Dot graphic with sufficient resolution to display a simple waveform,
2. Available for fast delivery,
3. Have sufficient documentation available online to design with,
4. Be easy to interface to mechanically, electrically, and firmware wise, and
5. Have a low price.

The Seiko-Epson G1216B1N000 was selected, apparently meeting all criteria, but I was unable to get it to work until Jesper Hanse kindly sent me his driver for the driver for the display in his VAMPP4 TAMPP (Yet Another MP3 Player) and comparing his code with my code, I found some mistakes I had made.


Connected to the a waveform capture unit, displaying a 15 kHz square wave.I think the poor contrast has more to do with the digital camera's low light signal to noise ratio than the performance of the display.
The display is a pretty old transflective gray mode TN LCD design with ok, but not great contrast. Its contrast is better than the screen shot above. The display's saving grace is that appeared to meet all of the primary criteria. The code to drive it was complicated somewhat by the fact that the 8 bit interface appears as two 64x64 displays for the left and right hand sides, and since I was determined to control it with an AT90S2313, I was a pin short of being able to have separate select pins for the left and right displays, and so implemented a Right/Left control pin, which produced some artifacts in the display, and avoiding these made it necessary to carefully code around them.

More about the hardware:

The controller was implemented with an AT90S2313, but it could have been done with an AT90S1200 and a firmware UART simulation since code is pretty small and doesn't rely on the RAM or timers that an AT90S2313 provide. The hardware needs to drive the data and control lines of the Seiko-Epson module, supply an adjustable negative bias voltage and + 5 volts to the module, and provide inverting buffers for the RS-232 interface.

The inverting RS-232 takes its negative supply from the host. The negative supply could have come from the LCD bias circuit (see below) but the handy thing about this circuit was that its output swung negative when connected to my RS-422 computer and only swung down to a little above ground when it was driven by the CMOS I/O port in the host on the waveform capture circuit that I connected it to after debugging.

The negative bias supply was generated by making 5V peak-to-peak pulses and using them to drive a 5 stage half-wave voltage multiplier and regulating the output with an opamp. The half-wave doubler is terribly inefficient using diodes for switch such a low voltage as each doubling of the 5 volts lost nearly half of it in the diodes, but I have a lot of diodes and miniature capacitors and wanted to pass the power signal through a single 5 volt regulator to minimize the exposure of the internal circuitry to accidental hazardous voltages on the cable. A single chip switched capacitor power supply would have reduced the parts count quite a bit.

The reference for the adjustable negative bias supply is the regulated +5 volt supply. The PNP and NPN saturating switches can be 2N2907 and 2N2222. The 330 Ohm resistor from the base of the PNP to +5V is necessary because the NPN emitter follower in the NE555 output stage cannot pull the output high enough to assure the PNP will shut off when the output is high.

More about the firmware:
After reset, the screen is erased, a line is drawn from the upper-left corner to the middle of the bottom edge, then another from there to the upper-right corner, which looks similar to a large letter "V" spanning the display. This is a visual indication that the display and serial controller are up and running. Its default is ASCII input mode, in which commands and the locations of dots to be written are received in ASCII- real nice for debugging with a terminal. Communications are at 19200 baud, 1 stop bit, no parity. The display can be switched to binary mode input, and in this mode commands and x,y coordinates are received as binary values, which is not easy to test with a terminal, but takes only half the transmission time to write a dot on the screen.

The ASCII conversion takes place within the GetASCIIorBinary routine, which returns a binary value regardless of whether the display is in the binary or ASCII input mode. If in the ASCII input mode, it also ignores commas, allowing it to graph comma delimited spreadsheet files.

The Epson documentation refers to the long axis as the Y axis and the coordinate 0,0 as being the upper-left corner of the screen (the latter is conventional for graphics systems). The driver converts this such that the coordinates 0,0 corresponds to the lower-left corner and 127,63 corresponds to the upper-right corner, which conventional for graphing.

The bits in a received byte (whether received as two characters in ASCII mode or a single byte in byte mode) are used according to the following rules:

Bit 7, if set, indicates that the byte is a command to be interpreted as one of the instructions listed below.

Bit 6 is the most significant bit of the Y address or 0 if it is an X address.

Bit 5 through 0 are the lower 5 bits of the X and Y addresses.

Four commands are supported by the serial controller:

$80 Erase display and reset
$81 Switch to ASCII input mode

$82 Switch to Binary input mode

$83 Restart the controller


Because of the way the Seiko-Epson module's interface works, dots are written in 7 row by 1 column segments (like 1 dot wide characters), and the current firmware doesn't read the display's internal ram to add a dot to it, rather it just writes a new segment of 1x7 dots, so this display is limited to simple graphs.

Link to Site: http://cappels.org/dproj/sed/sed.htm

CODE

;HOME;*********************************
;2313 serial to Sekio Epson 1216 display panel interface program
;*********************************
 
.include "2313def.inc"    
 
 
;Driver for Seiko 1216 LCD display. 128 X 64, with separate drivers for left and right
;halves of the screen. See the specification and app. notes for Seiko G1216B1N000.
;  Here is how the AT90S2313 is connected to the display:
 
;Port B is connected to the 8 bit data input/ouput on the display.
;Port D, bits 0 and 1 are not available as the corresponding pins are used for the UART.
;  these bits should be written as zero.
;Port D, bit 2 is connected to the R/W input on the display. This is
;  more of a data direction and mode pin.
;  Actual writes are clocked by the Enable pin.
;Port D, bit 3 is conntected to the D/I (Data/Instruction) pin on the display.
;  Low signifies insturction on the data port.
;Port D, bit 4 is connected to the enable input on the display. Instructions and
;  data are clocked into the display on the negative edge.
;Port D, bit 5 is to the RESET input on the display. Low resets the display.
;Port D, bit 6 is connected to CS1 on the dispaly and to the input of an inverter,
;  the output of which, drives CS2. It is therefore a right side/left side
;  select signal. Low for left side, high for right side.
 
;I/O Pin assignment
.equ Enable   =$04
 
 
;Display control codes
.equ instructionleft  = $30
.equ instructionright = $70
.equ writedataleft  = $38
;.equ writedataright  = $78
;.equ readstatusleft  = $34
;.equ readstatusright  = $74
 
;Displays Instructions
.equ displayon  = $3F
;.equ displayoff  = $3E
.equ XtoZero   = $B8
.equ YtoZero   = $40
.equ Slinetozero  = $C0
 
 
 
;Flag bit assignments for reigster YH
;YH bit 0 if = 1 then in bindary mode for serial data, if 0, ASCII-HEX mode
;YH bit 1 if = 1 then adds dot without erasing 8 bits in column (read-modify-write; slow)
 
;UART clock parameters
.equ     clock = 4000000         ;clock frequency
.equ     baudrate = 19200         ;choose a baudrate
.equ     baudconstant = (clock/(16*baudrate))-1
 
 
;Register Assignments
 
.def temp   = r16
.def xtarget  = r17
.def ytarget  = r18
.def dispdata = r19
.def temp2  = r20
 
.def delayreg = r23
.def delay2  = r24
;.def inchar  = r25
;.def outchar  = r26
 
.org     $00
 
rjmp     reset           ;Reset handle
 
reset: rjmp     init     ;Start init.
 
init:    
 
 
ldi     temp,ramend;low(ramend)
out     spl,temp     ;Set the stack pointer
ldi     temp,baudconstant    
out     ubrr,temp     ;Load UART bard rate
sbi ucr,txen;enable UART xmit
sbi ucr,rxen;Enable UART receiver
 
ldi YH,$00 ;Clear all flags

rcall waitlongtime ;Allow dispay to come on.

 
ldi temp,$FF ;Issue reset.
rcall odd
ldi temp,$00
rcall opd

ldi temp,instructionleft;Address left half of display
rcall opd

ldi temp,$FF
rcall odb
ldi temp,displayon ;Turn left display half on.
rcall opb
rcall strobeE

ldi temp,SlinetoZero;Set left start line to zero.
rcall opb
rcall shortdelay
rcall strobeE
 

ldi temp,instructionright;Address right half of display.
rcall opd

ldi temp,$FF
rcall odb
ldi temp,displayon ;Turn right half on.
rcall opb
rcall strobeE

ldi temp,SlinetoZero;Set rightstart lien to zero.
rcall opb
rcall shortdelay
rcall strobeE
 
 
rcall erasedisplay ;Fill display with zeros (clear screen).
 
 

ldi xtarget,$00 ;Draw A "V" on the screen. uses each row and each column.
ldi ytarget,$00

moredots:
rcall WriteDotAtXY
inc xtarget
inc ytarget
cpi xtarget,63
brne moredots

moredotsT:
rcall WriteDotAtXY
dec xtarget
inc ytarget
cpi xtarget,$FF
brne moredotsT


 
defaultloop: ;*****Default loop****    
   ;Until a command is received, which is distinguished by the MSb (bit 7)
   ;being set hight, receive x value, then y value, then write a dot there,
   ;notify when the dot write is complete, and get another. When a command
   ;is received, to interpret it.
   
   ;Message format:
   ;bit 7: 1 if command.
   ;bit 6: msb of y address, or zero if x address
   ;bits 5 hrough 0 remaining bits of address
   
   ;Host should send x, then y, then wait for completion notification.
   ;IN THIS ROUTINE, THE AXES ARE CORRECTED. X IS THE HORIZONAL AXIS (VALUE 0..127)
   ;AND Y IS THE VERTICAL AXIS (VALUE 0..63).
   ;SENSE IS CORRECTED ALSO. O,O IS LEFT,BOTTOM
rcall GetASCIIorBinary;Get char and put into xtarget.
mov temp2,temp
andi temp2,$80  
brne ItsaCommand
andi temp,$7F
mov ytarget,temp

rcall GetASCIIorBinary;Get char and put into ytarget.
mov temp2,temp
andi temp2,$80  
brne ItsaCommand
andi temp,$3F
ldi temp2,$3F
sub temp2,temp
mov xtarget,temp2
; mov xtarget,temp
 
rcall WriteDotAtXY ;Write dot.
ldi temp,$2A ;Notify write is complete.
rcall emitchar
 
rjmp defaultloop
 
 
 
GetASCIIorBinary: ;Get byte value from host to temp. If YH bit 0 is set, gets binary
  ;from host. If YH bit 0 is set, then gets ASCII-HEX from host.
rcall recvchar
sbrc YH,0  
ret  ;Binary mode - return after first byte
 
cpi temp,$30
brmi GetASCIIorBinary;If comma, ignore and use next char instead
mov temp2,temp;Get second char and make binary. No error checking.
rcall recvchar

;If comma, out of sync - start receiving byte over
cpi temp,$30
brmi GetASCIIorBinary
 
sbrc temp2,6;convert high byte
subi temp2,$f7;if bit 6 is set, add $09
andi temp2,$0F
 
sbrc temp,6;convert low byte
subi temp,$f7;if bit 6 is set, add $09
andi temp,$0F
 
lsl temp2 ;combine them
lsl temp2
lsl temp2
lsl temp2    
or temp,temp2
ret






 ;convert ascii in inbyteh,inbytel to byte in inbytel


 
ItsaCommand:
cpi temp,$80 ;Command $80 erase display and reset
breq ClearAndReset
cpi temp,$81 ;Command $81 switch to ASCII mode
breq SwitchToAscii
cpi temp,$82 ;Command $82 switch to binary mode
breq SwitchToBinary
cpi temp,$83 ;Command $83 restart controller
brne drs1
rjmp init
drs1:
; cpi $84
; breq ?????

ldi temp,$21 ;Else, Nack command and reset
rcall emitchar ;Exclaimation mark is printable Nack
rjmp defaultloop
 
 
SwitchToAscii:
andi YH,$FE
rjmp defaultloop

SwitchtoBinary:
ori YH,$01
rjmp defaultloop
 
ClearAndReset:  ;Clear display and reset default interperetation loop (can be used to sycn)
rcall erasedisplay
rjmp AckAndReset
 
 
 
AckAndReset:
ldi temp,$2A ;Send asterisk, which is printable ack
rcall emitchar ;and go back to start of default loop.
rjmp defaultloop  
 
 
 
erasedisplay:  
ldi dispdata,$00
ldi xtarget,$00
anotherx:
ldi ytarget,$00
anothery:
rcall WriteByteAtXY
inc ytarget
cpi ytarget,128
brne anothery
inc xtarget
cpi xtarget,8
brne anotherx
ret

 
WriteDotAtXY: ;Write a dot at X Y location
 ;(0=<X=<63, 0=<Y=<127.
 ;Enter with X in xtarget and
 ;Y in ytarget (nothing to do with Y but pass it along.
push xtarget  ;Save xtarget on stack for later
push ytarget
andi xtarget,$3F
andi ytarget,$7F
mov temp,xtarget ;Make display data from 3 lsb of xtarget  
andi temp,$07
rcall bitpositiontoormask
mov dispdata,temp
   ;Make X page address from xtarget. Put in xtarget.
lsr xtarget
lsr xtarget
lsr xtarget
andi xtarget,$07
rcall WriteByteAtXY
pop ytarget
pop xtarget  
ret
 
 
WriteByteAtXY: ;Write 8 bits at X and Y locaton per data sheet
sbi portd,2  ;Put R/W on display in Read to
ldi temp,instructionleft;prevent ghost right write in column 1.
mov temp2,ytarget
andi temp2,$40
breq notrights
ldi temp,instructionright
notrights:
rcall opd
mov temp,xtarget
ldi temp2,XtoZero
add temp,temp2
rcall opb
rcall strobeE
mov temp,ytarget
andi temp,$3F
ldi temp2,YtoZero
add temp,temp2
rcall opb
rcall strobeE
notright:
sbi portd,3  ;Make this a data write.
rcall shortdelay
mov temp,dispdata
rcall  opb
rcall strobeE
ldi temp,$00 ;Prevent glitching starting line register
rcall opb
ret
 
 
odd:
out ddrd,temp
ret
 
opd:    
out portd,temp
rcall shortdelay
ret
 
odb:
out ddrb,temp
ret
opb:
out portb,temp
; rcall shortdelay
ret
 
 
strobeE:
; rcall shortdelay
cbi portd,4
rcall shortdelay
sbi portd,4
ret
 
 
bitpositiontoormask:;Convert bit position (0..7) to OR mask value
 ;Enter with bit position in temp, Exit with
 ;mask in temp
ldi temp2,$07
cp temp2,temp
brmi error  
ldi temp2,$01;Put 0000 0001 pattern into temp for shifting
rotatesomemore:
cpi temp,$00
breq finishedshifting
lsl temp2
dec temp
rjmp rotatesomemore
finishedshifting:
mov temp,temp2
ret
 
error: ;Report error - for now, just return.
ldi temp,$21 ;Else, Nack command and reset
rcall emitchar ;Exclaimation mark is printable Nack
ret
 
 
 
 
emitchar: ;Send byte in temp to terminal
sbis usr,udre;wait until the register is cleared
rjmp emitchar    
out udr,temp;send the byte
ret  ;go back

 
   
 
recvchar:     ;Receive a byte from the terminal and put into temp        
sbis usr,rxc ;Wait for byte to be received
rjmp  recvchar
in temp,udr;Read byte
ret  
 
 
 
shortdelay:
ldi delayreg,$04
delaymore:
dec delayreg
brne delaymore
ret
 
 
longdelay:
ldi delayreg,$00
ldi delay2,$00
delaymore2:
dec delayreg
brne delaymore2
dec delay2
brne delaymore2
ret

waitlongtime:
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
rcall longdelay
ret
 



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.