 
by Michael Brown of Instant Net Solutions www.KillerPCs.net
Code:
;---------------------------------------------------------------------------------------------
;       HEADER:
;---------------------------------------------------------------------------------------------
              LIST          P=16f84a 
              RADIX         DEC 
              INCLUDE       "p16f84a.inc" 
              __CONFIG      _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
              
;  This program and the code/routines contained within are Copyright 2001,2003 by michael brown.  It may
;  not be used for commercial purposes without written consent from the Copyright holder (me).  It  
;  is free for personal use as long as this Copyright message is kept intact.  If commercial
;  usage is desired, please contact michael brown via e-mail at n5qmg@amsat.org to make licensing 
;  arrangements.  I'm not trying to be a greedy jerk, but I have to eat too.  ;-)  
;
;  73's de N5QMG
;---------------------------------------------------------------------------------------------
#define       Clock_Freq    4000000
#include "wait.mac"
;---------------------------------------------------------------------------------------------
;       EQUATES:
;---------------------------------------------------------------------------------------------
RS            equ           0                ;LCD's pin 4 should be connected to PORTB.0
RW            equ           1                ;LCD's pin 5 should be connected to PORTB.1
EN            equ           2                ;LCD's pin 6 should be connected to PORTB.2
#define       LCD_PORT      PORTB            ;LCD_PORT implies use of bits 4-7 for data lines to LCD
#define       LCD_RS        LCD_PORT, RS
#define       LCD_RW        LCD_PORT, RW
#define       LCD_EN        LCD_PORT, EN
#define       LCD_DAT7      LCD_PORT, 7
#define       LCD_DAT6      LCD_PORT, 6
#define       LCD_DAT5      LCD_PORT, 5
#define       LCD_DAT4      LCD_PORT, 4
#define       YEL_LED       PORTA, 0
#define       RED_LED       PORTA, 1
#define       INTSCOPE      PORTA, 2
#define	      MAIN_SCOPE    PORTA, 3
#define       ONE_WIRE      PORTA, 4          ;Dallas 1-wire bus
MAX_DEVICES   equ           4                 ;Maximum number of 1-wire devices to find
STARTOFRAM    equ           0x0C              ;First Usable RAM Location for 16f84
ENDOFRAM      equ           0x4F              ;Last Usable RAM Location for 16f84
;
; General Purpose Temp Storage
;
              cblock STARTOFRAM
OneWireByte
SOURCE
DEST
TEMP0
TEMP1
TEMP2
tempone
temptwo
;
; ISR Register Save Areas
;
;INT_FLAGS
;W_TEMP
;STATUS_TEMP
;FSR_TEMP
;
; ISR Loop Control
;
;LoopCntH
;LoopCntL
;
; Variables Relating to LCD Control
;
CursorRow                                     ; Current Cursor Position
CursorCol
AbsAddr                                       ; Absolute cursor position (start address of CursorRow + CursorCol)
SrcRowNum                                     ; Source Row Number
DestRowNum                                    ; Destination Row Number
SrcCharAddr                                   ; DDRAM address in LCD
DestCharAddr                                  ; DDRAM address in LCD
RowLoopCtr                                    ; For Scrolling the screen
CharLoopCtr                                   ; Same as above
LCD_Data
TEMPX
;
; Work areas
;
rombit_idx
bits
ctr_1wire
curr_discrep
last_discrep
done_flag
return_value
; One-Wire work area
work0                       ; CRC (8 bits)
work1                       ; Serial # (48 bits)
work2                       ; "
work3                       ; "
work4                       ; "
work5                       ; "
work6                       ; "
work7                       ; Family Code (8 bits)
;Sensor 0 Storage
ts00
ts01
ts02
ts03
ts04
ts05
ts06
ts07
;Sensor 1 Storage
ts10
ts11
ts12
ts13
ts14
ts15
ts16
ts17
;Sensor 2 Storage
ts20
ts21
ts22
ts23
ts24
ts25
ts26
ts27
;Sensor 3 Storage
ts30
ts31
ts32
ts33
ts34
ts35
ts36
ts37
              endc
;---------------------------------------------------------------------------------------------
;       START:
;---------------------------------------------------------------------------------------------
              org         0x000
              goto        Start
              org         0x004
;              movwf       W_TEMP              ;Save everything               
;              swapf       STATUS, W
;              movwf       STATUS_TEMP
;              movfw       FSR
;              movwf       FSR_TEMP
;
; Interrupt handler right here
;
;              bsf         INTSCOPE            ;Mark start of interrupt routine
;              bcf         INTSCOPE            ;Mark end of interrupt routine (for timing)
;
; Restore everything and return
;
;IntExit
;              movfw       FSR_TEMP
;              movwf       FSR
;              swapf       STATUS_TEMP, W
;              movwf       STATUS
;              swapf       W_TEMP, F
;              swapf       W_TEMP, W
              retfie
