
Code to drive an LCD and a serial routine so that serial data can be displayed.
;**************************************************************************
; LC001.ASM
;
; PROGRAM: Simple LCD project
;
; DESCRIPTION:
;
; AUTHOR: Douglas Rice
; Copyright 2000
;
; Crystal: 4MHz
;
; I/O used:-
;
; ; Port B is used for the LCD
;
INCLUDE "p16F84.inc"
;
;**************************************************************************
LIST P=16F84, R=DEC
__idlocs 0x1234
__config _XT_OSC&_PWRTE_ON & _WDT_OFF
; NOEXPAND
cblock 0x0c
endc
;--------------------------------------------------------------------------
; Sec 1. Equates and Constants
;--------------------------------------------------------------------------
; The General Purpose Registers start at the end of the
; Special Purpose Registers.
; IPMentState values
; in normal running or in time setting modes
;
; DoTimeSlice bits
; these bits are set to schedule a timer chain event
DTsS4event EQU 0 ;
DTsSevent EQU 1
DTsMevent EQU 2
DTSTriggered EQU 3 ; a capture should take place
DTsTurnOff EQU 4
DTsMeasFreq EQU 5
DTsDispFreq EQU 6
DTsDispCount EQU 7
; IPtrigMenu
DTSWaitForEdge EQU 0 ; if set, then wait for 0 to 1 edge on PA0
DTSSingle EQU 1
; IPtrigMenu
DTSFast EQU 0
;--------------------------------------------------------------------------
; Sec 1.1 Button and LED
;--------------------------------------------------------------------------
BUTTON_RS232 EQU 0 ; EDG - Bottom Buttom
BUTTON_DOWN EQU 6 ; EDG - Bottom Buttom
BUTTON_UP EQU 7 ; TRIG - Middle Button
LCDnumSamples EQU 40
; PORTA binary values
;--------------------------------------------------------------------------
; Sec 1.2 Button and LED
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; Sec 2.0 Variables
;--------------------------------------------------------------------------
; Variables start 0x0C
;
; Variables for FlashLED ( FL ) process
;
; DoTimeSlice Bits, to schedule, set bit
cblock
DoTimeSlice
IPnew
IPlast
IPbuttonEvent
IPnewFast
IPlastFast
IPbuttonEventUp
IPtrigMenu
LCDAnalSpeed
LCDcnt3
LCDgetCharFlag
LCDbase
LCDbaseCnt
CLtmr4sec
RSloopCnt
RSdata
RSdell
endc
; *********** I/O EQUATES **************
PORTA EQU 5 ; 5 BITS
PA0 EQU 0
PA1 EQU 1
PA2 EQU 2
PA3 EQU 3
PA4 EQU 4
PORTB EQU 6
PB0 EQU 0 ; Serial In
PB1 EQU 1
PB2 EQU 2
PB3 EQU 3
PB4 EQU 4
PB5 EQU 5
PB6 EQU 6
PB7 EQU 7
RS232tx EQU PA0 ; Serial Out
RS232rx EQU PB0 ; Serial In
buildLCD_HD44780
TEST_STRADDLE MACRO START
if high( $ ) != high( START )
Error "Table straddles Page Boundary " + Start
endif
endm
;--------------------------------------------------------------------------
; Sec 3. Program Code
;--------------------------------------------------------------------------
ORG 0
GOTO Start
ORG 4
RETFIE
GOTO Intrtn
;--------------------------------------------------------------------------
; Sec 3.1 Main Program Init Code
;--------------------------------------------------------------------------
Start
CALL LCDdelaylong
CALL LCDdelaylong
CALL LCDdelaylong
; Enable Interupts
MOVLW H'00'
MOVWF INTCON
; Set up PortB:7 as output.
BSF STATUS, RP0
MOVLW 0XF0
MOVWF TRISB
MOVLW 0xFF ; Make PORTA 3:0 INPUTS.
MOVWF TRISA
BCF STATUS, RP0
CLRF DoTimeSlice
; Change Prescaler
CLRWDT
; Configure Tmr 0
BSF STATUS,RP0
; Set up prescaller for 8192 / 16 = 512 ticks perseconds.
MOVLW 0x0 + 2 ; For Tmr0 0=/2, 1=/4, 2=/8,3=/16
MOVWF OPTION_REG
BCF STATUS,RP0
CALL LCDstart
MOVLW LCDCurLeftLower
CALL LCDwrtCmd
CLRF LCDbase
CLRF IPbuttonEvent
CLRF IPbuttonEventUp
GOTO MainLoop
;--------------------------------------------------------------------------
; Sec 3.2 Main Program
;--------------------------------------------------------------------------
MainLoop
; Enable Interupts
; Disable Interupts
MLdisableInt
CALL CLtimeslice
CALL IPtimesliceFast
; test for rising edge
BTFSC IPbuttonEventUp,BUTTON_RS232 ; RS232 input start
CALL IPrs232
; test for button presses
BTFSC IPbuttonEvent,BUTTON_UP ; On BUTTON_RATE Press
CALL IPupPressed
BTFSC IPbuttonEvent,BUTTON_DOWN ; On BUTTON_RATE Press
CALL IPdownPressed
GOTO MainLoop
;--------------------------------------------------------------------------
; Sec 3.3 Jump Table for running or time setting mode
;--------------------------------------------------------------------------
LCDInit
; We run this from the toggle state and
; Prevent update of time display on second ticks.
RETURN
include "lcd4mhz.inc"
; the code below must be kept together.
LCDgetByte
; we should have set up PCLATH
; and reset LCDgetCharFlag
; BCF LCDPortB,LCDgetCharFlag
MOVLW high $
MOVWF PCLATH
MOVFW LCDstrPtr;
; INCF LCDstrPtr,f
; ADDWF PCL,f
MOVWF PCL
LCDstrs
LCDstrLFast ;equ $ - LCDstrs
DT "del"
GOTO LCDgetByteEnd2 ; now print out 4 blanks
LCDstrLCont ;equ $ - LCDstrs
DT "C "
GOTO LCDgetByteEnd1
LCDstrLContEdge ;equ $ - LCDstrs
DT "C_- "
GOTO LCDgetByteEnd1
LCDstrLSingle ;equ $ - LCDstrs
DT "S "
GOTO LCDgetByteEnd1
LCDstrLSingleEdge ;equ $ - LCDstrs
DT "S_- "
GOTO LCDgetByteEnd1
LCDstrLFreq ;equ $ - LCDstrs
DT "Freq"
GOTO LCDgetByteEnd1
LCDstrLTime ;equ $ - LCDstrs
DT "Time LCD001.asm"
GOTO LCDgetByteEnd1
LCDLastStr
TEST_STRADDLE LCDgetByte
; Jump into these to select how many spaces printed
; at the end, so that 9 chars are printed.
LCDgetByteEnd0
DECF LCDeraseCnt,f
LCDgetByteEnd1
DECF LCDeraseCnt,f
LCDgetByteEnd2
DECF LCDeraseCnt,f
LCDgetByteEnd3
DECF LCDeraseCnt,f
LCDgetByteEnd4
DECF LCDeraseCnt,f
LCDgetByteEnd5
DECF LCDeraseCnt,f
LCDgetByteEnd6
BSF LCDPortB,LCDgetCharFlag
CLRF LCDstrPtr
DECFSZ LCDstrPtr,f
NOP
RETURN
;--------------------------------------------------------------------------
; Sec 4. Subroutines, procedures and functions
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; Sec 4.1 Button Poll Routine
;--------------------------------------------------------------------------
IPtimeslice
; --_____ button press
; ----___
; __----- /IPnew
; ----___ IPlast
; __--___
;
;
;
; This reads all Port B inputs and looks for Press
MOVFW IPnew
MOVWF IPlast
MOVFW PORTB
MOVWF IPnew
; IP last contains new setting, IPlast contains previous
; look for falling edges
COMF IPnew,W
ANDWF IPlast,W
; now force IPbuttonEvent bits to high for new pressed button
; the service routine should reset the bit to clear the event.
IORWF IPbuttonEvent,F
RETURN
IPtimesliceFast
; Look for rising edges
MOVFW IPnewFast
MOVWF IPlastFast
MOVFW PORTB
MOVWF IPnewFast
COMF IPlastFast,W
ANDWF IPnewFast,W
IORWF IPbuttonEventUp,F
RETURN
;--------------------------------------------------------------------------
; Sec 4.2
;--------------------------------------------------------------------------
IPupPressed
BCF IPbuttonEvent,BUTTON_UP
MOVLW LCDCurLeftLower
CALL LCDwrtCmd
MOVLW 0x10
MOVWF LCDbaseCnt
IPupPressed1
MOVFW LCDbase
CALL LCDwrtChar
INCF LCDbase,f
DECFSZ LCDbaseCnt
GOTO IPupPressed1
MOVLW LCDCurLeftLower
CALL LCDwrtCmd
return
IPdownPressed
BCF IPbuttonEvent,BUTTON_DOWN
MOVLW LCDCurLeftLower
CALL LCDwrtCmd
MOVLW 0x10
MOVWF LCDbaseCnt
IPdownPressed1
MOVFW LCDbase
CALL LCDwrtChar
DECF LCDbase,f
DECFSZ LCDbaseCnt
GOTO IPdownPressed1
MOVLW LCDCurLeftLower
CALL LCDwrtCmd
return
IPrs232
BCF IPbuttonEventUp,BUTTON_RS232
GOTO RS232in
;--------------------------------------------------------------------------
; Sec 4.3 Clock Chain Routine
;--------------------------------------------------------------------------
CLtimeslice
;
BTFSS INTCON,T0IF
RETURN
; TMR0 timeout
BCF INTCON,T0IF
BSF DoTimeSlice,DTsS4event
CALL IPtimeslice
RETURN
;--------------------------------------------------------------------------
; Sec 4.6 Event Handler Routine - Buttons
;--------------------------------------------------------------------------
; come here and combine the current state and the current event to index into
; the state jump table.
;
IPtrigMenuJT
MOVLW high $
MOVWF PCLATH
MOVFW IPtrigMenu
ANDLW 0x03
ADDWF PCL,f
; set choice State Table - limited to 2 states and two events
RETLW LCDstrLCont
RETLW LCDstrLContEdge
RETLW LCDstrLSingle
RETLW LCDstrLSingleEdge
TEST_STRADDLE IPtrigMenuJT
DTSTriggered EQU 3 ; a capture should take place
DTsTurnOff EQU 4
DTsMeasFreq EQU 5
DTsDispFreq EQU 6
DTsDispCount EQU 7
;--------------------------------------------------------------------------
; Sec 4.7 Serial Input Routine
;--------------------------------------------------------------------------
;**************************************************
RS232in
; spin for a start bit
; CLRWDT
; BTFSS PORTB,RS232rx
; GOTO RS232in
CALL Delay6
CALL Delay5
movlw 8
movwf RSloopCnt
RS232inL0
; BTFSC PORTB,RS232rx
; GOTO RS232inL1
; BSF STATUS,C
; GOTO RS232inL2
;RS232inL1 BCF STATUS,C
;RS232inL2 RRF RSdata,F
MOVFW PORTB
ANDLW 1<< RS232rx ; mask off bit
ADDLW -1<< RS232rx ; use ripple carry to move into C
RRF RSdata,F
CALL Delay5
DECFSZ RSloopCnt,f
goto RS232inL0
; test for Stop bit
COMF RSdata,f
MOVFW RSdata
ADDLW -0x0D
SKPNZ
GOTO RSfoundCR
ADDLW 0x0D
CALL LCDwrtChar
RETURN
RSfoundCR
MOVLW LCDCurLeftLower
CALL LCDwrtCmd
RETURN
Delay5
; RETURN
; NOP
NOP
MOVLW 0x1E
MOVWF RSdell
Delay51 DECFSZ RSdell ; 1
GOTO Delay51 ; 2 clk
CLRWDT
RETURN
;***************
; Delay 0x0F * 3 ticks of 4Mhz ~= 45us
Delay6
; RETURN
; MOVLW 0x0F
MOVLW 0x08 ; shorten delay as edge detector takes about 22 us
MOVWF RSdell
Delay61 DECFSZ RSdell
GOTO Delay61
CLRWDT
RETURN
;--------------------------------------------------------------------------
; Sec 5.0 Interrupt Routines
;--------------------------------------------------------------------------
Intrtn
; Which Interupt ?
; No Context Save in these routines.
; BTFSC INTCON,2
; GOTO IntTmr0
; BTFSC INTCON,1
; GOTO Intfint
; BTFSC INTCON,0
; GOTO IntRbport
IntTmr0
; BCF INTCON,2
RETFIE
Intfint
; BCF INTCON,1
; RETFIE
IntRbport
; BCF INTCON,0
RETFIE
;--------------------------------------------------------------------------
; Program End
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; EEPROM data
;--------------------------------------------------------------------------
ORG 0x2100
; first 2 on and off are general ones
DE 0x24,0x00 ; 4
cblock
LastVar
endc
END
;**************************************************************************
;
;
; LCD4MHZ.inc LCD code to drive an epson SED1200 ( 32Khz clk ) or Hitachi HD44780 ( 4Mhz clk)
;
; Description: Drives EPSON EA-C20017AR based upon Epson
; SED1200F if buildLCDsed1200 defined
;
; Drives Hitachi HD44780 based Modules if if buildLCD_hd44780 defined
;
; Common Procedures:-
; LCDwrtStr - display a String into 10 byte window starting at 0x80.
; LCDdispByte - display byte as two hex nibbles
; LCDwrtChar - write Char to module
; LCDwrtCmd - write CMD to module
;
; Cursor addres 0x80 is line 1 on both modules
; Cursor addres 0xC0 is line 2 on both modules.
;
; On SED1200 line 1 is left 10 Chars
; On SED1200 line 2 is Right10 Chars
;
; Treat the two sides separately, as two lines
;
; On HD557840 line 1 is top line
; On HD557840 line 2 is bottom line
;
; LCDstart - Initilizes Module
;
;Define one of these to select the module in main file.
;
; buildLCDsed1200
; buildLCD_HD44780
;
;
; Author: Doug Rice
;
;
;
;
;**************************************************************************
;--------------------------------------------------------------------------
; Sec 3.3 LCD routines stuff
;--------------------------------------------------------------------------
cblock
LCDtemp ;
LCDcnt ;
LCDnibble ;
LCDPortB ; image of port B for unused bits
LCDeraseCnt ;
LCDstrPtr ;
endc
;--------------------------------------------------------------------------
; Sec 3.3.4.2 LCD procedures LCD string write displayes
;--------------------------------------------------------------------------
ifdef buildLCDgetByte
LCDgetByte
; we should have set up PCLATH
; When LCDstrPtr gets to 0xFF
MOVLW high $
MOVWF PCLATH
MOVFW LCDstrPtr;
ADDWF PCL,f
LCDstrs
LCDstrLTime equ $ - LCDstrs
DT "Hello"
GOTO LCDgetByteEnd4 ; now print out 4 blanks
LCDstrLblank equ $ - LCDstrs
DT " "
GOTO LCDgetByteEnd6
LCDstrLOff equ $ - LCDstrs
DT "OFF"
GOTO LCDgetByteEnd6
LCDstrLOn equ $ - LCDstrs
DT "ON "
GOTO LCDgetByteEnd6
LCDstrLOnp equ $ - LCDstrs
DT "ON+"
GOTO LCDgetByteEnd6
LCDLastStr
IF 0 != ( high ( LCDLastStr ) - high ( LCDgetByte ) )
Error "String Table straddles Page Boundary "
ENDIF
; Jump into these to select how many spaces printed
; at the end, so that 9 chars are printed.
LCDgetByteEnd0
DECF LCDeraseCnt,f
LCDgetByteEnd1
DECF LCDeraseCnt,f
LCDgetByteEnd2
DECF LCDeraseCnt,f
LCDgetByteEnd3
DECF LCDeraseCnt,f
LCDgetByteEnd4
DECF LCDeraseCnt,f
LCDgetByteEnd5
DECF LCDeraseCnt,f
LCDgetByteEnd6
CLRF LCDstrPtr
DECF LCDstrPtr,f
RETURN
endif ; buildLCDgetByte
;--------------------------------------------------------------------------
; Sec 3.3.4.3 LCD procedures LCD string write displayes
;--------------------------------------------------------------------------
LCDwrtStr ; W contains the string offset
MOVWF LCDstrPtr;
; Erase upto 6 chars at end of string
MOVLW 0x06
MOVWF LCDeraseCnt
; position cursor at left on line 1.
; erase old display
MOVLW LCDCurLeft0 ; 0x80
CALL LCDwrtCmd
GOTO LCDwrtStr1
LCDwrtStr0
CALL LCDwrtChar
LCDwrtStr1
CALL LCDgetByte
INCFSZ LCDstrPtr,f
GOTO LCDwrtStr0
GOTO LCDwrtStrFlush
; write 10 chars to blank rest of right
LCDwrtStrFlush
; W contains the number of Chars to flush
LCDwrtStrLoop
DECFSZ LCDeraseCnt,f
GOTO LCDwrtStrLoop1
RETURN
LCDwrtStrLoop1
MOVLW 0x20
CALL LCDwrtChar
GOTO LCDwrtStrLoop
;--------------------------------------------------------------------------
; Sec 3.3.4 LCD procedures
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; Sec 3.3.4.1 LCD procedures - Multi entry display procedure for commands, nibbles,bytes,chars
;--------------------------------------------------------------------------
LCDdispByte
MOVWF LCDnibble
; Display top nipple
SWAPF LCDnibble,w
CALL LCDwrtDecNibble
; Display bottom nipple
MOVFW LCDnibble
CALL LCDwrtDecNibble
RETURN
LCDwrtCmd
BCF LCDPortB,LCDbitA0
GOTO LCDwrtByte
LCDwrtDecNibble ; currently only displays 0..9, A..F
ANDLW 0x0F
ADDLW 0x06 ; is it A..F, if so trigger a digit overflow
SKPNDC
ADDLW 7; subtract 10, then add 'A'-'0'
ADDLW 0x30-6 ; Subtract extra 6 added to cause DC
LCDwrtChar
BSF LCDPortB,LCDbitA0
ifdef buildLCD_HD44780
;You don't need to read the busy line on the display.
;
;PORT B Display LCD Pin
;DB7 DB7 14
;DB6 DB6 13
;DB5 DB5 12
;DB4 DB4 11
;DB3 E 6
; R/W gnd 5
;DB2 RS 4
; V0 Vlcd 3
; Vss 0 2
; Vdd +5 1
;R/W ==X====================x====
;RS ____________________________ 0 for CMD, 1 for DATA
;E ____/----\____/-----\_______
;DB ==X=========X==========X====
; MSN LSN
; define bits - these need to be defined for the HD44780 chip
;LCDbitCS EQU 1 ; PORTB:1
;LCDbitWR EQU 3 ; PORTB:3
;LCDbitCLK EQU 3 ; PORTB:3 or OSC Out
LCDbitE EQU 3
LCDbitRS EQU 2
LCDbitA0 EQU LCDbitRS ; RS - PORTB:2 ; sometimes used for bit number
LCDCurOff EQU 0x0C ; DisplayOn, Cursor Off, Blink Off
LCDCurOn EQU 0x0F ; DisplayOn, Cursor On, Blink On
LCDCurLeft0 EQU 0x80 ; display 80,..,89,C0..C9 ; top
LCDCurRight0 EQU 0xC0 ; left
LCDCurLeftLower EQU 0xC0 ; left
LCDwrtByte
; assume that the A0 line is correctly set,
; Byte to be displayed is in W
; SED1200 LCD chip
; CS ----________------------------------------------------
; WR,CLK-----__--__------_-_-_-_--_-_-_-_--_-_-_-_--_-_-_-_---
; DB,A0 ---x====x====x----------------------------------------
; HD44780 LCD chip
;R/W ==X====================x====
;RS ____________________________ 0 for CMD, 1 for DATA
;E ____/----\____/-----\_______
;DB ==X=========X==========X====
; MSN LSN
; Assumes:-
; LCD_DB0..3 connected to PORTB:4..7
; R/~w connected to Gnd.
; R/S,E are equated, but connected to PORTB
; on exit PORTB<4:7> are left as inputs, so that they can
; be used for the keyboard/buttons.
MOVWF LCDtemp
; set up PORTB<0:3> to Outputs,PORTB<4:7> to Outputs
MOVLW 0x00 ; This is only required if
MOVWF PORTB ; The MS nibble is used as
BSF STATUS, RP0 ; inputs when reading buttons.
MOVLW 0x01 ;
MOVWF TRISB ;
BCF STATUS, RP0 ;
BTFSC LCDPortB, LCDbitA0 ; set RS line early
BSF PORTB,LCDbitA0
BTFSS LCDPortB, LCDbitA0 ; set
BCF PORTB,LCDbitA0
; set up to write top nibble, then pulse WR
MOVFW LCDtemp
ANDLW 0xF0 ; assumes DB0..DB3 is MSB
BTFSC LCDPortB, LCDbitRS ; set
IORLW 1 << LCDbitRS
MOVWF PORTB
BSF PORTB,LCDbitE
NOP
BCF PORTB,LCDbitE
; set up to write bottom nibble, then pulse WR
SWAPF LCDtemp,w
ANDLW 0xF0 ; assumes DB0..DB3 is MSB
BTFSC LCDPortB, LCDbitA0 ; set
IORLW 1 << LCDbitRS
MOVWF PORTB
BSF PORTB,LCDbitE
NOP
BCF PORTB,LCDbitE
NOP
; set up PORTB<0:3> to Outputs,PORTB<4:7> to Inputs
BSF STATUS, RP0 ;
MOVLW 0xF1 ;
MOVWF TRISB ;
BCF STATUS, RP0 ;
; Run a little delay to allow the instructions to take place.
MOVLW 20
; MOVLW 1
MOVWF LCDtemp
; Hold CS high and pulse WR low at least 16 times
; Now pulse CLK low 16 times to execute command
LCDloop
; BCF PORTB,LCDbitCLK
NOP
NOP
; BSF PORTB,LCDbitCLK
DECFSZ LCDtemp,f
GOTO LCDloop
RETURN
LCDdelay
; 1.79 ms delay
MOVLW 255
MOVWF LCDtemp
LCDdelay1
GOTO $+1
GOTO $+1
DECFSZ LCDtemp,f
GOTO LCDdelay1
RETURN
LCDdelaylong
; 1.79 ms delay
CLRF LCDtemp
LCDdelaylong1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
GOTO $+1
DECFSZ LCDtemp,f
GOTO LCDdelaylong1
RETURN
;--------------------------------------------------------------------------
; Sec 3.3.4.2 LCD procedures - Initilization
;--------------------------------------------------------------------------
LCDstart
; Minimum reset instructions:
; System Reset,Line Select(2),Display On
; set up for LCD commands
; wlcdCmd($33);
; wlcdCmd($32);
; wlcdCmd($28); { 4 bit, 2 line, 5x7 display }
; wlcdCmd($01); { Clear Display }
; wlcdCmd($0F); { $0F - Display On,CursorOn,Blink }
; wlcdCmd($C9); { set dd address }
MOVLW 0x33 ; 40us force to 8 bit mode, from any mode
CALL LCDwrtCmd
MOVLW 0x32 ; 40us force to 4 bit mode
CALL LCDwrtCmd
MOVLW 0x28 ; 40us 4 bit, 2 line, 5x7 display
CALL LCDwrtCmd
MOVLW 0x01 ; Clear display
CALL LCDwrtCmd
CALL LCDdelay
MOVLW 0x0F ; Display On,Cursor On,Blink
CALL LCDwrtCmd
MOVLW 0x80
MOVLW 10
MOVWF LCDcnt
; Now actually display something
MOVLW LCDstrLTime
CALL LCDwrtStr
RETURN
;To know wwhich nibble is being sent initilize to 8 bit then
;go into 4 bit mode and keep track of each nibble sent
;
;If using 4 bit interface only use the DB4 to DB7 pins.
;The 8 bits comands to convert to 4 bits mode do not care
;about the 4 LSB.
;
;With R/W =0 and RS=0:
;
;0x01 ;clear display 82us @250Hz
;0x02 ;return home 82us @250Hz
;0x04 ;EntryModeSet 40us @250Hz
; 0x01 ; S 1 = shift
; 0x02 ; I/D 1= increment/0=decrement
;0x08 ;Display ON/OFF 40us @250Hz
; 0x01 ; B Blink
; 0x02 ; C Cursor On
; 0x04 ; D Display On
;0x10 ;Cursor and Display Shift 40us @250Hz
; 0x04 ; s/c Shift Display/ 0=shift Cursor
; 0x08 ; r/l Shift Right,0=shift left
;0x20 ;Function Set 40us @250Hz
; 0x04 ; F 5x10 dots /5x7dots
; 0x08 ; N 2lines /1lines
; 0x10 ; DL 8bits interface /4 bits interface.
;0x40 ;Set CG RAM address 40us @250Hz
;0x80 ;Set DD RAM address; 40us @250Hz
;With R/W =0 and RS=1:
;write data to CG or DD
;With R/W =1 and RS=1:
;Read data from CG or DD
;
;Send the commands below to Initilize.
;First mop up any 4 bit commands, and convert to 8 bit,
;either from 4 bit mode or 8 bit mode.
;Then from 8 bit node move to 4 bit mode.
;Then issue 4 bit commands.
; wlcdCmd($33); 8 bit mode - could be in 4 bit mode
; wlcdCmd($32); 8 bit mode - could be in 4 bit mode
; wlcdCmd($28); 4 bit mode, 2 lines 5x7 dots
; wlcdCmd($01); Clear Display could take 1.6ms
; wlcdCmd($0F); $0F - Display On,CursorOn,Blink
; wlcdCmd($C9); set dd address
;You don't need to read the busy line on the display.
;
;PORT B Display LCD Pin
;DB7 DB7 14
;DB6 DB6 13
;DB5 DB5 12
;DB4 DB4 11
;DB3 E 6
; R/W gnd 5
;DB2 RS 4
; V0 Vlcd 3
; Vdd +5 2
; Vss 0 1
endif
ifdef buildLCDsed1200
;
;
;================================================================
;this needs to be changed
;
;
;--------------------------------------------------------------------------
; Sec 3.3.1 LCD introduction - SED1200F
;--------------------------------------------------------------------------
;LCD Information
;==================
;
;Having brought a number of displays for a bargin price, and finding that the
;information provided was inadequate, this document summarizes what has been
;found out.
;
;
;Epson EA-C20017AR
;==================
;
;20 char by one line.
;
;The display appears to be based on an SED1200F controller.
;
;Pin Connections when looking at display, contacts on left.
;
; 1 +5V 2 Gnd |------------------|
; 3 Vlcd 4 Clk | |
; 5 -CS 6 A0 | DISPLAY 20x1 |
; 7 -WR 8 -RD | - |
; 9 DB3 10 DB2 | |
; 11 DB1 12 DB0 |------------------
;
; Display is 20 x 1
; Suggested values for single line mode , 10 x 1 repeated 10 x 1.
;
; + 5V Pin 1
; |
; [ ] 10k ohm
; |
;Vlcd Pin 3
; |
; [ ] 3k ohm
; |
; GND
;
;
; For proper operation run the display as two line mode.
;
;
; Initialization. leaves random characters.
;
; CMD, System Reset 0,0x10
; CMD, DISPLAY ON 0,0x0D
; CMD, Line Select-On 0,0x13
; CMD, Cursor Home 0,0x80
; DATA,0x20
;--------------------------------------------------------------------------
; Sec 3.3.2 LCD command equates
;--------------------------------------------------------------------------
;
; SED 1200F config commands A0=0
;
LCDsetCurDirInc EQU 0x04
LCDsetCurDirDec EQU 0x05
LCDCurInc EQU 0x06
LCDCurDec EQU 0x07
LCDCurBlock EQU 0x09
LCDCurUL EQU 0x08
LCDCurConst EQU 0x0A
LCDCurBlink EQU 0x0B
LCDCurDispOff EQU 0x0C
LCDCurDispOn EQU 0x0D
LCDCurOff EQU 0x0E
LCDCurOn EQU 0x0F
LCDSysReset EQU 0x10
LCD1line EQU 0x12
LCD2line EQU 0x13
LCDCurX0Y0 EQU 0x80 ; display has two halfs of 10 chars each
LCDCurX1Y0 EQU 0xC0 ;
LCDCurLeft0 EQU 0x80 ; display 80,..,89,C0..C9
LCDCurRight0 EQU 0xC0 ;
LCDCgRamAddr EQU 0x20
LCDCgRamData EQU 0x40
;--------------------------------------------------------------------------
; Sec 3.3.3 LCD control line / hardware to port mapping equates
;--------------------------------------------------------------------------
; define binary Mask for bits
LCD_CS EQU 2 ; PORTB:1
LCD_WR EQU 8 ; PORTB:3
LCD_CLK EQU 8 ; PORTB:3 or OSC Out
LCD_A0 EQU 4 ; PORTB:2 ; sometimes used for bit number
; define bits
LCDbitCS EQU 1 ; PORTB:1
LCDbitWR EQU 3 ; PORTB:3
LCDbitCLK EQU 3 ; PORTB:3 or OSC Out
LCDbitA0 EQU 2 ; PORTB:2 ; sometimes used for bit number
LCDwrtByte
; assume that the A0 line is correctly set,
; Byte to be displayed is in W
;
; CS ----________------------------------------------------
; WR,CLK-----__--__------_-_-_-_--_-_-_-_--_-_-_-_--_-_-_-_---
; DB,A0 ---x====x====x----------------------------------------
; Assumes:-
; LCD_DB0..3 connected to PORTB:4..7
; RD connected to +5
; WR,CS,A0,CLK are equated, but connected to PORTB
; on exit PORTB<4:7> are left as inputs, so that they can
; be used for the keyboard/buttons.
MOVWF LCDtemp
; set up PORTB<0:3> to Outputs,PORTB<4:7> to Outputs
MOVLW 0xFF ; This is only required if
MOVWF PORTB ; The MS nibble is used as
BSF STATUS, RP0 ; inputs when reading buttons.
MOVLW 0x01 ;
MOVWF TRISB ;
BCF STATUS, RP0 ;
BTFSC LCDPortB, LCDbitA0 ; set A0 line early
BSF PORTB,LCDbitA0
BTFSS LCDPortB, LCDbitA0 ; set
BCF PORTB,LCDbitA0
; set up to write top nibble, then pulse WR
MOVFW LCDtemp
IORLW 0x0F ; -CS,-A0,-WR
BTFSS LCDPortB, LCDbitA0 ; set
ANDLW ~LCD_A0
MOVWF PORTB
BCF PORTB,LCDbitCS
BCF PORTB,LCDbitWR
NOP
BSF PORTB,LCDbitWR
; set up to write bottom nibble, then pulse WR
SWAPF LCDtemp,w
IORLW 0x0F ; -CS,-A0,-WR
BTFSS LCDPortB, LCDbitA0 ; set
ANDLW ~(LCD_A0 | LCD_CS)
ANDLW ~LCD_CS
MOVWF PORTB
BCF PORTB,LCDbitWR
NOP
NOP
BSF PORTB,LCDbitWR
NOP
NOP
BSF PORTB,LCDbitCS
; set up PORTB<0:3> to Outputs,PORTB<4:7> to Inputs
BSF STATUS, RP0 ;
MOVLW 0xF1 ;
MOVWF TRISB ;
BCF STATUS, RP0 ;
MOVLW 20
; MOVLW 1
MOVWF LCDtemp
; Hold CS high and pulse WR low at least 16 times
; Now pulse CLK low 16 times to execute command
LCDloop
BCF PORTB,LCDbitCLK
NOP
NOP
BSF PORTB,LCDbitCLK
DECFSZ LCDtemp,f
GOTO LCDloop
; set up PORTB<0:3> to Outputs,PORTB<4:7> to Inputs
BSF STATUS, RP0 ;
MOVLW 0xF1 ;
MOVWF TRISB ;
BCF STATUS, RP0 ;
RETURN
;--------------------------------------------------------------------------
; Sec 3.3.4.2 LCD procedures - Initilization
;--------------------------------------------------------------------------
LCDstart
; Minimum reset instructions:
; System Reset,Line Select(2),Display On
; set up for LCD commands
; CMD, System Reset 0,0x10
; CMD, DISPLAY ON 0,0x0D
; CMD, Line Select 2
; CMD, Cursor On 0,0x0F
; CMD, Cursor Dir 0,0x04
; CMD, Cursor Blink off 0,0x0A
; CMD, Cursor Home 0,0x80
; DATA,0x20 BCF PORTA,LCDA0
; LCD system reset
MOVLW 0x10
CALL LCDwrtCmd
; LCD Display On
MOVLW 0x0D
CALL LCDwrtCmd
; LCD Set 2 Line Mode
MOVLW 0x13
CALL LCDwrtCmd
; LCD Display On
MOVLW 0x0D
CALL LCDwrtCmd
; LCD Cursor Home
MOVLW 0x80
CALL LCDwrtCmd
MOVLW 10
MOVWF LCDcnt
; now write some characters
LCDloop1
MOVLW 0x20
CALL LCDwrtChar
DECFSZ LCDcnt,f
GOTO LCDloop1
; LCD Cursor Home
MOVLW 0xC0
CALL LCDwrtCmd
MOVLW 10
MOVWF LCDcnt
LCDloop2
MOVLW 0x20
CALL LCDwrtChar
DECFSZ LCDcnt,f
GOTO LCDloop2
LCDloop2A
; Now actually display something
MOVLW LCDstrLTime
CALL LCDwrtStr
RETURN
endif ;buildLCDsed1200
;
;
;=======================================================================
;
;
;: Symbols that need to be defined differently for different LCD chips
;RT003.ASM 390 : (LCDstart)
;LCD.INC 151 : (LCDbitA0) ; check the sense
;LCD.INC 152 : (LCDwrtByte)
;RT003.ASM 803 : (LCDCurOn)
;RT003.ASM 812 : (LCDCurOff)
;RT003.ASM 680 : (LCDCurRight0)
;LCD.INC 104 : (LCDCurLeft0)
;--------------------------------------------------------------------------
; END OF FILE
;--------------------------------------------------------------------------
Strap GPIO3 low for serial.
Strap GPIO3 high to allow A/D0 bit5 to be copied to GPIO5.
;**********************************************************
;* dm002.asm
;**********************************************************
;* This program configures the A/D Module to convert on
;* A/D channels and outputs the results serial at 32K
;**********************************************************
list p=12f675
; Include file, change directory if needed
include "p12f675.inc"
__idlocs 0x1234
__config _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF
cblock 0x20
; variables used for context saving
w_temp
status_temp
ADrh
ADrl
ADcnt
SRtxTemp
SRtxCnt
SRout
SRdel
cnt1
cnt2
cnt3
endc
; Start at the reset vector
org 0x000
; goto test
goto Init
test
movlw 0
movwf cnt1
movlw 1
movwf cnt2
test1
incf cnt1,f
incf cnt2,f
movfw cnt1
xorwf cnt2,w
andlw 0x88
movwf cnt3
goto test1
Init
org 0x010
banksel 0x3FF
CALL 0x3FF
MOVWF OSCCAL
banksel TRISIO
BSF STATUS, RP0
; movlw 0xCF
movlw 0xDF
MOVWF TRISIO ; Set output high to start Measurement
BCF STATUS, RP0
movlw 0x0D
call SRtxChar
movlw 0x0A
call SRtxChar
movlw 0x0D
call SRtxChar
movlw 0x0A
call SRtxChar
movlw 0x55
call SRtxChar
movlw 0xAA
call SRtxChar
movlw ' '
call SRtxChar
movlw 'A'
call SRtxChar
movlw '/'
call SRtxChar
movlw 'D'
call SRtxChar
movlw ' '
call SRtxChar
movlw '('
call SRtxChar
movlw '8'
call SRtxChar
movlw '7'
call SRtxChar
movlw '6'
call SRtxChar
movlw ')'
call SRtxChar
movlw ' '
call SRtxChar
movlw 0x55
call SRtxChar
movlw 0xAA
call SRtxChar
movlw 0x0D
call SRtxChar
movlw 0x0A
call SRtxChar
; goto Init
Start
; output p(,ad0,ad1,ad2,ad3,ad5,);
movlw 0x0D
call SRtxChar
movlw 0x0A
call SRtxChar
movlw 'p'
call SRtxChar
movlw '('
call SRtxChar
movlw ','
call SRtxChar
movlw 0 << 2
call ADconvert
call LDled
movlw 1 << 2
call ADconvert
movlw 2 << 2
call ADconvert
movlw 3 << 2
call ADconvert
; movlw ','
; call SRtxChar
movlw ')'
call SRtxChar
movlw ';'
call SRtxChar
goto Start ;Do it again
ADconvert
; W contains the channel in bit 5-3
banksel ADCON0
addlw B'00000001' ;Fosc/8, A/D enabled
movwf ADCON0
banksel ANSEL
movlw B'00010111' ;Fosc/8, A/D enabled
movwf ANSEL
banksel OPTION_REG
movlw B'10000111' ;TMR0 prescaler, 1:256
movwf OPTION_REG
banksel ADCON0
movlw 0x80 | 2 ;Left justify,5 analog channel
addwf ADCON0,f ;VDD and VSS references
banksel GPIO
banksel INTCON
Main
; goto StartConvert
; btfss INTCON,T0IF ;Wait for Timer0 to timeout
; goto Main
; bcf INTCON,T0IF
;
; use PORTA 4 as a delay.
;
;Vdd - [ Rt ] + [ R ] - pin RA4
;
; C
; |
; gnd
;
; make RA4 an output to discharge C
; then make it an input
; Wait for C to Charge, then proceed.
;
StartConvert
bcf PIR1,ADIF
banksel ADCON0
bsf ADCON0,GO ;Start A/D conversion
Wait
btfss PIR1,ADIF ;Wait for conversion to complete
goto Wait
nop
nop
movfw ADRESH
movwf ADrl
; now output the value in Hex
swapf ADrl,W ;Write A/D result to GPIO
call SRwrtHexNibble
movf ADrl,W ;Write A/D result to GPIO
call SRwrtHexNibble
banksel ADRESL
movfw ADRESL
banksel ADrl
movwf ADrl
swapf ADrl,W ;Write A/D result to GPIO
call SRwrtHexNibble
movf ADrl,W ;Write A/D result to GPIO
call SRwrtHexNibble
movlw ','
call SRtxChar
return
SRwrtHexNibble ; currently only displays 0..9, A..F
ANDLW 0x0F
ADDLW 0x06 ; is it A..F, if so trigger a digit overflow
SKPNDC
ADDLW 7; subtract 10, then add 'A'-'0'
ADDLW 0x30-6 ; Subtract extra 6 added to cause DC
MOVWF SRout
GOTO SRtxChar
SRtxChar
; test GPIO bit 3 to see if serial out or LED out
; GPIO bit 3 must be low
BTFSC GPIO,3
RETURN
;
;Output Start Bit
;Output LSB first
;use
TxOnBit equ 5
movwf SRtxTemp
comf SRtxTemp,f
BCF GPIO,TxOnBit
MOVLW ~( 3 << TxOnBit )
; TRIS GPIO
BSF STATUS, RP0
MOVWF TRISIO ; Set output high to start Measurement
BCF STATUS, RP0
; 1200 baud output
; move the char into SRtxtemp, it is destroyed.
;Start Bit
BSF GPIO,TxOnBit
GOTO $+1
call delay
movlw TxOnBit
movwf SRtxCnt
GOTO $+1
SRtxCharLp1
; This outputs two bits at a time
; this takes 6.5 cycles each
; After start bit, which is 1, then test each bit
; I need to set PA:0 to same as LSB SRtxTemp
; this compares PA:0 with SRtxTemp so see if it needs toggling
; The xorwf PORTA,f causes the bit to be toggled if required.
; Toggle bit if next bit is different
RRF SRtxTemp,f
movfw STATUS
andlw 1 << C ; mask off bit
addlw ( 1 << TxOnBit) -1 ; shift bit by using a ripple carry
xorwf GPIO,W
andlw 0x1 << TxOnBit
xorwf GPIO,f ;t+6,19
GOTO $+1
call delay
RRF SRtxTemp,f
movfw STATUS
andlw 1 << C
addlw ( 1 << TxOnBit) -1
xorwf GPIO,W
andlw 0x1 << TxOnBit
xorwf GPIO,f ;t+11,24
GOTO $+1
call delay
decfsz SRtxCnt
goto SRtxCharLp1
GOTO $+1
GOTO $+1
call delay
BCF GPIO,TxOnBit
GOTO $+1
GOTO $+1
RETURN
delay
nop
movlw 0x03
movwf SRdel
delay1
decfsz SRdel
goto delay1
return
;---------------------------
; LD process
;---------------------------
LDled
; test GPIO bit 3 to see if serial out or LED out
BTFSS GPIO,3
RETURN
banksel ADRESL
movfw ADRESL
movwf ADrl
banksel GPIO
bcf GPIO,5
BTFSC ADrl,5
bsf GPIO,5
return
org 0x3FD
RETLW 0x6C
RETLW 0x6C
RETLW 0x6C
end
