;
; =====================================================================
; Dallas TouchMemory routines
; (c) 1997 Pavel Korensky <pavelk@dator3.anet.cz>
;
; Changed for slave support by Ake Hedman, Eurosource
; <akhe@eurosource.se>
; =====================================================================
;
;
; Dallas TouchMemory commands - Touch Multikey specifically
;
LIST
; Supported commands
READ_ROM equ 0x33
MATCH_ROM equ 0x55
SEARCH_ROM equ 0xF0
ALARM_SEARCH_ROM equ 0xEC
SKIP_ROM equ 0xCC
WRITE_SCR equ 0x96
READ_SCR equ 0x69
COPY_SCR equ 0x3C
CONVERT_T equ 0x44
RECALL equ 0xB8
READ_POWER_SUPPLY equ 0xB4
; not supported commands
READ_ROM_2400 equ 0x0F
WRITE_PSW equ 0x5A
WRITE_SUB equ 0x99
READ_SUB equ 0x66
FAM_MULTIKEY equ 0x02
SEARCH_ROM equ 0xF0
WRITE_SCRATCHPAD equ 0x4E
READ_SCRATCHPAD equ 0xBE
COPY_SCRATCHPAD equ 0x48
; 1-Wire State machine
#define STATE_RESET_WAIT 0 ; Low detected can be a Reset pulse.
#define STATE_COMMAND_WAIT 1 ; Reset received/Presence sent.
#define STATE_READ_ROM 2
#define STATE_MATCH_ROM 3
#define STATE_SEARCH_ROM 4
#define STATE_ALARM_SEARCH_ROM 5
#define STATE_SKIP_ROM 6
#define STATE_WRITE_SCR 7
#define STATE_READ_SCR 8
#define STATE_COPY_SCR 9
#define STATE_CONVERT_T 10 ; used as generic command
#define STATE_RECALL 11
#define STATE_READ_POWER_SUPPLY 12
;*****************************************************************
;
; Some macros
;
;*****************************************************************
DSIN macro ; Set Dallas as input
bsf STATUS, RP0
bsf TRISA, DS_BIT
bcf STATUS, RP0
endm
DSOUT macro ; Set Dallas as output - 1
bsf DS_PORT, DS_BIT ; ### Fix, AH
bsf STATUS, RP0
bcf TRISA, DS_BIT
bcf STATUS, RP0
endm
IRQHL macro
bsf STATUS, RP0
bcf OPTION_REG,INTEDG
bcf STATUS, RP0
endm
IRQLH macro
bsf STATUS, RP0
bsf OPTION_REG,INTEDG
bcf STATUS, RP0
endm
;************************************************************
;
; Delay 67 us - For PRESENCE routine ( 4MHz )
; 65 us + call 2 us
;************************************************************
;D67us:
; movlw 0x14 ; 1
; movwf delay ; 1
;loop_d67:
; decfsz delay,1 ; 20 * 3 = 60
; goto loop_d67 ;
; nop ; 1
; nop ; 1
; retlw 0 ; 1
;************************************************************
; Set_Rom_Bit_At_Index_To_One
;************************************************************
Set_Rom_Bit_At_Index_To_One:
call Get_Byte_For_Bit
call Get_Mask_From_Bit_Pos
iorwf INDF,f
return
;************************************************************
; Set_Rom_Bit_At_Index_To_Zero
;************************************************************
Set_Rom_Bit_At_Index_To_Zero:
call Get_Byte_For_Bit
call Get_Inverse_Mask_From_Bit_Pos
andwf INDF,f
return
;************************************************************
; Get_Rom_Bit
;************************************************************
; Get the ROM bit that ds_rom_bit_index points to
; The bit is in the first bit of W on return. Also the Z flag indicates if
; the bit is a zero or a one.
Get_Rom_Bit:
call Get_Byte_For_Bit
call Get_Mask_From_Bit_Pos
andwf INDF,W
btfss STATUS,Z
movlw 1
return
;************************************************************
; Get_Byte_For_Bit
;************************************************************
; This routine fetch the byte where the bit is located
; from the ds_rom_bit_index which should be in W on entry
Get_Byte_For_Bit:
movf ds_rom_bit_index,W
movwf ds_temp2
decf ds_temp2,f
bcf STATUS,C ; divide by 8
rrf ds_temp2,F
bcf STATUS,C
rrf ds_temp2,F
bcf STATUS,C
rrf ds_temp2,F
movlw rom
addwf ds_temp2,W
movwf FSR ; FSR points to byte, INDF now contains byte
return
;************************************************************
; Get_Mask_From_Bit_Pos
;************************************************************
; Bit pos in W on entry ( 0 - 7 ).
; Mask in W on exit.
Get_Mask_From_Bit_Pos:
movf ds_rom_bit_index,W
movwf del1
decf del1,f
movlw 0x07
andwf del1,F
incf del1,F
clrf del2 ; clear del2
bsf STATUS,C
;************************************************************
; Get_Mask_From_Bit_Pos_Loop
;************************************************************
Get_Mask_From_Bit_Pos_Loop:
rlf del2,f
decfsz del1,f
goto Get_Mask_From_Bit_Pos_Loop
movf del2,w
return
;************************************************************
; Get_Inverse_Mask_From_Bit_Pos
;************************************************************
Get_Inverse_Mask_From_Bit_Pos:
call Get_Mask_From_Bit_Pos
comf del2,w
return
;************************************************************
; Fetch_ROM
;
; Fetch ROM code from EEPROM and store in RAM
;
;************************************************************
DS_Fetch_ROM:
movlw F1-H'2100'
call Read_EEPROM
movwf rom
movlw F1+1-H'2100'
call Read_EEPROM
movwf rom+1
movlw F1+2-H'2100'
call Read_EEPROM
movwf rom+2
movlw F1+3-H'2100'
call Read_EEPROM
movwf rom+3
movlw F1+4-H'2100'
call Read_EEPROM
movwf rom+4
movlw F1+5-H'2100'
call Read_EEPROM
movwf rom+5
movlw F1+6-H'2100'
call Read_EEPROM
movwf rom+6
return
;************************************************************
; Read_EEPROM
;
; Read the content of the EEPROM position whos address is in W
; on entry. The contents is in W on Exit.
;
;************************************************************
Read_EEPROM:
movwf EEADR
bsf STATUS,RP0
bsf EECON1,RD
bcf STATUS,RP0
movf EEDATA,w
return
;************************************************************
;
; 1-Wire routines
;
;************************************************************
;************************************************************
; Init the 1-Wire system
;
;************************************************************
Init1Wire:
; 1-Wire State is waiting for a Reset
movlw STATE_RESET_WAIT
movwf ds_state
DSIN ; Port set for input
; We want Interrupt on High To Low on 1-Wire
IRQHL
bsf INTCON,INTE ; Enable IRQ on RBO edge change
clrf ds_status ; clear status byte
return
;************************************************************
; Timer 0 overflow Interrupt
;
; Just add value to counter.
;************************************************************
Ds_Timer_Overflow:
bcf INTCON,T0IF ; clr IRQ flag
incf ds_tmr_overflow,f
return
;************************************************************
;
; The Edge of the RB0 input has changed
;
; If this is a falling edge we should enable the TMR0 interrupt
; after clearing the timer.
;
; If this is a raisning edge we should disable the TMR0 interrupt
; Get the value from the timer and determine what we received.
;
; 480-960 - Reset.
; 1-15 - Read/Write cycle.
;
; 480 = 2 * 240
; 960 = 4 * 240 so we should use 240 to preset timer.
;************************************************************
DS_RB0_Edge:
bcf INTCON,INTF ; clr IRQ flag
movf TMR0,w ; save timer content ( 8 )
movwf ds_timer
bsf STATUS, RP0
btfss OPTION_REG,INTEDG
goto DS_RB0_Edge_Falling
;************************************************************
;
; Handle raising edge
;
;************************************************************
DS_RB0_Edge_Raising:
bcf STATUS, RP0
bcf INTCON,T0IE ; Disable TMR0 overflow
IRQHL ; next IRQ on falling edge
movf ds_state ; handle it
addwf PCL,f
goto Handle_RESET_State
goto Handle_COMMAND_State
;************************************************************
;
; Handle falling edge
;
;************************************************************
DS_RB0_Edge_Falling:
bcf STATUS, RP0
clrf TMR0
clrf ds_tmr_overflow
movf ds_state,w
addwf PCL,f
goto Falling_Edge_Default ; STATE_RESET_WAIT
goto Receive_Command_Bit ; STATE_COMMAND_WAIT
goto DS_IRQ_READ_ROM ; STATE_READ_ROM
goto DS_IRQ_MATCH_ROM ; STATE_MATCH_ROM
; STATE_SEARCH_ROM
; STATE_ALARM_SEARCH_ROM
; STATE_SKIP_ROM
; STATE_WRITE_SCR
; STATE_READ_SCR
; STATE_COPY_SCR
; STATE_CONVERT_T
; STATE_RECALL
; STATE_READ_POWER_SUPPLY
Falling_Edge_Default:
bsf INTCON,T0IE ; Enable TMR0 overflow
return
;************************************************************
;
; Handle possible Reset state
;
;************************************************************
Handle_RESET_State:
; For RESET
; =========
; Disregard everything except for a RESET
; A if ds_tmr_overflow = 0 error stay in state.
; B if ds_tmr_overflow = 1 TMR0 should be > 224-8
; C if ds_tmr_overflow = 2 TMR0 don't care
; D if ds_tmr_overflow = 3 TMR0 should be < 192-8
; E if ds_tmr_overflow > 3 error stay in state.
movf ds_tmr_overflow,w ; A
btfsc STATUS,Z
return
sublw 4 ; E
btfsc STATUS,C
return
movf ds_tmr_overflow,w ; C
sublw 2
btfsc STATUS,Z
goto Send_Presence_pulse
btfsc STATUS,C
goto Check_High_End
movlw (d'224'-8) ; B
subwf ds_timer,w
btfsc STATUS,C
goto Send_Presence_pulse
return
Check_High_End:
movlw (d'192'-8) ; E
subwf ds_timer,w
btfss STATUS,C
goto Send_Presence_pulse
return
;************************************************************
;
; Send Presence pulse
;
;************************************************************
Send_Presence_pulse:
nop ; wait a bit
nop
DSOUT ; Set DS for output
bcf DS_PORT, DS_BIT ; 0 to 1-wire
call D67us
nop ; wait tREC
nop
nop
nop
DSIN ; Set DS for input
movlw STATE_COMMAND_WAIT ; set new state
movf ds_state
movlw 1 ; Current bit = first bit
movf ds_bit_index
return
Handle_COMMAND_State:
return
;************************************************************
;
; Receive a bit of a command
;
; Should be done 15 us after falling edge.
;************************************************************
Receive_Command_Bit:
clrc ; clear carry
btfsc DS_PORT,DS_BIT ; bit is 0 ?
setc ; set carry if not
rrf ds_command,F
incf ds_bit_index,f ; another bit handled
movf ds_bit_index,w ; all 8 bits done?
sublw 0x08
btfsc STATUS,C
goto Receive_Command_Bit_Exit
; A command has been received. We have to
; check if this is one of the commands we
; support and go to that stage if so
movf ds_command,w
sublw READ_ROM
btfsc STATUS,Z
goto DS_READ_ROM
movf ds_command,w
sublw MATCH_ROM
btfsc STATUS,Z
goto DS_MATCH_ROM
movf ds_command,w
sublw SEARCH_ROM
btfsc STATUS,Z
goto DS_SEARCH_ROM
movf ds_command,w
sublw ALARM_SEARCH_ROM
btfsc STATUS,Z
goto DS_ALARM_SEARCH_ROM
movf ds_command,w
sublw SKIP_ROM
btfsc STATUS,Z
goto DS_SKIP_ROM
; The rest of the commands requires that the
; device should be selected before they are
; accepted
btfss ds_status,DS_SELECTED
goto Receive_Command_Bit_Invalid
movf ds_command,w
sublw WRITE_SCR
btfsc STATUS,Z
goto DS_WRITE_SCR
movf ds_command,w
sublw READ_SCR
btfsc STATUS,Z
goto DS_READ_SCR
movf ds_command,w
sublw COPY_SCR
btfsc STATUS,Z
goto DS_COPY_SCR
movf ds_command,w
sublw CONVERT_T
btfsc STATUS,Z
goto DS_CONVERT_T
movf ds_command,w
sublw RECALL
btfsc STATUS,Z
goto DS_RECALL
movf ds_command,w
sublw READ_POWER_SUPPLY
btfsc STATUS,Z
goto DS_READ_POWER_SUPPLY
;
; This must be a command that we don't accept
; Wait for Reset pulse again.
;
Receive_Command_Bit_Invalid:
call Init1Wire
Receive_Command_Bit_Exit:
return
;************************************************************
;
; Handle READ_ROM Command
;
; We should put out our ROM-code on the next 64 reads.
;************************************************************
DS_READ_ROM:
movlw STATE_READ_ROM ; set new state
movf ds_state
call DS_Fetch_ROM ; Fetch ROM from EEPROM
movlw 1
movwf ds_rom_bit_index
DS_READ_ROM_Loop:
call Get_Rom_Bit
btfsc STATUS,Z
goto DS_READ_ROM_Zero
DS_READ_ROM_One:
btfsc DS_PORT, DS_BIT ; Stay here until low pulse received
goto $-1
goto DS_READ_ROM_IsAllSent
DS_READ_ROM_Zero:
btfsc DS_PORT, DS_BIT ; Stay here until low pulse received
goto $-1
DSOUT
bcf DS_PORT, DS_BIT ; 0 to 1-wire
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop ; 15 us from low pulse
DSIN
DS_READ_ROM_IsAllSent:
incf ds_rom_bit_index,f ; another bit handled
movf ds_rom_bit_index,w ; all 64 bits done?
sublw 0x40
btfsc STATUS,C
goto DS_READ_ROM_Loop
DS_READ_ROM_Exit:
clrf ds_state ; STATE_RESET_WAIT
return
; The following should not occure
DS_IRQ_READ_ROM:
return
;************************************************************
; Handle MATCH_ROM Command
;
; The server wants to select a device so we expect to receive a
; ROM code. Go to the Reset Wait state as soon as a difference
; in bits is received.
;************************************************************
DS_MATCH_ROM:
movlw STATE_MATCH_ROM ; set new state
movf ds_state
call DS_Fetch_ROM ; Fetch ROM from EEPROM
movlw 1
movwf ds_rom_bit_index
call Get_Rom_Bit
movf ds_temp1
return
DS_IRQ_MATCH_ROM:
clrc ; clear carry
btfsc DS_PORT,DS_BIT ; bit is 0 ?
setc ; set carry if not
rlf ds_temp2,F
; ds_temp1 now should be the same as ds_temp2 if the
; bits are the same
movf ds_temp1,w
subwf ds_temp2
btfsc STATUS,Z
goto DS_READ_ROM_Exit ; Not same -> RESET_STATE
incf ds_bit_index,f ; another bit handled
call Get_Rom_Bit
movf ds_temp1
movf ds_bit_index,w ; all 64 bits done?
sublw 0x40
btfsc STATUS,C
goto Receive_Command_Bit_Exit
; device is selected
bsf ds_status,DS_SELECTED
return
;************************************************************
; Handle SEARCH_ROM Command
;
;
;************************************************************
DS_SEARCH_ROM:
movlw SEARCH_ROM ; set new state
movf ds_state
call DS_Fetch_ROM ; Fetch ROM from EEPROM
movlw 1
movwf ds_rom_bit_index
call Get_Rom_Bit
DS_SEARCH_ROM_Loop:
call Get_Rom_Bit
btfsc STATUS,Z
goto DS_READ_ROM_Zero
DS_SEARCH_ROM_One:
btfsc DS_PORT, DS_BIT ; Stay here until low pulse received
goto $-1
DS_SEARCH_ROM_Zero:
btfsc DS_PORT, DS_BIT ; Stay here until low pulse received
goto $-1
DSOUT
bcf DS_PORT, DS_BIT ; 0 to 1-wire
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop ; 15 us from low pulse
DSIN
DS_SEARCH_ROM_IsAllSent:
incf ds_rom_bit_index,f ; another bit handled
movf ds_rom_bit_index,w ; all 64 bits done?
sublw 0x40
btfsc STATUS,C
goto DS_READ_ROM_Loop
DS_SEARCH_ROM_Exit:
clrf ds_state ; STATE_RESET_WAIT
return
;************************************************************
; Handle ALARM_SEARCH_ROM Command
;
;
;************************************************************
DS_ALARM_SEARCH_ROM:
movlw STATE_ALARM_SEARCH_ROM ; set new state
movf ds_state
return
;************************************************************
; Handle SKIP_ROM Command
;
; This device is the only device on the bus so from now we accept
; selected device commands with no need for a MATCH_ROM or SEARCH ROM
; command.
;************************************************************
DS_SKIP_ROM:
bsf ds_status,DS_SELECTED ; Device selected
movlw STATE_COMMAND_WAIT ; set new state
movf ds_state
return
;************************************************************
; Handle WRITE_SCR Command
;
;
;************************************************************
DS_WRITE_SCR:
movlw STATE_WRITE_SCR ; set new state
movf ds_state
return
;************************************************************
; Handle READ_SCR Command
;
;
;************************************************************
DS_READ_SCR:
movlw STATE_READ_SCR ; set new state
movf ds_state
return
;************************************************************
; Handle COPY_SCR Command
;
;
;************************************************************
DS_COPY_SCR:
movlw STATE_COPY_SCR ; set new state
movf ds_state
return
;************************************************************
; Handle CONVERT_T Command
;
;
;************************************************************
DS_CONVERT_T:
movlw STATE_CONVERT_T ; set new state
movf ds_state
return
;************************************************************
; Handle RECALL Command
;
;
;************************************************************
DS_RECALL:
movlw STATE_RECALL ; set new state
movf ds_state
return
;************************************************************
; Handle READ_POWER_SUPPLY Command
;
;
;************************************************************
DS_READ_POWER_SUPPLY:
movlw STATE_READ_POWER_SUPPLY ; set new state
movf ds_state
return
;************************************************************************
;
; DS_CRC8 - Will calculate 8 bit CRC for DALLAS DS components
;
; Input: Byte for CRC in W
; Return: Byte in W, CRC in CRC8
;************************************************************************
DS_CRC8 movwf del2
movwf ds_temp2 ; Save byte
movlw 8 ; 8 bits
movwf ds_temp1 ; store counter
movf ds_temp2,W ; byte to W
CRC8_L1 xorwf crc8,W ; xor
movwf del1 ; ds_temp store
rrf del1,W
movf crc8,W ; fetch last CRC
skpnc ; if not C, skip
xorlw 0x18 ; xor with fixed
movwf crc8 ; store new CRC
rrf crc8,F ; update new CRC
clrc ; clear carry
rrf ds_temp2,F ; next bit
movf ds_temp2,W
decfsz ds_temp1,F ; count bits
goto CRC8_L1 ;
movf del2,W ; fetch original to W
return