;-------------------------------------------------------------
;Store_Bit -- take bit A (bits.1) and store into work0..work7
;             at bit offset rombit_idx (1 relative)
;  Entry:
;        bits - contains 2 bits read from 1 wire bus bits.1 is the one to store
;        rombit_idx - contains one relative bit offset from rom work area (work0..work7)
;                     of bit to store
;  Exit:
;        bits.1 -> work0..work7(rombit_idx)
;-------------------------------------------------------------
Store_Bit
              call      SetupFSR         ;convert rombit_idx to something we can use
;Determine if we need to set a bit (1) or clear a bit (0)
              movlw     HIGH SetWorkBit
              movwf     PCLATH
              
              rrf       bits, W          ;get bit.1 value right justified into W
              andlw     b'00000001'      ;maintain sanity
              addwf     PCL, F           ;quick test for 0 or 1
              goto      ClrWorkBit       ;must be 0 (clr bit)
SetWorkBit                               ;must be 1 (set bit)
              clrc
              rlf       TEMP2, W         ;get bit position * 2 (0, 2, 4 .. 14)
              addwf     PCL, F           ;bump PC, turn bit on then return
              bsf       INDF, 7
              return
              bsf       INDF, 6
              return
              bsf       INDF, 5
              return
              bsf       INDF, 4
              return
              bsf       INDF, 3
              return
              bsf       INDF, 2
              return
              bsf       INDF, 1
              return
              bsf       INDF, 0
              return
ClrWorkBit
              movlw     HIGH ClrWorkBit
              movwf     PCLATH
              clrc
              rlf       TEMP2, W         ;get bit position * 2 (0, 2, 4 .. 14)
              addwf     PCL, F           ;bump PC and turn it off then return
              bcf       INDF, 7
              return
              bcf       INDF, 6
              return
              bcf       INDF, 5
              return
              bcf       INDF, 4
              return
              bcf       INDF, 3
              return
              bcf       INDF, 2
              return
              bcf       INDF, 1
              return
              bcf       INDF, 0
              return
;-------------------------------------------------------------
;GetWorkBit --
;             at bit offset rombit_idx (1 relative)
;  Entry:
;        rombit_idx - contains one relative bit offset from rom work area (work0..work7)
;                     of bit to retrieve value of
;  Exit:
;        work0..work7(rombit_idx) -> W
;--------------------------------------------------------------
GetWorkBit
              call      SetupFSR         ;point to the bit in question
              movlw     HIGH GetWorkBit
              movwf     PCLATH
              clrc
              rlf       TEMP2, W         ;get bit position * 2 into w
              addwf     TEMP2, W         ;compute w = bit offset * 3 (0, 3, 6 ...)
              addwf     PCL, F           ;bump PC to jump to appropriate test
;Bit 0
              btfss     INDF, 7          ;Is bit set(1)
               retlw    d'0'             ; No, return 0
              retlw     d'1'             ; Yes, return 1
;Bit 1
              btfss     INDF, 6          ;Is bit set(1)
               retlw    d'0'             ; No, return 0
              retlw     d'1'             ; Yes, return 1
;Bit 2
              btfss     INDF, 5          ;Is bit set(1)
               retlw    d'0'             ; No, return 0
              retlw     d'1'             ; Yes, return 1
;Bit 3
              btfss     INDF, 4          ;Is bit set(1)
               retlw    d'0'             ; No, return 0
              retlw     d'1'             ; Yes, return 1
;Bit 4
              btfss     INDF, 3          ;Is bit set(1)
               retlw    d'0'             ; No, return 0
              retlw     d'1'             ; Yes, return 1
;Bit 5
              btfss     INDF, 2          ;Is bit set(1)
               retlw    d'0'             ; No, return 0
              retlw     d'1'             ; Yes, return 1
;Bit 6
              btfss     INDF, 1          ;Is bit set(1)
               retlw    d'0'             ; No, return 0
              retlw     d'1'             ; Yes, return 1
;Bit 7
              btfss     INDF, 0          ;Is bit set(1)
               retlw    d'0'             ; No, return 0
              retlw     d'1'             ; Yes, return 1
;---------------------------------------------------------------------
;Lookup_TS -- Return address of start of 8 byte entry within TS table
;  Entry:
;        W contains slot number within TS table (0,1,2, or 3)
;  Exit:
;        W contains address of beginning of slot pointed to by W
;---------------------------------------------------------------------
Lookup_TS
              andlw      b'00000011'
              addwf      PCL, F
              retlw      ts00
              retlw      ts10
              retlw      ts20
              retlw      ts30
