Full Version : Wireless LCD Display (AVR ASM)
avr >>PROJECTS (AVR) >>Wireless LCD Display (AVR ASM)


AVR_Admin- 04-28-2006
Minimum Mass Wireless LCD Display by Dick Cappel

A 2 line X 16 character LCD display that is battery operated and works without an external connection.


The basic MinThe basic Minimum Mass Wireless Coupler technology is described and links to other projects on this site that use the Minimum Mass Wireless Coupler are located on the web page, Minimum Mass Wireless Coupler: http://cappels.org/dproj/minmassrf/Min_Mas...ss_Coupler.html

Its an adaption of the 2X 16 LCD project, by adding a fettite loop antenna,
two resistors, and a capacitor. Here the display shows the output of the
10 bit scanning voltmeter with Minimum Mass Wireless Coupler. Both the
ferrite loop antenna and the scanning voltmeterare described elsewhere on this site.

Link to Site: http://cappels.org/dproj/minmassrfTruly/mmrft.html

CODE

;Copyright 2004 Richard Cappels, projects@cappels.org
;Program Name: VLFCW -Make 181.818181818181...kHz from 4 Mhz crystal

;vlfcw040711B Changed some macros to subroutines.

;Reload and prescale values
.equ XmtTimerReload = $BC;Timer 0 reload value for T
.equ RcvTimerReload = $EF;Timer 0 reload value for T/4
.equ RecThresh =  40;Minimum number of counts to detect carrier.

.equ Timer0Prescale = $03;Timer 0 prescaler selector

.equ delaytime = 20;Waiting time after transmit mode before receiving.


;Four callable routines are available. One register isnot saved, RFByte, which is
;used to transfer the data between the RF routines and calling routines and is
;to be a high register (r16-r31). It needs to be delcared as such in program calling this file..
;Calling other routines may result in modification of other registers.
;
;SendRFByte (subroutine)
;Sends contents of RFChar via RF. Modifies RFChar.

;
;ReceiveRFByte (subroutine)
;Waits for start bit on RF channel for 63.75 bit times. Returns with carry set and
;data in RFChar if character received. Returns with carry clear if no byte received.


;  
;PostXmitDelay;(macro);Wait for antenna to stop ringing from xmit.
;Use this delay after transmitting if listening is to follow. The delay allows
;ringing in the antenna to die down so that the ringing is not misatken as data.


;PostRCVDelay;(macro);Wait for far end receiver to recover.
;Use this after receiving data, before sending to give the receiver associated
;with the transmitter that just sent data to recover.
;
;
;
;
;
;
;
;
;
;
;
;Reference circuit:
;AT90S2313 microcontroller with 4 MHz clock.

;A resonant loop antennat tuned to 182 kHz is connected across the comparitor intputs, PORTB,0
; and PORTB,0.

;One such resonant circuit is 14 turns of #30 wire on 5.5 cm in diameter, air core, brought into
;resonance with a .033 uf capacitor in parallel with it.

;BPORTB,1 is also connected to the tap on a 2:1 resistive voltage devider. Both resistors in the
;devider are of the same vlaue and may range from about 220 Ohms to 1 k Ohms each.

;The voltage devider may be power from the microcontroller's positive power supply, or optionally,
;powered from one of its output pins PORTB,2 has been designated for this purpose. Powering
;from an output pin allows power reduction during sleep.

;PORTB,3 is intended to drive an activity indicator LED. It goes high briefly while transmitting
;and receiving data over the RF link.


;*************Code for calling file found below .exit command, below*****************

;//////////////BEGIN BASIC RF COUPLER ROUTINES\\\\\\\\\\\\\\\


.macro pushall

push r2;
push r18 ;
push r17 ;
push r19;  
   
.endmacro          
     
   
.macro popall    
pop r19; ;Temporaty storage of status register
pop r17 ;;General purpose scratch register
pop r18 ;General purpose scratch register.
pop r2;;Comparitor interrupt counters
         
.endmacro          
         



