;***********************************************************************
;*              MASS-DIMM controller
;*              High voltage, control light, viewer illumination
;*              Circuit diagrams:       mass_dimm.sch
;*              Circuit boards:         mass_dimm.pcb
;*              Last modification:      19.08.03
;***********************************************************
;;
.include "M8DEF.INC"
.include "massdimm.inc"
.equ    BLS=    0x0e00
.listmac
.macro  skip
        rjmp    PC+2
.endmacro

;***********************************************************************
;*                  Interrupt table
;***********************************************************************
.cseg
.org $0000
        rjmp    Start                   ; Programm start, Reset handler
.org INT0addr
        rjmp    line_monitor            ; RS485 line monitor handler
.org INT1addr
        rjmp    overlight_monitor       ; Overlight detector handler
.org OC2addr
        rjmp    switch_timeout          ; Switch timeout handler
.org OVF2addr
        rjmp    window_timeout          ; Window timeout handler
.org ICP1addr
	reti
.org OC1Aaddr
        rjmp    long_cycle              ; Cycle for temperature and pooling
.org OC1Baddr
	rjmp	illum_clear		; Reset illimination RWM
.org OVF1addr
        reti
.org OVF0addr
        rjmp    syncronization          ; Light variation
.org SPIaddr
	reti
.org URXCaddr
        rjmp    receiver                ; UART receiver handler
.org UDREaddr
	reti
.org UTXCaddr
        rjmp    transmitt_complete      ; UART transmitter handler
.org ADCCaddr
        rjmp    convertion_complete     ; ADC6 handler  for temperature
.org ERDYaddr
	reti
.org ACIaddr
        reti
.org TWIaddr
	reti
.org SPMaddr
        reti
;***********************************************************************
;*                  Constant tables
;***********************************************************************
identno:                                ; Device Identification
        .dw     iddev
        .dw     pdate

line:
        .db     AUX, fbaudrate          ; Line constants
        .db     fbottom, fswitch

apparatus:                              ; Constants
        .db     0xff, 0x00
        .dw     freq

defaults:
        .db     dillum, dlight
        .db     dvariation, dvoltage
enddefaults:

;***********************************************************************
;*                  Command decoding
;***********************************************************************
;*      000 - (0x00) - Data  block
;*            (0x10) - Data block with marker
;*   +  001 - (0x20) - Argument write into SRAM (Byte)
;*            (0x30) - Arguments write into SRAM (2 Byte)
;*      010 - (0x40) - Command with 1-byte argument
;*            (0x50) - Command with 2-bytes argument
;*      011 - (0x60) - Argument write into EEPROM {not implemented)
;*            (0x70)
;*   +  100 - (0x80) - Direct Functions
;*            (0x90) - Direct Functions
;*   +  101 - (0xA0) - Request functions
;*            (0xB0) - Reserve
;*      110 - (0xC0) - Special functions
;*            (0xD0) - Reserve
;*   +  111 - (0xE0) - Parameter read from SRAM  (Byte)
;*            (0xF0) - Parameters read from SRAM  (2 Byte)
;***********************************************************************
command:
        ldi     ZL,low(rbuffer+1)
        ld      COMMAND,Z+
        cpi     COMMAND,0x20
        brcs    commandgrup
        ld      AL,Z+
        ld      AH,Z+
        mov     ARGUMENT,COMMAND
        ldi     TEMP,0x0F               ; Argument address extraction
        and     ARGUMENT,TEMP
        swap    COMMAND
        and     COMMAND,TEMP
        mov     ZL,COMMAND
        lsr     ZL
        subi    ZL,low(-commandgrup)
        ijmp
commandgrup:                            ; Command groups separation
        rjmp    none                    ; Data blocks loading
        rjmp    parameterset
        rjmp    parameterfunction
        rjmp    none

        rjmp    simplefunction
        rjmp    datafunction
        rjmp    special                 ; C0-D0
        rjmp    parameterget