;---------------------------------------------------------------------------------------------
;
; lookup_row - Lookup ddram address of beginning of row for LCD
;
;---------------------------------------------------------------------------------------------
lookup_row    addwf       PCL, F              ; bump PC by zero relative row number
              retlw       0x00                ; start of row 0
              retlw       0x40                ;          row 1
              retlw       0x14                ;          row 2
              retlw       0x54                ;          row 3
              
;----------------------------------------------------------------------------------------
; SetupFSR -- Point FSR at byte within work area determined by rombit_idx
;   Entry:
;         rombit_idx contians bit number (one relative) we need to get to
;   Exit:
;         FSR - pointing at byte within work0..work7
;         TEMP1 - zero relative byte offset (0,1,..7)
;         TEMP2 - zero relative(0,1,..7) bit offset within byte
;----------------------------------------------------------------------------------------
SetupFSR                                 ;Setup FSR, TEMP1(byte offset), and TEMP2(bit offset)
              decf      rombit_idx, W    ;convert index to 0 relative
              sublw     d'63'            ;form compliment of rombit_idw 0-63->63-0
              movwf     TEMP1            ;  and temp byte offset area
              andlw     b'00000111'      ;strip off byte offset leaving bit offset only
              movwf     TEMP2            ; and save into temp bit offset area
              
              clrc                       ;right justify the byte offset in TEMP1
              rrf       TEMP1, F         ; by right shifting
              clrc                       ;  and stripping 3 LSB's 
              rrf       TEMP1, F
              clrc
              rrf       TEMP1, F
;Get FSR pointing at appropriate byte in work area (work0, work1 ...)
              movlw     work0            ;Point FSR at beginning of work area
              movwf     FSR
              movfw     TEMP1            ;get byte offset (0 relative)
              addwf     FSR, F           ; point FSR straight at it
              return
;---------------------------------------------------------------------------------------------
;
;  Main level code begins here
;
;---------------------------------------------------------------------------------------------
Start
              bsf         STATUS, RP0          ;Switch to Bank 1
              movlw       b'00000000'          ;Define I/O on Port B (all outputs)
              movwf       TRISB & 0x07F
              movlw       b'00000'             ;Define I/O on Port A (all outputs)
              movwf       TRISA & 0x07F
              bcf         STATUS, RP0          ;Back to Bank 0
              
              clrf        PORTA
              clrf        PORTB
Main
; Waste a couple of seconds between itterations
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              Wait      100 Millisecs, 0
              call        LCD_Init            ;Initialize the LCD
              movlw       'I'                 ;Display Init message
              call        LCD_Txt
              movlw       'n'
              call        LCD_Txt
              movlw       'i'
              call        LCD_Txt
              movlw       't'
              call        LCD_Txt
              movlw       'i'
              call        LCD_Txt
              movlw       'a'
              call        LCD_Txt
              movlw       'l'
              call        LCD_Txt
              movlw       'i'
              call        LCD_Txt
              movlw       'z'
              call        LCD_Txt
              movlw       'e'
              call        LCD_Txt
              movlw       'd'
              call        LCD_Txt
              movlw       ' '                 ;Display Version
              call        LCD_Txt
              movlw       'V'
              call        LCD_Txt
              movlw       'e'
              call        LCD_Txt
              movlw       'r'
              call        LCD_Txt
              movlw       '.'
              call        LCD_Txt
              movlw       ' '
              call        LCD_Txt
              movlw       '0'
              call        LCD_Txt
              movlw       '.'
              call        LCD_Txt
              movlw       '1'
              call        LCD_Txt
              movlw       0x03                ;position to bottem row
              movwf       CursorRow
              movlw       0x13                ;position to last column
              movwf       CursorCol
       
              call      Search_1Wire_init
_search_next
;              movlw       'a'      
;              call        LCD_Print
              call      Search_1Wire     ;Initiate a search              
;              movlw       'b'    
;              call        LCD_Print
              
              btfss     return_value, 0  ;See if we found anything
               goto     _search_done     ;Nope, we are done
;              movlw       'c'    
;              call        LCD_Print              
              
              movlw     work0            ;get address of work area
              movwf     SOURCE           ;make it the source for block move
              
              movlw     HIGH Lookup_TS
              movwf     PCLATH
              movfw     ctr_1wire        ;get device count
              call      Lookup_TS        ;get address of its entry
              movwf     DEST             ;set as destination for block move
              call      Block_Move       ;copy the work area off to storage
              call      Print_Work_Area               
              incf      ctr_1wire, F     ;count the one just found
              movlw     MAX_DEVICES
              xorwf     ctr_1wire, W
              
              btfss     STATUS, Z        ;is it 4 devices found yet
               goto     _search_next     ; No, try for another