PostXmitDelay:
ldi r18,delaytime
rcall delay
ret



PostRCVDelay:
ldi r18, 2 * delaytime
rcall delay
ret



delay:    ;Delay - load 00 into r18 for max delay, 01 for minimum delay.
   ;r18 and r17 destroyed.
lptrf1: clr r17
lptrf12: dec r17
brne lptrf12
dec r18
brne lptrf1
ret


ReceiveRFByte:   ;Receive a byte by RF and put into RFChar
   ;Returs with carry set if data received, otherwise cleared.
pushall   ;Save  working registers on stack
ldi  r18,Timer0Prescale;Initaize prescaler.
out  TCCR0, r18
ldi  r18, RcvTimerReload;Initialize counter.
out  TCNT0,r18
ldi  r18, $02 ;Enable interrupts TIMSK.
out  TIMSK,r18

clr r2  ;Zero comparitor interrupt counter.
ldi r17,0b00001011 ;Comparitor setup: enable interrupt on positive edge.
out ACSR,r17

clr r17  ;Clear start bit test counter.

wfsbrf1:    ;Wait for start bit.
rcall QCDrf1  ;Sample for 1/4 bit time.
dec r17  ;See if too many consecutive unsuccessful samples.
breq bailrf1

mov r18,r2
cpi r18,RecThresh ;Check number of carrier cycles against threshold.
brmi wfsbrf1

rcall QCDrf1  ;Wait T/4.
rcall QCDrf1  ;Wait T/4.

ldi r17,8  ;Set number of bits: 8 data.
nbrf1:

sbi LEDOutPort,LEDOutPin

rcall QCDrf1  ;Wait T/4.
rcall QCDrf1  ;Wait T/4.
rcall QCDrf1  ;Wait T/4.
clr r2
rcall QCDrf1  ;Sample for 1/4 bit time <== use this sample


mov r18,r2
cpi r18,RecThresh ;Set carry true if threshold exceeded.
brpl oirf1
clc
rjmp zeinrf1
oirf1: sec
zeinrf1: ror RFChar ;Get carry into lsb of RFChar.

dec r17
brne nbrf1

sec   ;Data received - set carry flag
rcxtrf1:
ldi r18,0
out TCCR0,r18 ;Turn off timer0 interrupt
out ACSR,r18 ;Turn off Comparitor interrupt
cbi LEDOutPort,LEDOutPin  
popall
ret
bailrf1:clc   ;No data received - clear carry and return
rjmp rcxtrf1



SendRFByte:   ;Shift byte in RFChar out through RF channel.
   ;RFChar changed by routine.
pushall   ;Save all working registers except RFChar.
sbi LEDOutPort,LEDOutPin;For indication purposes

ldi  r18,Timer0Prescale;Initaize prescaler
out  TCCR0, r18
ldi  r18, XmtTimerReload;Initialize counter
out  TCNT0,r18
ldi  r18, $02 ;Enable interrupts TIMSK
out  TIMSK,r18
ldi r17,11 ;Set number of bits:1 start, 8 data, 2 stop
sec   ;Start bit    
nxbtrf1:
brcs bitsonerf1
rcall szerorf1
rjmp iwzrf1
bitsonerf1:
sbi RFSigDDR,RFSigPin ;Set signal output pin to output.
rcall SendOnerf1
cbi RFSigDDR,RFSigPin ;Set signal output pin to input.
iwzrf1:
lsr RFChar  ;Shift next bit into carry.
dec r17  ;Decrement bit counter.
brne nxbtrf1  ;If not all done, then continue.
out TCCR0,RFChar ;(RFChar was cleared by shifting.)
cbi RFSigPort,RFSigPin ;Set signal output low (no pullup).
cbi LEDOutPort,LEDOutPin
popall   ;Restore all working registes except RFChar.
ret


szerorf1:   ;Send no carrier for for one bit time.
ldi  r18, XmtTimerReload;Initialize counter
out  TCNT0,r18
WaitNotSend:
rjmp WaitNotSend ;Do nothing but wait for interrupt to yank out of loop.