simplefunction:                         ; Direct functions decoding
        ldi     ZL,low(sfunction)
        add     ZL,ARGUMENT
        ijmp
sfunction:
        rjmp    comm_illum_on           ; Illumination turn on     (0x80)
        rjmp    comm_illum_off          ; Illumination turn off    (0x81)
        rjmp    comm_light_on           ; Control light turn on    (0x82)
        rjmp    comm_light_off          ; Control light turn off   (0x83)
        rjmp    comm_vary_on            ; Modulation turn on       (0x84)
        rjmp    comm_vary_off           ; Modulation turn off      (0x85)
        rjmp    none                    ; ACN signal               (0x86)
        rjmp    soft_reset              ; Software reset (0x87)

        rjmp    comm_voltage_on         ; High voltage turn on     (0x88)
        rjmp    comm_voltage_off        ; High voltage turn off    (0x89)
        rjmp    comm_safety_on          ; Safety turn on           (0x8A)
        rjmp    comm_safety_off         ; Safety turn off          (0x8B)
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none

datafunction:                           ; Request functions decoding
        ldi     ZL,low(dfunction)
        add     ZL,ARGUMENT
        ijmp
dfunction:
        rjmp    none
        rjmp    none
        rjmp    identification          ; Module identification request
        rjmp    constants               ; Module constants request
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none

special:
        tst     ARGUMENT
        brne    PC+2
        rjmp    flash_update            ; Switch to FlashWriter (0xC0)
        rjmp    none

parameterset:                           ; Argument(s) write into SRAM
parameterfunction:                      ; Command with argument(s)
        ldi     ZL,low(parameters)
        add     ZL,ARGUMENT
        st      Z+,AL
        sbrc    COMMAND,0               ; 1-byte or 2-bytes?
        st      Z+,AH
        sbrs    COMMAND,2               ; Write or write and execute
        rjmp    yes
        ldi     ZL,low(pfunction)
        add     ZL,ARGUMENT
        ijmp
pfunction:                              ; Associated command decoding
        rjmp    none
        rjmp    comm_illum_set          ; Set illumination level
        rjmp    comm_light_set          ; Set control light level
        rjmp    none
        rjmp    comm_voltage_set        ; Set high voltage level
        rjmp    none
        rjmp    none
        rjmp    none

        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none
        rjmp    none

parameterget:                           ; Parameter(s) read from SRAM
        ldi     ZL,low(parameters)
        st      Z,STATUS
        add     ZL,ARGUMENT
        ldi     TEMP_CNT,2
        sbrc    COMMAND,0
        inc     TEMP_CNT
        ldi     YL,low(tbuffer-1)
        st      Y+,TEMP_CNT
        dec     TEMP_CNT
        st      Y+,TEMP_CNT
        rcall   rr_copy
        st      Y+,YH
        rjmp    crc_gen

none:   ldi     TRANSMIT,ACN            ; ACN Signal
        rjmp    signal

yes:    ldi     TRANSMIT,ACY            ; ACY Signal
        rjmp    signal

busy:   ldi     TRANSMIT,ACW            ; ACW Signal
        rjmp    signal

mirror_check:
        sbic    PINC,HALL
        rjmp    clm
        sbrc    STATUS,MIRROR
        rjmp    mainf
        inc     CHATTER
        brne    mainf
        dec     CHATTER
        sbr     STATUS,(1<<MIRROR)
clm:    sbrs    STATUS,MIRROR
        rjmp    mainf
        dec     CHATTER
        brne    mainf
        cbr     STATUS,(1<<MIRROR)
        rjmp    mainf