_search_done
;              movlw       'X'    
;              call        LCD_Print              
              goto      Main
Print_Work_Area
              movfw     work0
              call      LCD_Hex
              movlw     ':'
              call      LCD_Print
              movfw     work1
              call      LCD_Hex
              movfw     work2
              call      LCD_Hex
              movfw     work3
              call      LCD_Hex
              movfw     work4
              call      LCD_Hex
              movfw     work5
              call      LCD_Hex
              movfw     work6
              call      LCD_Hex
              movlw     ':'
              call      LCD_Print
              movfw     work7
              call      LCD_Hex
              movlw     0x13             ;position to last column so next byte starts on new line
              movwf     CursorCol
              
              return
              
;-------------------------------------------------------------------
;
; Search the Dallas 1-Wire Bus
;
;-------------------------------------------------------------------
Search_1Wire_init
              clrf      ctr_1wire        ;init device counter(effectively clears table)
              clrf      work0            ;clear the work area to zeros
              clrf      work1
              clrf      work2
              clrf      work3
              clrf      work4
              clrf      work5
              clrf      work6
              clrf      work7
              clrf      last_discrep     ;init the bit position of last descrepancy
              clrf      done_flag        ;set status to not done
              return
Search_1Wire
              clrf      return_value     ;set return flag to false
              btfss     done_flag,0      ;Are we done yet?
               goto     Do_reset         ; No, start a search
              clrf      done_flag        ; Yes, init this for next time???
              goto      Wrapup           ;  and get on out of here
Do_reset
              call      Reset_1wire
              clrf      rombit_idx       ;set rom bit index to 1
              incf      rombit_idx, F
              clrf      curr_discrep     ;set descrepancy marker to 0
              movlw     h'f0'            ;send search rom
              movwf     OneWireByte
              call      Sendbyte_1wire   ; command to devices
              
              bsf       MAIN_SCOPE
              bcf       MAIN_SCOPE
Get_2bits             
              call      Readbit_1wire    ;read bit a from bus and
              movwf     bits             ; save it
              clrc                       ;clear the carry flag
              rlf       bits, F          ;shift bit A over to the left
              call      Readbit_1wire    ;read bit B from bus and 
              iorwf     bits, F          ; save it
              movlw     HIGH lookup_1x
              movwf     PCLATH
              movfw     bits
lookup_1x
              addwf     PCL, F           ;decode the bits read
              goto      bits_00          ;collision detected
              goto      bits_01          ;0 read
              goto      bits_10          ;1 read
              goto      bits_11          ;nobody there
bits_00                                  ;collision detected
;Does rombit_idx = last_discrep
;              movlw     '0'
;              call      LCD_Print
              movfw     rombit_idx
              xorwf     last_discrep, W
              btfss     STATUS, Z        ;Does rombit_idx = last_discrep
               goto     _chknxt          ; No, check other stuff
              movlw     b'10'            ; Yes, pretend we read a 1
              movwf     bits
              call      Store_Bit        ;Store a 1 into work area
              goto      ack_bus
_chknxt
              movfw     last_discrep     ;get current bit position
              subwf     rombit_idx, W    ;compare to last discrepancy position
;is rombit_idx > last_discrep
              btfss     STATUS, C        
               goto     _chknx2          ; No, 
              movlw     b'01'            ; Yes, pretend we read a 0
              movwf     bits
              call      Store_Bit
;set discrepancy marker to rombit_idx
              movfw     rombit_idx       
              movwf     curr_discrep
              goto      ack_bus
_chknx2
;does rombits(rombit_idx) = 0 ?
              call      GetWorkBit       ;get bit located at work(rombit_idx)
              movwf     TEMP0            ; and save
              movlw     HIGH lookup_2x
              movwf     PCLATH
              movfw     TEMP0
lookup_2x
              addwf     PCL, F           ;quik test for 0 or 1
              goto      _zero            ; was 0
_one                                     ; was 1
              movlw     b'10'            ; Pretend we read a 1
              movwf     bits
              goto      ack_bus
_zero
              movlw     b'01'            ; Pretend we read a 0
              movwf     bits
;set discrepancy marker to rombit_idx
              movfw     rombit_idx       
              movwf     curr_discrep
              goto      ack_bus
              
bits_01                                  ;0 received
;              movlw     '1'
;              call      LCD_Print
              goto      _storit
bits_10                                  ;1 received
;              movlw     '2'
;              call      LCD_Print
_storit
              call      Store_Bit        ;Save it into work area at rombit_idx offset