SendOnerf1:   ;Send carrier for T us
ldi  r18, XmtTimerReload;Initialize counter
out  TCNT0,r18 ;Send carrier until next interruput
MakeRF1:   ;Make 181.8181 Mhz
sbi RFSigPort,RFSigPin;Output High sbi and cbi are 2 clock instructions.
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
sbi RFSigPort,RFSigPin
nop   ;(need this nop for timing)

cbi RFSigPort,RFSigPin;Output Low
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
cbi RFSigPort,RFSigPin
nop
rjmp MakeRF1  ;Interrupt will yank out of loop.



QCDrf1:   ;Send no carrier for T/3 us
ldi  r18, RcvTimerReload;Initialize counter
out  TCNT0,r18
WaitHere1:
rjmp WaitHere1 ;Send no carrier until next interruput



timer0service:   ;Return to routine that called interrupted routine. The processor
   ;must be in a subroutine when this interrupt occurs!  Disable
   ;the timer the rest of the time.
pop r18
pop r18
reti   ;Return from interrupt.to routine before interrupt


comparitorservice:  ;Increment r18 upon comparitor interrupt.
in r19,sreg ;Save status register.
inc r2 ;Increment SigCount.
out sreg,r19 ;Restore status register.
reti   ;Return from interrupt. Total of 7 cycles including the return.

;//////////////END BASIC RF COUPLER ROUTINES\\\\\\\\\\\\\\\
 



.exit






;******************** Below is code for the calling file *****************************.

;Inlcude the code below in the calling file. It may be customized. Copy the code from here
;to ".exit" into the calling document.


;Copyright 2004 Richard Cappels, projects@cappels.org
;Program Name: VLFCW -Make 181.818181818181...kHz from 4 Mhz crystal


;////////////////// START OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\

.include "2313def.inc" ;Include file in same directory as project.


.equ RFSigPort = PORTB;Port output signal is to appear on.
.equ RFSigDDR = DDRB;Data Direction Register for signal output
.equ RFSigPin = 0;Pin output signal is to appear on.

.equ LEDOutPort = PORTB;Indicator LED
.equ LEDOutDDR = DDRB
.equ LEDOutPin = 3

.equ CompPlusPort = PORTB;Comparitor noninverting input (input 0)
.equ CompPlusDDR = DDRB
.equ CompPlusPin = 0

.equ BridgePowerPort = PORTB;Power for bridging resistors
.equ BridgePowerDDR = DDRB
.equ BridgePowerPin = 2


.def temp  = r18;General purpose scratch register.

.def RFChar  = r16;RF character I/O buffer


;definition of I/O
;B0 + comparitor input - Antenna Signal
;B1 - comparitor input - Antenna reference
;B2 Bridge power  
;B3 LED (high to turn LED on) .
;B4 Receive/Xmit application (for test purposes)
;B5 (not assigned - configure as INPUT with weak pullup)
;B6 (not assigned - configure as INPUT with weak pullup)
;B7 (not assigned - configure as INPUT with weak pullup)


;D0 Reserved FOR UART RECEIVE - input has weak pullup
;D1 Reserved FOR UART TRANSMIT - output.
;D2 (not assigned - configure as INPUT with weak pullup)
;D3 (not assigned - configure as INPUT with weak pullup)
;D4 (not assigned - configure as INPUT with weak pullup)
;D5 (not assigned - configure as INPUT with weak pullup)
;D6 (not assigned - configure as INPUT with weak pullup)
;D7 (not assigned - configure as INPUT with weak pullup)


.cseg

.ORG $0000   ;Initializaton code
rjmp start
.ORG $0006
rjmp timer0service ;Timer/counter compare interrupt
.ORG $000A
rjmp comparitorservice ;Service comparitor interupt

.include "vflcw2313.inc" ;Load VLFCW routines