;***********************************************************************
;*                  Main
;***********************************************************************
Start:                                  ; Entry
        ldi     TEMP,low(RAMEND)        ; Stack Pointer initialization
        out     SPL,TEMP
        ldi     TEMP,high(RAMEND)
        out     SPH,TEMP

        ldi     TEMP,BDIRECT            ; Port B tuning
        out     DDRB,TEMP
        ldi     TEMP,BMASK
        out     PORTB,TEMP

        ldi     TEMP,CDIRECT            ; Port C setting
        out     DDRC,TEMP
        ldi     TEMP,CMASK
        out     PORTC,TEMP

        ldi     TEMP,DDIRECT            ; Port D setting
        out     DDRD,TEMP
        ldi     TEMP,DMASK
        out     PORTD,TEMP

        rcall   sram_initialization     ; Copy data into SRAM (YH=0, ZH=0)
        rcall   exchange_initialization ; Initialization of the exchange features (XH=0)
        rcall   work_initialization     ; Initialization  of the functional features

        lds     STATUS,mod_status
        ldi     LINE_CSR,1<<LINE_BUSY
        sei
        rcall identification
main:   rjmp    mirror_check
mainf:  sbrc    LINE_CSR,FAILURE
        rcall   transmit_repeat
        sbrs    LINE_CSR,RECV_READY     ; Check receiver
        rjmp    main
        cbr     LINE_CSR,1<<RECV_READY
        rcall   crc_check
        brne    main
        rcall   command
        rjmp    main

flash_update:                           ; Moving interrupts to boot section
        ldi     TRANSMIT,ACY
        rcall   signal
        sbrc    LINE_CSR,LINE_BUSY
        rjmp    PC-1
        jmp     BLS

soft_reset:
        ldi     TRANSMIT,ACY
        rcall   signal
        sbrc    LINE_CSR,LINE_BUSY
        rjmp    PC-1
        rjmp    Start

;***********************************************************************
;*                      Interrupt handlers
;***********************************************************************
overlight_monitor:                      ; Overlight signal interrupt INT1
        in      SREG_COPY,SREG          ; handler
        sbr     STATUS,1<<OVERLIGHT
        sbrs    STATUS,SAFETY
        rjmp    ov1
        sbr     STATUS,1<<LOCK_HV
        cbr     STATUS,1<<HV_ON
        sbi     PORTC,SHUTDOWN          ; High voltage turn off
ov1:    out     SREG,SREG_COPY
        reti

syncronization:                         ; Change control light synchronously with strob
        in      SREG_COPY,SREG
        push    ZL
        push    AL
        inc     POINTER
        sbrc    POINTER,2
        clr     POINTER
        ldi     ZL,fluxes
        add     ZL,POINTER
        ld      AL,Z
        rcall   load01
        clr     AL
        dec     AL
        out     TCNT0,AL
        pop     AL
        pop     ZL
        out     SREG,SREG_COPY
        reti

long_cycle:                             ; Cycle for temperature and mirror control
        in      SREG_COPY,SREG
	sbrc    STATUS,ILLUM
	sbi	PORTB,IL_LOAD
        sbi     ADCSR,ADSC
        out     SREG,SREG_COPY
        reti

illum_clear:
	cbi	PORTB,IL_LOAD
	reti


convertion_complete:                     ; ADC handler
        in      SREG_COPY,SREG
        push    ZL                        ; Temperature control : temperature = U/2
        ldi     ZL,temp_data
        ld      RL,Z+
        ld      RH,Z+
        in      TREG,ADCL
        add     RL,TREG
        in      TREG,ADCH
        adc     RH,TREG
        inc     COUNTS
        sbrc    COUNTS,6                ; 64 measurements
        rjmp    norm
        st      -Z,RH
        st      -Z,RL
        pop     ZL
        out     SREG,SREG_COPY
        reti
norm:   clr     COUNTS                  ; Normalization for -20 +45 range
        ldi     TREG,0x1E               ; Sub 0x1E00 from summ of 64 meas
        sub     RH,TREG
        lsl     RL
        rol     RH
        lsl     RL
        rol     RH                      ; Mutiplied by 4
        sts     temperature,RH
        st      -Z,ZH
        st      -Z,ZH
        pop     ZL
        out     SREG,SREG_COPY
        reti