; Send rombit(rombit_idx) to 1-wire bus
ack_bus
;             call      GetWorkBit
              clrc                       ;clear the carry flag and
              rrf       bits, W          ; get bit A into W
              call      Sendbit_1wire    ;send bit A to wire
; Increment rombit_idx
              incf      rombit_idx, F    ;bump pointer to next location
; Is rombit_idx > 64?
              movfw     rombit_idx       ;see if index > 64
              sublw     d'65'            ; (i.e. = 65)
              btfss     STATUS, Z
               goto     Get_2bits        ;if not, loop back for more
;set last discrepancy to descrepancy marker
              movfw     curr_discrep     
              movwf     last_discrep
;is last discrepancy = 0?
              btfsc     STATUS, Z        
               incf     done_flag, F     ;yes, set done flag
              movlw     d'1'             ;either way, set return value to true
              movwf     return_value
              goto      Wrapup
              
bits_11                                  ;nothing answered on the bus
              movlw     'D'
              call      LCD_Print
              movlw     'e'
              call      LCD_Print
              movlw     'a'
              call      LCD_Print
              movlw     'd'
              call      LCD_Print
              movlw     'B'
              call      LCD_Print
              movlw     'e'
              call      LCD_Print
              movlw     'e'
              call      LCD_Print
              movlw     'f'
              call      LCD_Print
              clrf      last_discrep
              goto      Wrapup
              
Wrapup
              return
;---------------------------------------------------------------------
;Reset the one wire bus
;---------------------------------------------------------------------
Reset_1wire
              bcf ONE_WIRE               ;Pull it low
              Wait 480 Microsecs, 0      ;Hold it till they are reset
              bsf ONE_WIRE               ;Let it idle back up
;
;*** suppose to check for ack from devices here, but why??  I'm leaving it out for now
;
              Wait      500 Microsecs, 0
              return
;---------------------------------------------------------------------
;Send bytes and bits on the one wire bus
;  BYTE -- Send a byte from OneWireByte to the one wire bus
;  bit  -- Send bits, 1 to the one wire bus
;---------------------------------------------------------------------
Sendbyte_1wire
              movlw     d'8'
              movwf     TEMP0
;              bsf       MAIN_SCOPE
;              bcf       MAIN_SCOPE
_send_1w_lp
              clrf      TEMP1            ;Clear work area
              bcf       TEMP1, 0         ;Assume sending 0
              clrc                       ;Fill new bits with 0
              rrf       OneWireByte, F   ;Load CARRY with bit to send
              btfsc     STATUS, C        ;See what we are sending
               bsf      TEMP1, 0         ; must be a 1
              movfw     TEMP1            ;Load up the bit and
              call      Sendbit_1wire    ; send it out
              decfsz    TEMP0, F         ;Is it 8 bits yet
               goto     _send_1w_lp      ; not yet
              return
Sendbit_1wire
              movwf     TEMP1
              bcf       ONE_WIRE         ;Pull it low
              btfsc     TEMP1, 0 
               bsf      ONE_WIRE        ;end of low pulse if bit was a 1
              Wait      58 Microsecs,0   ; (Tslot + Trec) - Tlow1
              bsf       ONE_WIRE        ;end of low pulse if 0 (1 no change)
              Wait      1 Microsecs,4    ; Trec
              return
;---------------------------------------------------------------------
;Receive bytes and bits from the one wire bus
;  BYTE -- Read a byte from the one wire and stick into OneWireByte
;  bit  -- Read a bit sticking it into bits, 1
;---------------------------------------------------------------------
Readbyte_1wire
              movlw     d'8'
              movwf     TEMP0
_read_1w_lp
              call      Readbit_1wire
              movwf     TEMP1            ;Save the bit read
              clrc                       ;Assume bit is 0
              btfsc     TEMP1, 0         ;Check bit
               setc                      ; its a 1
              rrf       OneWireByte, F   ;Rotate bit into IO area
              decfsz    TEMP0, F         ;Is it 8 bits yet
               goto     _read_1w_lp      ; not yet
              movfw     OneWireByte      ; yes, return with byte read in W
              return                     ;
Readbit_1wire
              bcf       ONE_WIRE         ;Pull it low and
              nop
              bsf       ONE_WIRE         ; release for a clock pulse
              clrf      TEMP1            ;Assume incomming bit is 0
              Wait      12 Microsecs, 0  ;Give device time to respond
              btfsc     ONE_WIRE         ;What are we receiving?
               bsf      TEMP1, 0         ; must be a 1
              Wait      47 Microsecs, 0  ;Wait out the rest of the cycle
              movfw     TEMP1
              
              return