;Four callable routines are available. One register isnot saved, RFByte, which is
;used to transfer the data between the RF routines and calling routines and is
;to be a high register (r16-r31). It needs to be delcared as such in program calling this file..
;Calling other routines may result in modification of other registers.
;
;SendRFByte (subroutine)
;Sends contents of RFChar via RF. Modifies RFChar.

;
;ReceiveRFByte (subroutine)
;Waits for start bit on RF channel for 63.75 bit times. Returns with carry set and
;data in RFChar if character received. Returns with carry clear if no byte received.


;  
;PostXmitDelay;(macro);Wait for antenna to stop ringing from xmit.
;Use this delay after transmitting if listening is to follow. The delay allows
;ringing in the antenna to die down so that the ringing is not misatken as data.


;PostRCVDelay;(macro);Wait for far end receiver to recover.
;Use this after receiving data, before sending to give the receiver associated
;with the transmitter that just sent data to recover.
;



start:
 
ldi r16,RAMEND ;Initialize Stack Pointer.
out spl,r16
   ;Set PORTD.
ldi temp,0b00000010  
out DDRD,temp
ldi temp,0b10111111
out PORTD,temp

   ;Set PORTB.
ldi temp,0b00000000  
out DDRB,temp
ldi temp,0b11110100
out PORTB,temp  


sbi BridgePowerDDR,BridgePowerPin;Turn on bridge power
sbi LEDOutDDR,LEDOutPin;Make LED so an output pin.
sei   ;ENABLE THE INTERRUPTS



;////////////////// END OF INITIALIZATION CODE \\\\\\\\\\\\\\\\\\\\\\\\\


.exit



CODE


;rftruly040802A  Minor correction - explicitly initialized DDRD.
;rftruly040731C;Fixed greeting message
;rftruly040731B;Working with RF and UART (UART has buffer).
;rftruly040731A;Working with RF receiver.


;Receive data to 16 char buffer. Write to display after time-out or return.
;Scroll after character after lf is received. Echo a null after receiving return.



; Character receive and display for Truly MTC-C162DPLY-2N 2 line X 16 char LCD.
; Requires AT90S2313 or equivalent with 4 MHz clock.
;
; Below are the connections to the Truly Display
; Pin  Function (connection)
; 1 GND
; 2 VCC (+5V)
; 3 Contrast (0to +5V from wiper of 10 pot)
; 4 RS (Register Select 1=data 0=command)
; 5 R/W (tie to ground for write-only)
; 6 OE (Enable - data clocked on neg transition)
; 7-10 D0 - D3 lower 4 data bits (not used - ground these)
; 11-14 D4-D7 upper 4 data bits (connects to AVR90S2313 PB4 through PB7 respectively).
;
; The AT90S2313 routines to control the display, based on the Hitachi HD44780, and the initialization
; code in particular, are based on code originally published by Richard Hosking.
; The display is driven in the 4 bit mode. The Truly display uses a Samsung KS0070B controller
; that appears to differ from the Hitachi HD44780 controller in that the Samsung requires an
; additional 4 bit write operation during "Function set" when in 4 bit mode. This was accomplished
; by writing the "Function set" command twice to the controller twice instead of once.
; I suspect that this would work without modification with the Hitachi
; controller as the second write would be a redundant command for the Hitachi controller.
;
; Note that
;
; Below re the connections for the AT90S2313
; Pin  Function (Connection)
; VCC  +5V (decoupled)
; GND  ground
; XTAL1  Clock (see data sheet)
; XTAL2  Clcok (see data sheet)
; TXD  Serial out (RS-232 inverting buffer to remote device - NOT USED)
; RXD  Serial in (RS-232 inverting receive buffer)
; PD2-PD6 Unassigned (not connected)
; PB0,PB1 For RF link.
; PB2  R/S pin on Truly LCD (Truly module pin 4)
; PB3  OE pin on Truly LCD (Truly module pin 6)
; PB4-PB7 D4-D7 on Truly LCD (Truly module pins 11-14 respectively)
;

