I don't understand assembly language. I have found assembly code. I'm looking someone to help me to understand assembly code.
Code for the smart watering controller. The comment in the code shows that the relay, real time clock are used in the controller. I have a doubt that LCD must have been used in it, but I 'm not confident.
The most important I want to understand what program supposed to do in controller.
Here is code
Code for the smart watering controller. The comment in the code shows that the relay, real time clock are used in the controller. I have a doubt that LCD must have been used in it, but I 'm not confident.
The most important I want to understand what program supposed to do in controller.
Here is code
Code:
;
;
; Code for the smart watering controller. We have a real time
; clock that is periodically read and a list of actions stored
; in EEprom that is compared with this time. If a match is found,
; that action is activated. We have 7 relay outputs.
;
;
;
;
;
;
;
;
chip 8051
;
; port pin assignments
;
mux0 reg P1.0 ;latch addr 0/bcd sw 0
mux1 reg P1.1
mux2 reg P1.2
mux_dat reg P1.3 ;latch data/bcd sw 3
mux_sel reg P1.4 ;latch strobe
wire1 reg P1.5 ;Dallas 1 wire port
SCL reg P1.6 ;i2c port clock
SDA reg P1.7 ;i2c port data
sw_sel reg P3.5 ;bcd switch select
;
; system equates
;
SOH equ 1 ;ascii start of header char
eeprom_addr equ a4h ;i2c addr for eeprom
rtc_addr equ a0h ;i2c addr for 8583 rtc
baud equ 3 ;19200 baud
time_tick equ 9220 ;tick time =10mS
rom equ 8000h ;8000h for debug,0 for prom
;
;
; op-code equates for the action stuff
;
;
op_on equ 0 ;relay(s) on
op_off equ 1 ;relay(s) off
op_ongt equ 2 ;relay(s) on if var X > const
op_onlt equ 3 ;relay(s) on if var X < const
op_offgt equ 4 ;relay(s) off if var X > const
op_offlt equ 5 ;relay(s) off if var X < const
;
; Start of rom vectors
;
org rom
ljmp begin
org rom+3h
* ljmp int0_isr
org rom+bh
ljmp timer0_isr
org rom+13h
* ljmp int1_isr
org rom+1bh
* ljmp timer1_isr
org rom+23h
ljmp serial_isr
;
;
; Start of code
;
;
org rom+28h
begin
;
; init the serial port & timers
;
mov sp,#stack ;load stack ptr
mov pcon,#80h ;set SMOD
mov tmod,#00100001b ;timer1 brg,timer0 16 bit
mov tl0,#<(1-time_tick)
mov th0,#>(1-time_tick) ;reload the timer
setb tr0 ;and set it going again
mov th1,#-baud ;load reload val
mov tl1,#-baud ;load timer1
mov scon,#01010010b ;mode 1 8 bit uart
mov tcon,#01010000b ;timer 0,1 run
;
; clear mem & init vars
;
mov r0,#01h ;->ram
clr a
mem_clr1
mov @r0,a ;clear loc'n
inc r0 ;++->
cjne r0,#80h,mem_clr1 ;end?
mov task_bits,#40h ;start with read clock task
mov ie,#10000010b ;enable ints
setb task_bits.6
;----------------------------------------------------------------------------
;
;
; Main dispatcher. To simulate a real-time task switch we fake things
; a little by allowing each task time in 1mS chunks. If the task
; finishes before time, we wait for the next 1mS tick. If the task runs
; over time, the next task runs immediately after the previous has
; finished. Each task has a priority, the highest priority task runs
; first. The general idea is to have the highest priority tasks run
; infrequently so that they don't hog the cpu
;
;
;----------------------------------------------------------------------------
dispatch
jnb task_bits.7,dispatch ;wait for a tick
clr task_bits.7 ;reset the tick bit
acall update_relays
mov r2,#0 ;start at task#0 -highest priority
mov a,task_bits ;get the bits
find_task
clr c
rrc a ;get task bit into carry
jc go_task ;the bit is set,r2 has the task#
inc r2 ;try next
cjne r2,#7,find_task ;7 tasks max!
sjmp dispatch ;no tasks found! idle till next tick
;
; task found! task# in R2
;
go_task
mov a,r2 ;get task #
rl a ;word index
mov dptr,#task_jt ;->jump table
jmp @a+dptr ;goto task
task_jt
ajmp decode_rx_packet ;highest priority
ajmp dispatch
ajmp dispatch
ajmp dispatch
ajmp dispatch
ajmp scan_action ;scan the action tables
ajmp read_clock ;lowest priority
;----------------------------------------------------------------------------
;
;
; read the real time clock every 1/2 seconds & activate the action
; scan routine when the minute ticks over
;
;
;----------------------------------------------------------------------------
read_clock
clr task_bits.6 ;reset the task request
mov clock_time,#50 ;restart this task in 500mS
acall read_rtc ;get the current time
;
; read the unit select switch
;
orl p1,#0fh ;set p1.0..3 as inputs
clr sw_sel ;select the address switch
nop
nop
nop
mov a,p1 ;read back the switch
setb sw_sel
cpl a ;flip it
anl a,#0fh
mov unit_sw,a
setb es ;allow serial ints
mov a,time_seconds ;get the current seconds
mov b,prev_seconds ;test with the previous
mov prev_seconds,a ;update the previous
cjne a,b,rc_1
rc_1 jnc rc_2 ;no minute tickover yet!
;
; a minute has ticked over.activate the scan task
;
setb task_bits.5 ;activate
rc_2
ajmp dispatch ;exit
;----------------------------------------------------------------------------
;
;
; Scan the eeprom action tables for a time match & activate the action
;
;
;----------------------------------------------------------------------------
scan_action
clr task_bits.5 ;reset the task request
;
; convert the day# into a bit field
;
mov a,time_wmonth
rl a
rl a
rl a
anl a,#7 ;get bits 5..7 to 0..2
add a,# const & turn relays on
;
mov a,act_cmd
anl a,#3 ;4 vars only
add a,#vars ;add var base addr
mov r0,a
mov a,@r0 ;get the var
mov b,a ;into B
mov a,#act_const ;get the constant
clr c
subb a,b ;const-var
jnc no_match
sjmp rly_on ;if const < var
match_3
cjne a,#op_onlt,match_4
;
; test for var < const & turn relays on
;
mov a,act_cmd
anl a,#3 ;4 vars only
add a,#vars ;add var base addr
mov r0,a
mov a,@r0 ;get the var
mov b,#act_const ;get the constant
clr c
subb a,b ;var-const
jnc no_match
sjmp rly_on ;if const < var
match_4
cjne a,#op_offgt,match_5
;
; test for var > const & turn relays off
;
mov a,act_cmd
anl a,#3 ;4 vars only
add a,#vars ;add var base addr
mov r0,a
mov a,@r0 ;get the var
mov b,a ;into B
mov a,#act_const ;get the constant
clr c
subb a,b ;const-var
jnc no_match
sjmp rly_off ;if const < var
match_5
cjne a,#op_offlt,no_match
mov a,act_cmd
anl a,#3 ;4 vars only
add a,#vars ;add var base addr
mov r0,a
mov a,@r0 ;get the var
mov b,#act_const ;get the constant
clr c
subb a,b ;var-const
jnc no_match
sjmp rly_on ;if const < var
no_match
inc curr_action
mov a,curr_action
cjne a,#32,nm_1
nm_1 jnc nm_2
ajmp do_it
nm_2
mov curr_action,#0 ;update the relays & exit
acall update_relays
ajmp dispatch
;----------------------------------------------------------------------------
;
;
; Update the relay outputs
;
;
;----------------------------------------------------------------------------
update_relays
mov b,#0 ;start at bit 0
mov a,relays ;get relay bits
ur_1
rrc a ;get bit into carry
mov mux_dat,c ;copy to latch
mov c,b.0
mov mux0,c
mov c,b.1
mov mux1,c
mov c,b.2
mov mux2,c
clr mux_sel ;strobe data
nop
nop
setb mux_sel ;set strobe hi
inc b ;next..
jnb b.3,ur_1
orl p1,#0fh ;set bits 0..3 high
ret
;----------------------------------------------------------------------------
;
; Read the Real Time Clock thru the i2c port.
; returns time/date in structure 'time'
; exit: carry clear if ok,else set if there was an error
;
;----------------------------------------------------------------------------
read_rtc
mov r0,#time ;->time storage
mov r2,#7 ;7 regs
mov r1,#rtc_addr
mov a,#2 ;read from seconds reg onwards
acall read_block
jc rr_x ;exit if error
;
; test for year rollover
;
mov a,time_ydate ;get year/date
rl a
rl a ;get bits 7 & 6 into 1 & 0
xrl a,time_year ;same as our year ram loc'n
anl a,#3 ;mask other bits
jz rr_x ;jump if year hasn't ticked over
inc time_year ;tick year count over
mov r0,#time_year ;->time storage
mov r2,#1 ;1 byte
mov r1,#rtc_addr
mov a,#8 ;ram for year storage
acall write_block ;update the year
rr_x
ret
;----------------------------------------------------------------------------
;
; Read the Real Time Clock thru the i2c port.
; returns time/date in structure 'time'
; exit: carry clear if ok,else set if there was an error
;
;
;----------------------------------------------------------------------------
write_rtc
;
; fix up the year stuff
;
mov a,time_ydate ;get year/date
anl a,#3fh ;clear year bits
mov time_ydate,a
mov a,time_year ;get the year
rr a
rr a ;get the tw olsb into the msbs
anl a,#c0h ;bit 6 & 7 only
orl a,time_ydate
mov time_ydate,a ;update the year/date value
;
; stop the clock
;
mov r6,#80h ;control reg..stop the clock
mov r7,#0
mov r0,#6 ;->R6
mov r2,#2 ;2 regs
mov r1,#rtc_addr
mov a,#0 ;read from seconds reg onwards
acall write_block
jc wrtc_x ;exit of there was an error
;
; write the time stuff
;
mov r0,#time ;->time storage
mov r2,#7 ;7 regs
mov r1,#rtc_addr
mov a,#2 ;read from seconds reg onwards
acall write_block
jc wrtc_x ;exit if error
;
; start the clock
;
mov r6,#00h ;control reg..start the clock
mov r0,#6 ;->R6
mov r2,#1 ;1 reg
mov r1,#rtc_addr
mov a,#0 ;read from seconds reg onwards
acall write_block
wrtc_x
ret
;----------------------------------------------------------------------------
;
; Write from one byte to one page of data to an AT24Cxx.
; Called with address of first byte in A,R0->data to write
; byte count in register R2.
; Does not wait for write cycle to complete.
; Returns CY set to indicate that the bus is not available
; or that the addressed device failed to acknowledge.
; Destroys A, R0, R2.
;
;----------------------------------------------------------------------------
write_block
push b
mov b,a ; save address
acall start
jc x38 ; abort if bus not available
;
mov a,R1 ; fixed address
clr acc.0 ; specify write operation
acall shout ; send device address
jc x37 ; abort if no acknowledge
;
mov a,b
acall shout ;
jc x37 ; abort if no acknowledge
;
x36
mov a,@r0 ; get data
acall shout ; send data
jc x37 ; abort if no acknowledge
;
inc r0 ; advance buffer pointer
djnz r2, x36 ; next byte
clr c ; clear error flag
x37
acall stop
x38
pop b
ret
;----------------------------------------------------------------------------
;
; Read from one byte to one page of data from an AT24Cxx.
; Performs a Random Read which is extended into a Sequential Read
; when more than one byte is read. Called with address of first
; byte in A,byte count in register R2 and ->buffer in R0.
; R1 has the i2c addr
;
; Returns data in the buffer. Returns CY set to indicate that the bus is
; not available or that the addressed device failed to acknowledge.
; Destroys A, R0, R2.
;
;----------------------------------------------------------------------------
read_block
push b
mov b,a ; save address into B
call start
jc x35 ; abort if bus not available
;
mov a,R1 ; add fixed address
clr acc.0 ; specify write operation
call shout ; send device address
jc x34 ; abort if no acknowledge
;
mov a,b ; send address
call shout ;
jc x34 ; abort if no acknowledge
;
; Send read command and receive data.
;
call start ; second start for read
jc x34 ; abort if bus not available
;
mov a,R1 ; get device address
setb acc.0 ; specify read operation
call shout ; send device address
jc x34 ; abort if no acknowledge
;
x31
call shin ; receive data byte
mov @r0, a ; save data
cjne R2, #1, x32 ; jump if not last byte
call nak ; do not acknowledge last byte
jmp x33 ; done
x32
call ack ; acknowledge byte
inc r0 ; advance buffer pointer
djnz R2, x31 ; next byte
x33
clr c ; clear error flag
x34
call stop
x35
pop b
ret
;----------------------------------------------------------------------------
;
; AT24Cxx Current Address Read function.
; Returns data in A.
; Returns CY set to indicate that the bus is not available
; or that the addressed device failed to acknowledge.
;
;----------------------------------------------------------------------------
read_current:
acall start
jc x45 ; abort if bus not available
;
mov a, #eeprom_addr ; add fixed address
setb acc.0 ; specify read operation
acall shout ; send device address
jc x44 ; abort if no acknowledge
;
acall shin ; receive data byte
acall nak ; do not acknowledge byte
clr c ; clear error flag
x44
acall stop
x45
ret
;----------------------------------------------------------------------------
;
; Send START, defined as high-to-low SDA with SCL high.
; Return with SCL, SDA low.
; Returns CY set if bus is not available.
;
;----------------------------------------------------------------------------
start
setb SDA
setb SCL
;
; Verify bus available.
;
jnb SDA, x40 ; jump if not high
jnb SCL, x40 ; jump if not high
nop ; enforce setup delay and cycle delay
clr SDA
nop ; enforce hold delay
nop ;
nop ;
nop ;
nop ;
clr SCL
clr c ; clear error flag
jmp x41
x40
setb c ; set error flag
x41
ret
;----------------------------------------------------------------------------
;
; Send STOP, defined as low-to-high SDA with SCL high.
; SCL expected low on entry. Return with SCL, SDA high.
;
;----------------------------------------------------------------------------
stop
clr SDA
nop ; enforce SCL low and data setup
nop
setb SCL
nop ; enforce setup delay
nop ;
nop ;
nop ;
nop ;
setb SDA
ret
;----------------------------------------------------------------------------
;
; Shift out a byte to the AT24Cxx, most significant bit first.
; SCL, SDA expected low on entry. Return with SCL low.
; Called with data to send in A.
; Returns CY set to indicate failure by slave to acknowledge.
; Destroys A.
;
;----------------------------------------------------------------------------
shout
push b
mov b, #8 ; bit counter
x42
rlc a ; move bit into CY
mov SDA, c ; output bit
nop ; enforce SCL low and data setup
setb SCL ; raise clock
nop ; enforce SCL high
nop ;
nop ;
nop ;
clr SCL ; drop clock
djnz b, x42 ; next bit
setb SDA ; release SDA for ACK
nop ; enforce SCL low and tAA
nop ;
setb SCL ; raise ACK clock
nop ; enforce SCL high
nop ;
nop ;
nop ;
mov c, SDA ; get ACK bit
clr SCL ; drop ACK clock
pop b
ret
;----------------------------------------------------------------------------
;
; Shift in a byte from the AT24Cxx, most significant bit first.
; SCL expected low on entry. Return with SCL low.
; Returns received data byte in A.
;
;----------------------------------------------------------------------------
shin
setb SDA ; make SDA an input
push b
mov b, #8 ; bit count
x43
nop ; enforce SCL low and data setup
nop ;
nop ;
setb SCL ; raise clock
nop ; enforce SCL high
nop ;
mov c, SDA ; input bit
rlc a ; move bit into byte
clr SCL ; drop clock
djnz b, x43 ; next bit
pop b
ret
;----------------------------------------------------------------------------
;
; Clock out an acknowledge bit (low).
; SCL expected low on entry. Return with SCL, SDA low.
;
;----------------------------------------------------------------------------
ack
clr SDA ; ACK bit
nop ; enforce SCL low and data setup
nop ;
setb SCL ; raise clock
nop ; enforce SCL high
nop ;
nop ;
nop ;
clr SCL ; drop clock
ret
;----------------------------------------------------------------------------
;
; Clock out a negative acknowledge bit (high).
; SCL expected low on entry. Return with SCL low, SDA high.
;
;----------------------------------------------------------------------------
nak
setb SDA ; nak bit
nop ; enforce SCL low and data setup
nop ;
setb SCL ; raise clock
nop ; enforce SCL high
nop ;
nop ;
nop ;
clr SCL ; drop clock
ret
;-----------------------------------------------------------------------------
;
;
; timer tick gets us here.
;
;
;-----------------------------------------------------------------------------
timer0_isr
clr tr0
mov tl0,#<(1-time_tick)
mov th0,#>(1-time_tick) ;reload the timer
setb tr0 ;and set it going again
push psw
push a
setb task_bits.7 ;set the tick bit
;
; re-enable the read_clock task if 500mS elapsed
;
mov a,clock_time ;decrement the input scan timer
jz t0_1 ;already 0
djnz clock_time,t0_1 ;not 0..decrement it
setb task_bits.6
t0_1
;
; eeprom write timer. If eeprom_time is 0, eeprom is free else write
; cycle is in progress
;
mov a,eeprom_time ;take care of the eeprom write timer
jz t0_2 ;already 0..leave it
dec a
mov eeprom_time,a ;decrement it
t0_2
pop a
pop psw
reti
;----------------------------------------------------------------------------
;
; Decode the receive packets.
; Commands supported are:
; 0 Read current inputs
; 1 Read raw channel & scale/offset
; 2 Set scale/offset
; 3 Dump the eeprom data (16 bytes at a time)
; 4 Set the channel display label
;
;----------------------------------------------------------------------------
decode_rx_packet
clr task_bits.0 ;clear our task request
mov unit_sw,#0 ;**diag
mov a,ppx_data ;get the address
xrl a,unit_sw
jz addr_ok ;if we're addressed
ajmp dispatch ;else exit
addr_ok
mov a,ppx_data+1 ;get the cmd byte
cjne a,#max_cmd,drp_1
drp_1 jc drp_2
sjmp cmd_error ;illegal command
drp_2
rl a ;make word index
mov dptr,#cmd_jump
jmp @a+dptr
max_cmd equ 5 ;maximum cmd #
cmd_jump
ajmp cmd_read_inputs ;cmd=0 reply with current relay state,time & vars
ajmp cmd_get_action ;cmd=1 reply with action
ajmp cmd_set_action ;cmd=2 reply with ok
ajmp cmd_set_time ;cmd=3 reply with ok
ajmp cmd_set_relays ;cmd=4 reply with ok
cmd_error
mov ppx_data,#ffh ;destination=master
mov ppx_data+1,#ffh ;cmd=ffh error
mov ppx_data+2,#'E'
mov ppx_data+3,#'r'
mov ppx_data+4,#'r'
mov ppx_lenl,#5 ;data packet length
mov ppx_lenh,#0 ;msb=0
ajmp create_tx ;create packet & end
;----------------------------------------------------------------------------
;
; Read input command. There is no parameters for this
; We just reply with the time,the var values & the relay states
; input packet:
; addr
; cmd
; reply:
; dest addr
; cmd
; time (7 bytes)
; vars (4 bytes)
; relays (1 byte)
;
;----------------------------------------------------------------------------
cmd_read_inputs
mov ppx_data,#ffh ;destination=master
mov ppx_data+1,#80h ;reply cmd
;
; copy time
;
mov r0,#ppx_data+2 ;->destination
mov r1,#time ;->source
mov r2,#7 ;7 bytes to the time structure
cri_1
mov a,@r1
mov @r0,a ;copy byte
inc r0
inc r1
djnz r2,cri_1
;
; copy vars
;
mov r1,#vars ;->source
mov r2,#4 ;4 bytes to the time structure
cri_2
mov a,@r1
mov @r0,a ;copy byte
inc r0
inc r1
djnz r2,cri_2
;
; copy relay state
;
mov a,relays
mov @r0,a ;copy relays
;
; set packet length & send!
;
mov ppx_lenl,#2+7+4+1 ;data packet length
mov ppx_lenh,#0 ;msb=0
ajmp create_tx ;create packet & end
;----------------------------------------------------------------------------
;
; Read action from eeprom
; input packet:
; src addr
; cmd
; input #
; reply:
; dest addr
; cmd
; input#
; action (8 bytes)
;
;----------------------------------------------------------------------------
cmd_get_action
mov ppx_data,#ffh ;destination=master
mov ppx_data+1,#81h ;reply cmd
mov a,ppx_data+2 ;get action #
anl a,#1fh ;32 actions only!
rl a
rl a
rl a
mov r0,#ppx_data+3 ;->dest
mov r2,#8 ;8 bytes
mov r1,#eeprom_addr ;from eeprom
acall read_block ;get from the eeprom
mov ppx_lenh,#0
mov ppx_lenl,#2+1+8 ;set reply length
ajmp create_tx
;----------------------------------------------------------------------------
;
; Write action to eeprom
; input packet:
; src addr
; cmd
; action #
; action (8 bytes)
; reply:
; dest addr
; cmd
; action#
; Ok
;
;----------------------------------------------------------------------------
cmd_set_action
mov ppx_data,#ffh ;destination=master
mov ppx_data+1,#82h ;reply cmd
mov a,ppx_data+2 ;get action#
anl a,#1fh ;32 actions only!
rl a
rl a
rl a
mov r0,#ppx_data+3 ;where to copy the eeprom data from
mov r2,#8 ;8 bytes
mov r1,#eeprom_addr ;to eeprom
acall write_block ;write data to eeprom
mov eeprom_time,#2 ;load eeprom write timer
reply_ok
mov ppx_data+3,#'O'
mov ppx_data+4,#'k' ;reply with Ok
mov ppx_lenl,#2+1+2
mov ppx_lenh,#0 ;set packet length
ajmp create_tx
;----------------------------------------------------------------------------
;
; Read input command. There is no parameters for this
; We just reply with all values for the 16 inputs.
; input packet:
; src addr
; cmd
; time (7 bytes)
; reply:
; dest addr
; src addr
; cmd
; addr
; eeprom data (16 bytes)
;
;----------------------------------------------------------------------------
cmd_set_time
mov ppx_data,#ffh ;destination=master
mov ppx_data+1,#83h ;reply cmd
mov r0,#ppx_data+2 ;->time
mov r1,#time
mov r2,#7 ;7 bytes
cst_1
mov a,@r0
mov @r1,a
inc r0
inc r1
djnz r2,cst_1
acall write_rtc ;update the clock
ajmp reply_ok
;----------------------------------------------------------------------------
;
; Set the relays
; input packet:
; src addr
; cmd
; relays
;
; reply:
; dest addr
; cmd
; Ok
;
;----------------------------------------------------------------------------
cmd_set_relays
mov ppx_data,#ffh ;destination=master
mov ppx_data+1,#84h ;reply cmd
mov a,ppx_data+2 ;get the new relay states
mov relays,a ;copy
ajmp reply_ok
;----------------------------------------------------------------------------
;
;
; Create a PPX-1 transmit data packet. Calc checksum and forward
; the data onto the transmit interupt code. We assume the data
; packet length has been previously set.
; zaps A,B,R0
; returns to the dispatch code
;
;----------------------------------------------------------------------------
create_tx
mov ppx_lenh,#0 ;we can't tx packets > 20 bytes
mov a,ppx_lenl
add a,#5 ;add ppx packet overhead
mov bank1+4,a ;set length for tx code
;
; calc the packet header check
;
mov a,ppx_lenh
cpl a ;!length hi
mov r2,a ;save into R2
mov a,ppx_lenl
cpl a ;!length low
add a,r2
mov ppx_hchk,a ;=!length hi + !length low
;
; calc the checksum
;
mov b,ppx_lenl ;get length
mov r0,#ppx_data ;->data area
mov ppx_cksmh,#0
mov ppx_cksml,#0 ;init checksum
tx_cksm
mov a,@r0 ;get data
inc r0
add a,ppx_cksml
mov ppx_cksml,a
jnc tx_cksm1
inc ppx_cksmh
tx_cksm1
djnz b,tx_cksm ;accumulate the checksum
;
; append the checksum on the end of the data
;
mov a,ppx_cksmh
mov @r0,a
inc r0
mov a,ppx_cksml
mov @r0,a
mov bank1+1,#comms_buf ;r1 bank1->comms buffer
mov sbuf,#SOH ;start of packet
clr ti ;activate the tx interupt code
ajmp dispatch
;----------------------------------------------------------------------------
;
;
; serial port isr
; we use register bank #1 exclusively
; R0 rx ->
; R1 tx ->
; R2 rx state
; R3
; R4
; R5 rx char
; R6 packet length hi
; R7 packet length low
;
;----------------------------------------------------------------------------
serial_isr
jnb ri,sint_1 ;if not rx int
push psw
push a
push dph
push dpl
mov psw,#08h ;select register bank#1
acall rx_char
pop dpl
pop dph
pop a
pop psw
reti
;
; transmit code
;
sint_1
jnb ti,si_2 ;if not tx int
clr ti ;reset the int flag
push psw
push a
mov psw,#08h ;select register bank#1
mov a,r4
jz si_3 ;skip if ==0
mov a,@r1 ;get data
mov sbuf,a ;send it
inc r1
dec r4
sjmp si_4
si_3
mov r2,#0 ;rx state=0
si_4
pop a
pop psw
si_2
reti
;----------------------------------------------------------------------------
;
; Receive char interupt routine. Attempt to assemble a rx packet
; data packet. Reject bad headers
;
;----------------------------------------------------------------------------
rx_char
mov r5,sbuf ;save char
clr ri ;reset int flag
mov a,r2
cjne a,#max_rx_state,rx_1 ;test for valid state
rx_1 jnc rx_jumptable ;invalid state-goto state0
rl a
mov dptr,#rx_jumptable ;->jump table
jmp @a+dptr ;goto code
;
;
;
max_rx_state equ 8 ;max state+1
rx_jumptable
ajmp rx_state0 ;wait for SOH
ajmp rx_state1 ;get packet length high
ajmp rx_state2 ;get packet length low
ajmp rx_state3 ;get header check
ajmp store_rx ;get data
ajmp rx_state5 ;get checksum high
ajmp rx_state6 ;get checksum low
ajmp rx_state7 ;end idle state
;
; look for a SOH for start of packet
;
rx_state0
mov a,r5 ;get the rx char
cjne a,#SOH,rx_st01 ;soh ?
mov r2,#1 ;yes! next state =1
mov r0,#ppx_data ;reset the data ->
mov ppx_cksmh,#0
mov ppx_cksml,#0 ;clear the checksum
rx_st01
ret
;
; we've got a SOH already,get the packet length high
;
rx_state1
mov a,r5
mov r7,a ;into R7
mov ppx_lenh,a
inc r2
ret
;
; get the packet length low
;
rx_state2
mov a,r5
mov r6,a ;into R6
mov ppx_lenl,a
inc r2
ret
;
; get the header check & check the header data
;
rx_state3
mov a,r7 ;get header length hi
cpl a ;not
mov r7,a
mov a,r6
cpl a ;not
add a,r7 ;!lenh + !lenl
clr c
xrl a,r5 ;test header check
jnz rx_st31 ;twas bad
;
; header was good!
;
mov a,r7
cpl a
mov r7,a ;flip the packet length hi back again
orl a,r6 ;test for packet size ==0
jnz rx_st33
;
; packet size ==0 next state is checksum
;
mov r2,#5
ret
;
; packet size > 0
;
rx_st33
inc r2
ret
;
; header was bad!
;
rx_st31
mov r2,#0
ret
;
; Rx char in R5
; accumulate the checksum
; decrement the byte count,if count==0 then next state=checksum
;
store_rx
;
; test the rx data ->
;
mov a,r0 ;get the data ->
cjne a,#ppx_data+20,srx_4
srx_4 jnc srx_1 ;-> too high! skip storing the data
;
; store the rx data
;
mov a,r5 ;get rx char
mov @r0,a ;store the rx char
inc r0 ;->++
;
; accumulate the checksum
;
srx_3
add a,ppx_cksml
mov ppx_cksml,a
mov a,ppx_cksmh
addc a,#0
mov ppx_cksmh,a ;accumulate the checksum
xch a,r6
jnz srx_1
dec r7
srx_1
dec a
xch a,r6 ;decrement the byte count
mov a,r6
orl a,r7 ;test byte count==0
jnz srx_2
;
; byte count=0 next state = checksum
;
mov r2,#5
srx_2
ret
;
; we've got all the data,now check the checksum
;
rx_state5
mov a,r5 ;get the rx char
xrl a,ppx_cksmh ;xor with our checksum hi
mov ppx_cksmh,a ;store result back for later
inc r2
ret
;
; check the checksum low
;
rx_state6
mov a,r5
xrl a,ppx_cksml ;xor checksum low
orl a,ppx_cksmh ;check for good result==0
jnz rx_bad
;
; receive packet was for us and was good. report completion
; and next state=idle
;
mov r2,#7
setb task_bits.0 ;activate the serial comms task
ret
;
; checksum was bad...reject the packet
;
rx_bad
mov r2,#0
ret
;
; receive packet was good,stay in this state until we get released
;
rx_state7
ret
*****************************************************************************
*
* print hex in A
*
phex push a
swap a
acall l_hex
pop a
l_hex
anl a,#0fh
add a,#30h
cjne a,#3Ah,lh_1
lh_1 jc lh_2 ;if a<=$39
add a,#7
lh_2
acall pchar
ret
*
* send A out the serial port
*
pchar clr scon.1
mov sbuf,a
pc_1 jnb scon.1,pc_1
ret
;----------------------------------------------------------------------------
;
; ram
;
;
;----------------------------------------------------------------------------
RSECT
org 0
bank0 ds 8
bank1 ds 8
bank2 ds 8
bank3 ds 8
relays ds 1 ;relay states
task_bits ds 1 ;task flags
unit_sw ds 1 ;bcd switch value
eeprom_time ds 1 ;eeprom write timer
prev_seconds ds 1 ;previous seconds reading
clock_time ds 1 ;time between rtc readings
;
; real time clock structure for reading & writing to the rtc
;
time
time_seconds ds 1
time_minutes ds 1
time_hours ds 1
time_ydate ds 1
time_wmonth ds 1
time_timer ds 1
time_year ds 1
;
; action structure
;
action
act_mins ds 1 ;minutes in bcd
act_hrs ds 1 ;hours in bcd
act_day ds 1 ;days as a bit field
act_relay ds 1 ;relays as a bit field
act_cmd ds 1 ;command in hi nibble,var# in low
act_const ds 1 ;constant for comparison operation
act_null1 ds 1
act_null2 ds 1
;
;
;
curr_action ds 1 ;current action#
day_bits ds 1 ;days as a bit field
vars ds 4 ;storage for 4 input variables
ppx_cksml ds 1 ;comms checksum low
ppx_cksmh ds 1 ;comms checksum hi
comms_buf equ * ;comms buffer
ppx_lenh ds 1
ppx_lenl ds 1
ppx_hchk ds 1
ppx_data ds 20
stack equ *
;----------------------------------------------------------------------------
;
; EEprom
;
;----------------------------------------------------------------------------
eeprom section
org 0
actions ds 32*8 ;action table