;***********************************************************************
;*                      Interrupt handlers for RS485 exchange
;***********************************************************************
receiver:
        in      SREG_COPY,SREG
        sbis    UCSRB,RXB8              ; Packet header check
        rjmp    receiv_continue         ; It is not header!
        in      RECEIVE,UDR
        tst     RECEIVE
        brpl    receiv_adress           ; It is address byte
        sbrs    LINE_CSR,DATA_SENDING    ; Expected signal?
        rjmp    receiv_return           ; No
        cbr     LINE_CSR,1<<DATA_SENDING
        cpi     RECEIVE,ACK
        breq    receiv_return
        sbr     LINE_CSR,(1<<FAILURE)
        rjmp    receiv_return
receiv_adress:                          ; New transaction
        cbr     LINE_CSR,(1<<DATA_SENDING)|(1<<RECEIVING)
        andi    RECEIVE,MAXADRESS
        lds     BYTE_CNT,adress
        cpse    RECEIVE,BYTE_CNT        ; The module address
        rjmp    receiv_return
        sbr     LINE_CSR,1<<RECEIVING   ; Our packet begin
        ldi     XL,low(rbuffer)
        st      X+,RECEIVE
        clr     BYTE_CNT
        rjmp    receiv_return
receiv_continue:
        in      RECEIVE,UDR
        sbrs    LINE_CSR,RECEIVING
        rjmp    receiv_return
        tst     BYTE_CNT                ; Next bytes from our packet
        brne    rec_end
        cpi     RECEIVE,0x20            ; Packet length computation
        brcs    datum
        brlt    noarg
        inc     BYTE_CNT
        sbrc    RECEIVE,MODIFICATOR
        inc     BYTE_CNT
noarg:  inc     BYTE_CNT
        inc     BYTE_CNT                ; For CRC byte
        sts     rnumber,BYTE_CNT
rec_end:st      X+,RECEIVE
        dec     BYTE_CNT
        brne    receiv_return
rec_zero:
        sbr     LINE_CSR,1<<RECV_READY  ; This packet for module itself
        cbr     LINE_CSR,1<<RECEIVING
receiv_return:
        out     TCNT2,BOTTOM            ; Перезапуск, счетчик уже запущен Проверить!!!!
        ldi     XH,(1<<OCIE2)|(1<<TOIE2)
        out     TIFR,XH
        clr     XH
        out     SREG,SREG_COPY
        reti
datum:  mov     BYTE_CNT,RECEIVE
        tst     BYTE_CNT
        breq    rec_zero
        inc     BYTE_CNT
        inc     BYTE_CNT
        sts     rnumber,BYTE_CNT
        rjmp    rec_end

transmitt_complete:
        in      SREG_COPY,SREG
        cbi     UCSRB,TXB8
        dec     BYTE_CNT
        brpl    transm_continue
        cbi     UCSRB,TXCIE
        cbi     PORTD,DE                ; Disconnect from line
        out     TCNT2,BOTTOM            ; Line timer start
        ldi     XH,(1<<CS22)
        out     TCCR2,XH
        ldi     XH,(1<<OCIE2)|(1<<TOIE2)
        out     TIFR,XH
        clr     XH
        out     SREG,SREG_COPY
        reti
transm_continue:
        ld      TRANSMIT,X+
        out     UDR,TRANSMIT
        out     SREG,SREG_COPY
        reti

line_monitor:
        in      SREG_COPY,SREG
        cbi     PORTD,YELLOW
        in      XH,GIMSK                ;запрет прерывания по стартовому биту
        cbr     XH,(1<<INT0)
        out     GIMSK,XH
        sbr     LINE_CSR,(1<<LINE_BUSY) ;установка флага LINE_BUSY
        out     TCNT2,BOTTOM            ; Run Timer2
        ldi     XH,(1<<CS22)
        out     TCCR2,XH
        ldi     XH,(1<<OCIE2)|(1<<TOIE2)
        out     TIFR,XH
        clr     XH
        out     SREG,SREG_COPY
        reti