;---------------------------------------------------------------------
;Block_Move -- Move 8 Bytes from SOURCE to DEST
;  Entry:
;        SOURCE should be pointing at place to move from
;        DEST should be pointing at destination place to store block             
;  Exit:
;        SOURCE ,DEST, TEMP0, TEMP1, FSR will be destroyed. However,
;         the data will be moved ;-D
;---------------------------------------------------------------------
Block_Move
              movlw      d'8'
              movwf      TEMP0
_move_lp
              movfw      SOURCE          ;Set up source pointer
              movwf      FSR
              movfw      INDF            ;get the byte
              movwf      TEMP1           ; and save it
              
              movfw      DEST            ;Set up destination pointer
              movwf      FSR
              movfw      TEMP1           ;pick up saved byte
              movwf      INDF            ; and store it (now it is moved to destination)
              incf       SOURCE, F       ;adjust pointers
              incf       DEST, F
              decfsz     TEMP0, F
               goto      _move_lp                            
              return
;---------------------------------------------------------------------------------------------
;
; LCD_Print - Print a character to the LCD w/proper scrolling and wrapping
;             Code is setup for a 4 * 20 LCD Display
;
;---------------------------------------------------------------------------------------------
LCD_Print
              movwf       TEMPX
              incf        CursorCol, F        ;Bump the cursor
              movfw       CursorCol           ;Load it
              xorlw       0x14                ;Is it running off the right side of the screen
              btfss       STATUS, Z
               goto       noscroll            ;No, go on and print it
;              bsf         MAIN_SCOPE
              call        scroll_scr          ;Yes, scroll the display
              clrf        CursorCol           ;Set cursor to beginning of line
;              bcf         MAIN_SCOPE
noscroll
              movlw     HIGH lookup_row
              movwf     PCLATH
              movfw       CursorRow           ;Get current row into W
              call        lookup_row          ;Convert to start address of row
              addwf       CursorCol, W        ;Add in the column position
              movwf       AbsAddr             ;Store absolute address
              iorlw       b'10000000'         ; convert ABS Address to lcd command to set DDRAM address
              call        LCD_Cmd             ;Set DDRAM address
              movfw       TEMPX               ;Load the character received and
              goto       LCD_Txt              ; display it
;---------------------------------------------------------------------------------------------
;
; scroll_scr - Scroll Screen by moving data up a line at a time and then
;               filling the bottom row with blanks.
;
;---------------------------------------------------------------------------------------------
scroll_scr
              movlw       0x03                ; Move three rows total 1->0, 2->1, 3->2
              movwf       RowLoopCtr          ;
              clrf        DestRowNum          ; Destination starts at row 0
              movlw       0x01                ; Source row starts at row 1
              movwf       SrcRowNum
move_row
              movlw     HIGH lookup_row
              movwf     PCLATH
              movf        DestRowNum, W       ; Get destination row number and
              call        lookup_row          ;  convert to a char address
              movwf       DestCharAddr        ;   and save it
              movlw     HIGH lookup_row
              movwf     PCLATH
              movf        SrcRowNum, W        ; Get source row number and
              call        lookup_row          ;  convert to a char address
              movwf       SrcCharAddr         ;   and save it
              movlw       0x14                ; twenty chars per line
              movwf       CharLoopCtr
move_chars
;             read the source character
              movf        SrcCharAddr, W      ; Load DDRAM address into W
;              call        LCD_ReadRam         ; Fetch the character stored there
              iorlw       b'10000000'         ;Turn on the high bit (Set DDRAM Address)
              call        LCD_Cmd             ;Write the command to set the address
              call        LCD_In              ;Read the DDRAM value at current position
              movwf       LCD_Data            ;   and save it
;if bottom row move a space to it while we are here
              movf        SrcRowNum,W         ; See which row we are on
              xorlw       0x03                ; Is it the bottom one
              btfss       STATUS, Z           
               goto       wrtdest             ; No, just write the destination location
;have to reposition the cursor since it insists on moving itself after a read
              movf        SrcCharAddr, W      ; Load DDRAM address into W
              iorlw       b'10000000'         ; make into a command to set address
              call        LCD_Cmd             ; issue the command
              movlw       ' '                 ; Load up a space character
              call        LCD_Txt             ;  and clear the character in the bottom row
;write to destination address
wrtdest
              movf        DestCharAddr, W     ; Load Destination DDRAM address
              iorlw       b'10000000'         ; make into a command to set address
              call        LCD_Cmd             ; issue the command
              movf        LCD_Data, W         ; Get the saved character
              call        LCD_Txt             ; Write character to destination address
              incf        SrcCharAddr, F
              incf        DestCharAddr, F
              decfsz      CharLoopCtr, F
               goto       move_chars
