Connect with us

smart watering controller

Discussion in 'Microcontrollers, Programming and IoT' started by champ1, May 1, 2021.

Scroll to continue with content
  1. champ1

    champ1

    40
    0
    Jul 17, 2018
    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:
    ;
    ;
    ;    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
     
  2. Harald Kapp

    Harald Kapp Moderator Moderator

    11,802
    2,749
    Nov 17, 2011
    Then you'll have to learn it. See for example here or look it up in your favorite search engine. Searching for "8051 assembly language tutorial" turned up over 500000 hits.
    I doubt you'll find anyone walking you through over 1000 lines of assembler code.

    Where did you get the code from? Usually I'd expect an explanation of the code on that website.
    Alternatively find another source that offers code in a high level language such as e.g. "C" (a typical language used for microcontrollers). I found quite a few water controller projects.
     
  3. bancroft

    bancroft

    71
    2
    Apr 23, 2021
    I think you can check out books on assembly language, it helps you understand better how the microcontroller works.
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-