;definition of I/O
;B0 + comparitor input - Antenna Signal
;B1 - comparitor input - Antenna reference
;B2 Devider (bridge power) optional.MUST CHANGE  
;B3 LED (high to turn LED on) MUST CHANGE .



.include "2313def.inc"


.def charcount =r1;Number of characters displayed on line being written
.def    temp     =r19   ;Temporary register.(May not be R17).
.def RFChar  =r16;RF character I/O buffer (must be a high register)
.def flagreg  =r21;Flags
.def gpcount  =r23;Genral purpose counter (was YH in earlier version)
; YL  ;UART circular buffer write ponter.
; ZL  ;UART circultar buffer read pointer
; XL  ;16 char line buffer pointer

;The statements below establish I/O pins needed for RF operation.
.equ RFSigPort = PORTB;Port output signal is to appear on.
.equ RFSigDDR = DDRB;Data Direction Register for signal output
.equ RFSigPin = 0;Pin output signal is to appear on.

.equ LEDOutPort = PORTD;Indicator LED
.equ LEDOutDDR = DDRD
.equ LEDOutPin = 4

.equ CompPlusPort = PORTB;Comparitor noninverting input (input 0)
.equ CompPlusDDR = DDRB
.equ CompPlusPin = 0

.equ BridgePowerPort = PORTD;Power for voltage devider (bridging resistors)
.equ BridgePowerDDR = DDRD
.equ BridgePowerPin = 5

.equ lbufsiz  =10
.equ circbufsiz =64
.equ    OE  =8;Bit 3 port B display enable (also directly addressed).
.equ    RS  =4;Bit 2 in port B display register select (also directly addressed).

.equ cbufbot  =$60;Bottom of circular UART receive buffer.
.equ cbuftop  =$67;Top of circular UART receive buffer.

.equ lbufbot  =$70;Bottom of display line buffer.
.equ lbuftop  =$7F;Top of display line buffer.


;Baudrate Calculation
.equ clock  = 4000000 ;clock frequency
.equ baudrate = 9600  ;choose a baud rate
.equ baudconstant = (clock/(16*baudrate))-1



;Flagreg bit assignments
; bit 0  Pending linefeed if high.
; bit 1  
; bit 2
; bit 3
; bit 4
; bit 5
; bit 6
; bit 7

;Memory uage:
;Ring buffer from $60 through $67
;Line buffer from $70 to $7F

;******************************

.cseg
.org $00
rjmp start  ;Reset
.ORG $0006  
rjmp timer0service ;Timer/counter compare interrupt
.ORG $0007
rjmp UartRecInt
.ORG $000A
rjmp comparitorservice;Service comparitor interupt




.include "2x16lcd.inc"
.include "vlfcw2313.inc";Load VLFCW routines after last vector assignment
  ;but before start of application code..


HelloString:;TEXT TO BE TYPED ON FIRST LINE WHEN POWER IS APPLIED
.db "9600 1 N 040802A"
.db 00,00



start:
ldi  temp,RAMEND     ;Init Stack Pointer
out  SPL,temp

ldi temp,0b00000000;No weak pullups.
out PORTB,temp
ldi     temp,0b11111100    
       out     DDRB,temp;PORTB = all outputs except bits 0,1
       
       ldi temp,0b11111111;Weak pullups on inputs
       out PORTD,temp
       ldi temp,0b00000000;PORTD - all inputs
       out DDRD,temp  
       
ldi flagreg,$00;Set all flags to zero.
ldi temp,$00
mov charcount,temp

ldi temp,baudconstant
out ubrr,temp;load baudrate
sbi ucr,rxen;Enable the receiver..

rcall ClearLineBuffer;Initialize line buffer.
rcall InitDisplay;Initialize LCD display module,

  rcall sendhello;write line 1 power-up information
rcall Hometwo ;Position cursor for input on line two.