row_done
              incf        DestRowNum, F       ; Point to next row
              incf        SrcRowNum, F        ; Same thing
              decfsz      RowLoopCtr, F       ; Decrement loop counter and
               goto       move_row            ;  move next row
              return
     
;---------------------------------------------------------------------------------------------
;
;  LCD_ReadRam - Return character stored at LCD DDRAM Location
;
;---------------------------------------------------------------------------------------------
LCD_ReadRam
;              movwf       TEMP3               ;Save the address
              iorlw       b'10000000'         ;Turn on the high bit (Set DDRAM Address)
              call        LCD_Cmd             ;Write the command to set the address
              call        LCD_In              ;Read the DDRAM value at current position
              return        
;---------------------------------------------------------------------------------------------
;  LCD_Txt - Write ASCII byte in W to LCD
;
;---------------------------------------------------------------------------------------------
LCD_Txt       
              movwf       TEMP1               ;Store w for LCD_Out
              call        LCD_BF              ;Get the busy flag
              andlw       b'10000000' 
              btfss       STATUS, Z           ;Is busy flag set?
               goto       $ - 3               ;  yes.  Re-test busy flag.
              bsf         LCD_RS              ;This is DATA.
              goto        LCD_Out             ;Execute part of LCD_Cmd
;---------------------------------------------------------------------------------------------
;  LCD_Cmd  ROM: 12 words       RAM: TEMP0, TEMP1 
;---------------------------------------------------------------------------------------------
LCD_Cmd
              movwf       TEMP1               ;Store w
              call        LCD_BF              ;Get the busy flag
              andlw       b'10000000'
              btfss       STATUS, Z           ;Is busy flag set?
               goto       $ - 3               ;  Yes.  Re-test busy flag.
              bcf         LCD_RS              ;This is a COMMAND.
LCD_Out       bcf         LCD_RW              ;This is a WRITE.
              movf        TEMP1, w            ;Restore w.
              call        LCD_Nbl             ;Output the upper four bits of W.
              swapf       TEMP1, w            ;Swap nybbles (and put result in W).
              call        LCD_Nbl             ;Output the lower four bits of W.
              return                          ;Done--Return.
;----------------------------------------------------------------------------------------------
;
;  LCD_In - Return byte stored in CGRAM at currently addressed location (cursor position)
;
;----------------------------------------------------------------------------------------------
LCD_In
              call        LCD_BF              ;Get the busy flag
              andlw       b'10000000' 
              btfss       STATUS, Z           ;Is busy flag set?
               goto       LCD_In              ;  Yes.  Re-test busy flag.
              bsf         LCD_RS              ;This is DATA operation. 
              bsf         LCD_RW              ;This is a READ.
              bsf         STATUS, RP0         ;Select Bank 1.
              bsf         TRISB & 0x07F, 4    ;Make ports input
              bsf         TRISB & 0x07F, 5
              bsf         TRISB & 0x07F, 6
              bsf         TRISB & 0x07F, 7
              bcf         STATUS, RP0         ;Bank 0 please
              bsf         LCD_EN              ;Clock out the RS and RW bits.
              movf        LCD_PORT, w         ;Get, 
              andlw       b'11110000'         ;  mask, and
              movwf       TEMP0               ;    store the upper nybble into a temp area
              bcf         LCD_EN              ;Clock in the upper nybble
              bsf         LCD_EN              ;Clock in the lower nybble
              movf        LCD_PORT, w         ;Get and
              andlw       b'11110000'         ;  mask the lower nybble 
              bcf         LCD_EN
              swapf       TEMP0, f            ;Flip the temp area around backwards and
              iorwf       TEMP0, f            ; OR in the lower nybble to the upper half of temp
              swapf       TEMP0, w            ;Repair and load the byte into w.
              return                          ;Done -- return.
;---------------------------------------------------------------------------------------------
;
;  LCD_Hex - Take byte in W and LCD_Print it in HEX 
;   
;---------------------------------------------------------------------------------------------
LCD_Hex
              movwf       TEMP2               ;Store w
              swapf       TEMP2, w            ;Get upper nybble of w
              andlw       b'00001111'
              call        LCD_Hex1            ;Convert upper nybble to ASCII
              call        LCD_Print           ;Output ASCII on LCD display
              movf        TEMP2, w            ;Get lower nybble of w
              andlw       b'00001111' 
              call        LCD_Hex1            ;Conver lower nybble to ASCII
              call        LCD_Print           ;Output ASCII on LCD display
              return                          ;Done--return.
LCD_Hex1
              addlw       0xF6                ;This routine converts a number in w to an 
              btfsc       STATUS, C           ;ASCII hex number.  Result in w.
               addlw      0x07
              addlw       0x3A
              return