switch_timeout:                         ; Switch timeout handler
        in      SREG_COPY,SREG
        sbrc    LINE_CSR,DATA_SENDING   ; Signal transmission or
        rjmp    data_trans
        sbi     UCSRB,TXB8              ; data transmission start
        clr     BYTE_CNT
data_trans:
        sbi     PORTD,DE                ; Connect transmitter to line
        out     UDR,TRANSMIT
        sbi     UCSRB,TXCIE
        out     TCCR2,XH                ; Timer 2 stop
        in      XH,TIMSK                ; Switch interrup disable
        cbr     XH,(1<<OCIE2)
        out     TIMSK,XH
        clr     XH
        out     SREG,SREG_COPY
        reti

window_timeout:                         ; Window timeout handler
        in      SREG_COPY,SREG
        sbrc    LINE_CSR,RECEIVING
        rjmp    gap                     ; Receiving packet break
        sbrc    LINE_CSR,DATA_SENDING
        rjmp    sloss                   ; Replied signal loss
line_free:
        cbr     LINE_CSR,1<<LINE_BUSY   ; Line free
        ldi     XH,(1<<INT0)
        out     GIFR,XH
        in      XH,GIMSK                ; Line monitor enabled
        sbr     XH,(1<<INT0)
        out     GIMSK,XH
        clr     XH
        out     TCCR2,XH                ; Timer stop
        sbi     PORTD,YELLOW
        out     SREG,SREG_COPY
        reti

sloss:  cbr     LINE_CSR,1<<DATA_SENDING
        sbr     LINE_CSR,1<<FAILURE
        rjmp    line_free

gap:    cbr     LINE_CSR,1<<RECEIVING
;        ldi     TRANSMIT,NAK
;        rcall   signal+1
        rjmp    line_free

;***********************************************************************
;               Exchange subroutines
;***********************************************************************

transmit_repeat:
        cbr     LINE_CSR,(1<<FAILURE)
        ld      TEMP_CNT,X
        dec     TEMP_CNT                ; MAXRETRY - число попыток
        breq    noattempt
        st      X,TEMP_CNT
        rjmp    transmit_init           ; rjmp    noattempt - подработка в motor_tn
noattempt:
        ret

transmit_init:                          ; Инициализация передачи данных
        ldi     XL,low(tbuffer-1)
        ld      BYTE_CNT,X+
        ld      TRANSMIT,X+
        sbr     LINE_CSR,1<<DATA_SENDING
signal:                                 ; передача сигнала квитирования
        in      TEMP,TIMSK              ; Interrupt enable for transmission start
        sbr     TEMP,(1<<OCIE2)
        out     TIMSK,TEMP
        ret

;***********************************************************************
;               Functional subroutines
;***********************************************************************
exchange_initialization:                ; UART  initialization
        lds     TEMP,low(baud)
        tst     TEMP
        brpl    wi1
        sbi     UCSRA,U2X
        clr     TEMP
wi1:    out     UBRRL,TEMP
        ldi     TEMP,(1<<TXEN)|(1<<RXEN)|(1<<RXCIE)|(1<<CHR9)
        out     UCSRB,TEMP
                                        ; Timer2 - line timer
        lds     BOTTOM,tbottom
        lds     TEMP,tswitch            ; Set
	out 	OCR2,TEMP
        out     TCNT2,BOTTOM
        ldi     TEMP,(1<<CS22)
        out     TCCR2,TEMP              ; Set normal mode  with 1/64 prescaler
        ldi     TEMP,(1<<OCIE2)|(1<<TOIE2)
        out     TIFR,TEMP
        ldi     TEMP,(1<<TOIE2)
        out     TIMSK,TEMP

        ldi     TEMP,(1<<ISC01)         ; Interrupts INT0  on falling edge - line monitor
        out     MCUCR,TEMP
        ldi     TEMP,(1<<INT0)          ; Line monitor enable
        out     GIFR,TEMP
        out     GIMSK,TEMP
        clr     XH
        ret