clr XH ;Clear XH, YH, ZY for processors with 16 bit RAM addressing
clr YH
clr ZH
ldi YL,cbufbot;Set Y and Z circ buff pointers to bottom.
ldi ZL,cbufbot
sbi UCR,7 ;Enable UART Interrupt.
sei  ;Global interrupt flag set (enabled).

forever:;Waiting for new data from circular buffer


getchar:
rcall ReceiveRFByte ;Wait for character to be received
brcs RFcharRec

   ;Get waiting char from circular buffer if there is one.
cp YL,ZL ;Is circular buffer read pointer alredy pointing to latest entry?
breq getchar ;If so, there is no new data in the buffer.
ld RFchar,Z+;If pointers are not equal, then read next char in buffer.
cpi ZL,cbuftop + 1;Advance circular buffer read pointer to next value.
brne NoZeroZL;If end of buffer, wrap around to start of buffer.
ldi ZL,cbufbot
NoZeroZL:

RFcharRec:

cpi RFchar,$1F;If not a control char branch to displayable char routine..
brpl ItsDisplayable
   
cpi RfChar,$0D;If this is a carriage return character,
brne noCR ;Set cursor to start of bottom line.
ldi XL,lbufbot;Its a CR so set ponters back to start of line.
ldi temp,$00
mov charcount,temp
rcall hometwo ;Put cursor back in first column of line two.
noCR:

cpi RfChar,$0A;If its a linfeed char then
brne NotALineFeed;set linfeed pending flag.
ori flagreg,0b00000001
NotALineFeed:

rjmp Buffdone

   


ItsDisplayable:;If not a control char then do line feed if pending then
 ;write to display and to line buffer.
 
sbrc flagreg,0;If linefeed i spending, then do it
rcall linefeed
 
cpi XL,lbuftop+1;Don't store if buffer at limit.
breq  Xfull
st X+,RFchar
mov temp,RFchar
rcall SendData
Xfull:

Buffdone:
Buffempty:
rjmp forever



SendHello:;Send HelloString
  rcall Homeone
ldi     ZH,high(2*HelloString); Load high part of byte address into ZH
ldi     ZL,low(2*HelloString); Load low part of byte address into ZL
moretosend:
lpm   ; Load byte from program memory into r0
tst r0  ; Check if we've reached the end of the message
breq finishsendstering; If so, return
mov temp,r0
rcall SendData
adiw ZL,1  ; Increment Z registers
rjmp moretosend
finishsendstering:
    ret
   




linefeed:;Handle a linefeed char
;Clear line 1 (top line), copy line two to line one, clear
;line two, the position the cursor in first column of line two.
push gpcount
rcall hometwo ;Put cursor at start of line 2 so it can be cleared.
ldi gpcount,$10 ;Number of chars in line.
clearmore:

ldi temp,$20;Fill line with spaces (erase).
rcall SendData
dec gpcount
brne clearmore

rcall homeone ;Copy line buffer to line 1, reset XL to bottom.
ldi XL,lbufbot
ldi temp,$00
mov charcount,temp
MoreToCopy:
ld temp,X+
rcall SendData
cpi XL,lbuftop + 1
brne MoreToCopy
rcall ClearLineBuffer
andi flagreg,$0b11111100;Clear linefeed pending and enable flagsb.
rcall hometwo
pop gpcount
ret  ;Done


ClearLineBuffer:;Fill line buffer with spaces, set XL to bottom.
ldi XL,lbufbot
ldi temp,$00
mov charcount,temp
ldi temp,$20
MoreToSpace:
st X+,temp
cpi XL,lbuftop + 1
brne MoreToSpace
ldi XL,lbufbot
ret




recchar:  
sbis usr,rxc ;Wait for a char.
rjmp recchar
in RFchar,udr;Read the char.
ret  



UartRecInt:;Uart interrupt service -Write received char into a circular buffer
rcall recchar  ;Get the char from the UART.
st Y+,RFchar
cpi YL,cbuftop + 1
brne NoZeroYL2
ldi YL,cbufbot
NoZeroYL2:
reti



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