;---------------------------------------------------------------------------------------------
;
;  LCD_Nbl - Writes one nibble contained in upper half of W to LCD
;
;---------------------------------------------------------------------------------------------
LCD_Nbl
              bsf         STATUS, RP0         ;Make LCD_PORT.4-7 Outputs
              bcf         TRISB & 0x07F, 4
              bcf         TRISB & 0x07F, 5
              bcf         TRISB & 0x07F, 6
              bcf         TRISB & 0x07F, 7
              bcf         STATUS, RP0
              bcf         LCD_RW              ;This is a WRITE command.
              bsf         LCD_EN              ;Clock out RS and RW. 
              iorlw       b'00001111'         ;Write the upper four bits in W to the upper 
              andwf       LCD_PORT, f         ; four bits in LCD_PORT.
              andlw       b'11110000' 
              iorwf       LCD_PORT, f 
              bcf         LCD_EN              ;Clock out the four data bits.
              return                          ;Done--Return. 
;---------------------------------------------------------------------------------------------
;
;  LCD_BF - Do a busy flag read of the LCD returning in W': BF A6 A5 A4 A3 A2 A1 A0
;
;---------------------------------------------------------------------------------------------
LCD_BF
              bcf         LCD_RS              ;This is a DATA operation. 
              bsf         LCD_RW              ;This is a READ command.
              bsf         STATUS, RP0         ;Select Bank 1.
              bsf         TRISB & 0x07F, 4    ;Make ports input
              bsf         TRISB & 0x07F, 5
              bsf         TRISB & 0x07F, 6
              bsf         TRISB & 0x07F, 7
              bcf         STATUS, RP0
              bsf         LCD_EN              ;Clock out the RS and RW bits.
              movf        LCD_PORT, w         ;Get, 
              andlw       b'11110000'         ; mask, and
              movwf       TEMP0               ;  store the upper nybble into a temp area
              bcf         LCD_EN              ;Bring enable pin low after getting data
              bsf         LCD_EN              ;Clock in the lower nybble
              movf        LCD_PORT, w         ;Get and
              andlw       b'11110000'         ;  mask the lower nybble 
              bcf         LCD_EN
              swapf       TEMP0, f            ;Flip the temp area around backwards and
              iorwf       TEMP0, f            ; OR in the lower nybble to the upper half of temp
              swapf       TEMP0, w            ;Repair and load the byte into w.
              return                          ;Done -- return.
;---------------------------------------------------------------------------------------------
;
;  LCD_Init - That pretty much says it all
;
;---------------------------------------------------------------------------------------------
LCD_Init
              bcf         LCD_RS              ;The following will write to the HD44780's IR.
              Wait        10 Millisecs, 0
;
;Grab display per recommended way by setting to eight bit mode 3 times
;
              movlw       b'00111000'         ;Function set
              call        LCD_Nbl
              Wait        50 Microsecs, 0     ;Wait 50us
              movlw       b'00111000'         ;Function set
              call        LCD_Nbl
              Wait        50 Microsecs, 0     ;Wait 50us
              movlw       b'00111000'         ;Function set
              call        LCD_Nbl
              Wait        50 Microsecs, 0     ;Wait 50us
;
;Now that we have its attention, set it to nibble mode and initialize
;
              movlw       b'00101000'         ;Function Set -- 0 0 1 DL N F X X (nibble mode, 2lines, 5x7 font)
              call        LCD_Cmd
              movlw       b'00000001'         ;Clear Display -- 0 0 0 0 0 0 0 1
              call        LCD_Cmd
              Wait        1650 Microsecs, 0   ;Wait 1.65ms
              movlw       b'00000110'         ;Entry Mode Set -- 0 0 0 0 0 1 ID S (increment, no shifting)
              call        LCD_Cmd
              movlw       b'00001100'         ;Display Control -- 0 0 0 0 1 D C B (display on, no cursor, no blink)
              call        LCD_Cmd
              return
#include "delay.asm"
              end
+
Comments:
| file: /Techref/microchip/ibuttonsearch.htm, 44KB, , updated: 2013/1/11 13:09, local time: 2025/10/31 13:17, 
 
216.73.216.87,10-2-37-96:LOG IN | 
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://www.piclist.com/tecHREF/microchip/ibuttonsearch.htm"> PIC code to search the iButton bus (untested)</A> | 
| Did you find what you needed? | 
|  PICList 2025 contributors: o List host: MIT, Site host massmind.org, Top posters @none found - Page Editors: James Newton, David Cary, and YOU! * Roman Black of Black Robotics donates from sales of Linistep stepper controller kits. * Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters. * Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated! * Contributors: Richard Seriani, Sr. | 
| Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! | 
.