work_initialization:

        ldi     TEMP,(1<<CS02)|(1<<CS01); Timer 0 external on falling edge
        out     TCCR0,TEMP

        ldi     TEMP,(1<<CS11)|(1<<CS10)|(1<<CTC1)
        out     TCCR1B,TEMP             ; Timer 1 set up f/64 and clear on compare match
        ldi     TEMP,high(fcycle)
        out     OCR1AH,TEMP             ; Loading  long cycle
        ldi     TEMP,low(fcycle)
        out     OCR1AL,TEMP

       	lds     AL,illum_bright
	rcall	illumination_set
        ldi     TEMP,(1<<OCIE1B)|(1<<OCIE1A)
        out     TIFR,TEMP               ; Timer 1 flags  clear
        in      TEMP,TIMSK              ; Interrupts enable
        sbr     TEMP,(1<<OCIE1B)|(1<<OCIE1A)
        out     TIMSK,TEMP

        in      TEMP,MCUCR              ; Interrupts INT1  on falling edge - overlight
        sbr     TEMP,(1<<ISC11)
        out     MCUCR,TEMP
                                        ; Initialization  of the ADC
        ldi     TEMP,(1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)
        out     ADCSR,TEMP
        ldi     TEMP,(1<<REFS1)|(1<<REFS0)|(1<<MUX2)|(1<<MUX1)
        out     ADMUX,TEMP
                                        ; SPI_MasterInit: Mode 0, f/4
        ldi     TEMP,(1<<MSTR)
        out     SPCR,TEMP
        ret

comm_vary_on:                           ; Light modulation initialization
        sbrc    STATUS,MODULATION
        rjmp    busy
        sbr     STATUS,(1<<MODULATION)|(1<<CONTROL)
        ldi     ZL,light_bright
        ld      AL,Z+                   ; The mean light level
        ld      AH,Z+                   ; Amplitude
        ldi     ZL,fluxes
        st      Z+,AL                   ; The mean light level
        mov     TEMP,AL
        add     TEMP,AH
        st      Z+,TEMP                 ; The mean light level + amplitude
        st      Z+,AL                   ; The mean light level
        mov     TEMP,AL
        sub     TEMP,AH
        st      Z+,TEMP                 ; The mean light level - amplitude
        rcall   load01

        ldi     TEMP,(1<<TOIE0)
        out     TIFR,TEMP
        in      TEMP,TIMSK
        sbr     TEMP,(1<<TOIE0)
        out     TIMSK,TEMP              ; Timer 0 overflow interrupt  enable
        clr     TEMP                    ; Tune T0 to first fall clocks
        dec     TEMP
        out     TCNT0,TEMP
        clr     POINTER
        rjmp    yes
comm_vary_off:
        cbr     STATUS,(1<<MODULATION)|(1<<CONTROL)
        in      TEMP,TIMSK
        cbr     TEMP,(1<<TOIE0)
        out     TIMSK,TEMP              ; Timer 0 overflow interrupt  enable
        rjmp    yes

comm_illum_off:                         ; Illumination turn off
        cbr     STATUS,1<<ILLUM
        rjmp    yes

comm_illum_on:                          ; Illumination turn on
        sbr     STATUS,1<<ILLUM
        rjmp    yes

comm_illum_set:
        rcall   illumination_set        ; Illumination level setting
        rjmp    yes

illumination_set:
        clr     AH
        lsl     AL
	rol	AH
        lsl     AL
	rol	AH
        out     OCR1BH,AH               ; Loading  long cycle
        out     OCR1BL,AL
	ret

comm_light_off:                         ; Control light turn off
        cbr     STATUS,1<<CONTROL
        rcall   light_set
        rjmp    yes
comm_light_on:                          ; Control light turn on
        sbr     STATUS,1<<CONTROL
comm_light_set:
        sbrc    STATUS,CONTROL
        rcall   light_set               ; Control light level setting
        rjmp    yes

comm_voltage_on:                        ; High voltage turn on command
        sbrs    STATUS,LOCK_HV          ; High voltage is locking
        sbrc    STATUS,OVERLIGHT
        rjmp    busy
        sbr     STATUS,(1<<HV_ON)
        cbi     PORTC,SHUTDOWN          ; High voltage turn on
        rjmp    yes

comm_voltage_off:                       ; High voltage turn off command
        cbr     STATUS,(1<<HV_ON)|(1<<LOCK_HV)
        sbi     PORTC,SHUTDOWN          ; High voltage turn off
        rjmp    yes

comm_safety_on:
        sbrc    STATUS,LOCK_HV
        rjmp    busy
        sbr     STATUS,1<<SAFETY
        ldi     TEMP,(1<<INT1)
        out     GIFR,TEMP
        in      TEMP,GIMSK              ;разрешение прерывания
        sbr     TEMP,(1<<INT1)
        out     GIMSK,TEMP
        rjmp    yes

comm_safety_off:
        sbrc    STATUS,LOCK_HV
        rjmp    busy
        cbr     STATUS,(1<<SAFETY)|(1<<OVERLIGHT)
        in      TEMP,GIMSK              ;запрет прерывания
        cbr     TEMP,(1<<INT1)
        out     GIMSK,TEMP
        rjmp    yes


comm_voltage_set:                       ; Установка значения высокого напряжения
        lds     AL,voltage              ; (не зависит от  бита  HV_ON  в STATUS
load00:                                 ; Загрузка величины уровня на AD8402 / A=00
        cbi     PORTB,LOAD              ; Select
        sbi     PORTB,SCK
        cbi     PORTB,SCK               ; Adress 0b00
        sbi     PORTB,SCK
        cbi     PORTB,SCK
        sbi     SPCR,SPE
        out     SPDR,AL
        sbis    SPSR,SPIF
        rjmp    PC-1
        sbi     PORTB,LOAD              ; Level is changed here
        cbi     SPCR,SPE
        rjmp    yes

light_set:                              ; Control light level setting
        clr     AL                      ; or turning off depending
        sbrc    STATUS,CONTROL          ; on STATUS
        lds     AL,light_bright
load01:                                 ; Load level into AD8402
        cbi     PORTB,LOAD              ; Select
        sbi     PORTB,SCK
        cbi     PORTB,SCK               ; Adress 0b01
        sbi     PORTB,MOSI
        sbi     PORTB,SCK
        cbi     PORTB,SCK
        sbi     SPCR,SPE
        out     SPDR,AL
        sbis    SPSR,SPIF
        rjmp    PC-1
        cbi     PORTB,MOSI
        sbi     PORTB,LOAD              ; Level is changed here
        cbi     SPCR,SPE
        ret

constants:                              ; Module constants transmission
        ldi     ZL,low(apparatus*2)
        skip
identification:                         ; Module identification transmission
        ldi     ZL,low(identno*2)
        ldi     TEMP_CNT,5              ; Data length + 1
        ldi     YL,low(tnumber)
        st      Y+,TEMP_CNT             ; Block length
        dec     TEMP_CNT
        st      Y+,TEMP_CNT             ; Data header
id0:    lpm     R0,Z+                   ; From table to
        st      Y+,R0                   ; transmitter buffer copy
        dec     TEMP_CNT
        brne    id0
        st      Y+,YH                   ; 0 instead CRC
        rjmp    crc_gen

;***********************************************************************
;               General subroutines (do not use in interrupt handlers)
;***********************************************************************
sram_initialization:
                                        ; Clear 128 bytes of the SRAM
        ldi     YL, parameters
        clr     YH
        ldi     TEMP_CNT,0x80
cl1:    st      Y+,XH
        dec     TEMP_CNT
        brne    cl1
                                        ; Copy block from FLASH into SRAM
        ldi     ZL,low(line*2)
        clr     ZH
        ldi     YL,low(adress)
        ldi     TEMP_CNT,NLINE          ; Number of bytes
fl0:    lpm     R0,Z+
        st      Y+,R0
        dec     TEMP_CNT
        brne    fl0

        ldi     ZL,low(defaults*2)
        ldi     TEMP_CNT,2*(enddefaults-defaults) ; Number of bytes
        ldi     YL,low(illum_bright)
fl1:    lpm     R0,Z+
        st      Y+,R0
        dec     TEMP_CNT
        brne    fl1
        ret

rr_copy:                                ; Copy block SRAM to SRAM
        ld      TEMP,Z+
        st      Y+,TEMP
        dec     TEMP_CNT
        brne    rr_copy
        ret

crc_check:                              ; CRC check
        ldi     YL,low(rbuffer-1)
        rcall   crc
        tst     AH
        breq    crc_ok
        ldi     TRANSMIT,NAK
        rcall   signal
        clz
crc_ok: ret

crc_gen:                                ; Add CRC while transmission
        ldi     TEMP,MAXRETRY
        st      Y,TEMP
        ldi     YL,low(tbuffer-1)
        rcall   transmit_init

crc:    ld      TEMP_CNT,Y+             ; CRC computation
        ld      AH,Y+
        ldi     TEMP,DIVISOR
cr2:    ld      AL,Y+
        lsl     AL
        rol     AH
        brcc    PC+2
        eor     AH,TEMP                 ; CRC в старшем байте AH
        lsl     AL
        rol     AH
        brcc    PC+2
        eor     AH,TEMP
        lsl     AL
        rol     AH
        brcc    PC+2
        eor     AH,TEMP
        lsl     AL
        rol     AH
        brcc    PC+2
        eor     AH,TEMP
        lsl     AL
        rol     AH
        brcc    PC+2
        eor     AH,TEMP
        lsl     AL
        rol     AH
        brcc    PC+2
        eor     AH,TEMP
        lsl     AL
        rol     AH
        brcc    PC+2
        eor     AH,TEMP
        lsl     AL
        rol     AH
        brcc    PC+2
        eor     AH,TEMP
        dec     TEMP_CNT
        brne    cr2
        st      -Y,AH
        ret

;***********************************************************************
;               SRAM organization
;***********************************************************************
.dseg
.org    0x60                    ; Parameters area (access via commands)
parameters:                     ; Initially loaded from EEPROM
mod_status:                     ; The all in inner units
        .byte   1               ; Copy of STATUS register for external access
illum_bright:
        .byte   1               ; Brightness of illumination
light_bright:
        .byte   1               ; Brightness of control light
amplitude:
        .byte   1               ; Modulation amplitude
voltage:
        .byte   1               ; Величина высокого напряжения
temperature:
        .byte   1               ; значение температуры во внутренних единицах

.org    0x6D
key:    .byte   2               ; Key for program restart

.org    0x70                    ; Exchange paraneters, loaded from FLASH

adress: .byte   1               ; The module address
baud:   .byte   1               ; Exchange rate
tbottom:.byte   1               ; Line timer bottom value for WINDOW generation
tswitch:.byte   1               ; Transmittance switch delay

fluxes: .byte   4               ; Modulated fluxes

.org    0x78                    ; Variables area (access impossible)
temp_data:
        .byte   2
rnumber:.byte   1
rbuffer:.byte   21              ; Receiver buffer

tnumber:.byte   1
tbuffer:.byte   21              ; Transmitter buffer

.exit
