;***********************************************************************
;*              BiCounter photometric module
;*              MASS/DIMM
;*              Circuit diagrams:  Counter7400-4
;*              Circuit boards:    Counter7400-4
;*              Last modification:      06.09.03
;***********************************************************************

.include "m8def.inc"
.include "bicounter.inc"

.equ    BLS=    0x0e00
;***********************************************************************
;*                  Main programm interrupt table
;***********************************************************************
.cseg
.org $0000
        rjmp    Start                   ; Programm start, Reset handler
.org INT0addr
        rjmp    line_monitor            ; RS485 line monitor handler
.org INT1addr
        rjmp    microexposition         ; Microexposition data handler
.org OC2addr
        rjmp    strob_generation        ; Counter timing
.org OVF2addr
	reti
.org ICP1addr
	reti
.org OC1Aaddr
        reti
.org OC1Baddr
	reti
.org OVF1addr
	reti
.org OVF0addr
        rjmp    timer0                  ; Software extension of counter 0 ( 8 MSB )
.org SPIaddr
	reti
.org URXCaddr
        rjmp    receiver                ; UART receiver handler
.org UDREaddr
	reti
.org UTXCaddr
        rjmp    transmitt_complete      ; UART transmitter handler
.org ADCCaddr
        rjmp    adc_linetimer           ; Line timer handler
.org ERDYaddr
	reti
.org ACIaddr
	reti
.org TWIaddr
	reti
.org SPMaddr
	reti

;***********************************************************************
;*                  Flash constant section
;***********************************************************************
.cseg
.org $0013
identno:
        .dw     iddev
        .dw     pdate

line:
        .db     COUNTER, fbaudrate      ; Line constants
        .db     fwindow, fswitch

apparatus:				; Constants
        .db     0x44, 0x00
        .dw     freq

defaults:
        .db     (1<<EXTERNAL),128       ; Default STATUS, default threshold of descrimination A
        .db     128,0  			; default threshold of descrimination B, free byte
        .dw     1838                    ; Default exposure (1.0ms - 1838)
        .db     low(128),high(128)	; Default expositions series lenght
        .db     16,1                    ; Data block size (bytes), Def. inductor adress
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+
        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
        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    measurement_begin       ; Start up exposition series (0x80)
        rjmp    measurement_stop        ; Halt of exposition series (0x81)
        rjmp    extern_on               ; Use an extenal sync.clock on (0x82)
        rjmp    extern_off              ; Generation of sync.clock on (0x83)
        rjmp    shorter_on              ; One byte per count format on (0x84)
        rjmp    shorter_off             ; Two byte per count format on (0x85)
        rjmp    incremental_test        ; Start up decremental test (0x86)
	rjmp   	soft_reset              ; Software reset (0x87)
        rjmp    active_on               ; Active mode on (0x88)
        rjmp    active_off              ; Active mode off (0x89)
        rjmp    induce_on               ; Inductive mode on (0x8A)
        rjmp    induce_off              ; Inductive mode off (0x8B)
        rjmp    none                    ; ACN Signal
        rjmp    none                    ; ACN Signal
        rjmp    none
        rjmp    none

datafunction:                           ; Request functions decoding
        ldi     ZL,low(dfunction)
        add     ZL,ARGUMENT
        ijmp
dfunction:
        rjmp    require                 ; Request of a new data block
        rjmp    none                    ; ACN Signal
        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_level_setA         ; Discrimination threshold setting
        rjmp    comm_level_setB		; Discrimination threshold setting
        rjmp    none
        rjmp    comm_exposition_set     ; Integration time setting:
        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		; 2 byte
        ldi     YL,low(tbuffer-1)
        st      Y+,TEMP_CNT             ; actual_size+1
        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

active_on:                              ; Active mode on
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
        sbr     STATUS,(1<<ACTIVE)
        rjmp    yes

active_off:
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
        cbr     STATUS,(1<<ACTIVE)
        rjmp    yes

extern_on:                              ; Use an extenal synchro clock on
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
        sbr     STATUS,(1<<EXTERNAL)
        rjmp    yes

extern_off:                             ; Generation of synchro clock on
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
        cbr     STATUS,(1<<EXTERNAL)
        rjmp    yes

shorter_on:                             ; One byte per count format on
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
        sbr     STATUS,(1<<SHORTED)
        rjmp    yes

shorter_off:                            ; Two byte per count format on
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
        cbr     STATUS,(1<<SHORTED)
        rjmp    yes

induce_on:                              ; Inductive mode on
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
        sbr     STATUS,(1<<INDUCED)
        rjmp    yes

induce_off:                             ; Inductive mode off
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
        cbr     STATUS,(1<<INDUCED)
        rjmp    yes

;***********************************************************************
;*                  Main section
;***********************************************************************

Start:
	cli
        ldi     TEMP,low(RAMEND)        ; Stack Pointer initialization
        out     SPL,TEMP
        ldi     TEMP,high(RAMEND)
        out     SPH,TEMP

        ldi     TEMP, BDMask            ; Port B setting
	out 	DDRB, TEMP
	ldi 	TEMP,BMask
	out 	PORTB,TEMP

        ldi     TEMP, CDMask            ; Port C setting
	out 	DDRC, TEMP
	ldi 	TEMP,CMask
	out	PORTC,TEMP

        ldi     TEMP, DDMask            ; Port D setting
	out	DDRD, TEMP
	ldi 	TEMP,DMask
	out 	PORTD,TEMP

        rcall   sram_initialization     ; Copy data to SRAM
        rcall   exchange_initialization ; Initialization of the exchange features
        rcall   work_initialization     ; Initialization  of the functional features
	rcall	level_setA
	rcall	level_setB
        ldi     LINE_CSR,(1<<LINE_BUSY)
        sei             ; Interrupts enable
main:   sbrc    STATUS,DATA_READY       ; New count ready?
        rcall   convert
        sbrc    LINE_CSR,FAILURE        ; Transmission failure?
        rcall   transmit_repeat         ;
        sbrc    LINE_CSR,LINE_BUSY      ; When line will free?
        rjmp    main1
        sbrs    STATUS,BLOCK_READY      ; Data block ready?
        rjmp    main1
        sbrs    STATUS,ACTIVE           ; Is module Active?
        sbrc    LINE_CSR,INDUCE_PASS    ; Has inductor transmitted packet?
        rcall   senddata
main1:  sbrs    LINE_CSR,RECV_READY     ; Receiving complete?
        rjmp    main
        cbr     LINE_CSR,1<<RECV_READY  ; New command was received
        rcall   crc_check               ; CRC check
        brne    main                    ; CRC invalid
        rcall   command                 ; To commands decoding
        rjmp    main                    ; Main loop end

flash_update:                           ; Jump to boot section
        ldi     TRANSMIT,ACY
        rcall   signal
        sbrc    LINE_CSR,LINE_BUSY
        rjmp    PC-1
        jmp     BLS

soft_reset:                             ; Software reset
        ldi     TRANSMIT,ACY
        rcall   signal
        sbrc    LINE_CSR,LINE_BUSY
        rjmp    PC-1
        rjmp    Start

;***********************************************************************
;*                  Most significant functional Interrupt
;***********************************************************************

strob_generation:
        in	SREG_COPY,SREG
	in	TREG,TCCR2
	sbrs	TREG,COM20
	rjmp	t2_pause
        dec     CYCLES
	breq	t2_last
;        sbrs    TREG,COM20
;        rjmp    t2_out
	ldi	TREG,0x80		; End of pause
	out	OCR2,TREG
t2_out: out	SREG,SREG_COPY
	reti
t2_pause:
	ldi	TREG,(1<<WGM21)|(1<<COM21)|(1<<COM20)|(1<<CS21)	; Set OC2 at next compare
	out	TCCR2,TREG
	ldi	TREG,fstrob_pause	; Load pause
	out	OCR2,TREG
;        mov     TREG,ZL
;        lds     ZH,exposition+1         ; Load exposure high
;        lds     ZL,exposition           ; Load exposure
;        sbiw    ZL,fstrob_pause
;        lsl     ZL
;        rol     ZH
;        sec                             ; ZL=7 low bit+0x80
;        ror     ZL
;        mov     EXPL,ZL
;        mov     EXPH,ZH
;        clr     ZH
;        mov     ZL,TREG
        mov     CYCLES,EXPH
        out	SREG,SREG_COPY
	reti
t2_last:
	ldi	TREG,(1<<WGM21)|(1<<COM21)|(1<<CS21)	; Clear OC2 at next compare
	out	TCCR2,TREG
	out	OCR2,EXPL
        out	SREG,SREG_COPY
	reti

Timer0:
        in      SREG_COPY,SREG          ; Counter 0 overflow handler (8bit)
        inc     CNT3
        out     SREG,SREG_COPY
        reti

microexposition:                        ; Microexposition finish handler
        in      SREG_COPY,SREG
        in      TREG,TIFR
        sbrc    TREG,TOV0
        inc     CNT3
;        in      TREG,PIND               ; Precounters
;        sts     cnt_data,TREG
;        in      TREG,PINC
;        sts     cnt_data+1,TREG
        in      DATAS,PIND
        in      DATA0,PINC
        in      DATA1,TCNT0              ; From Counter 0
;        sts     cnt_data+2,TREG
        mov     DATA2,CNT3
        in      TREG,TCNT1L             ; From Counter 1
        sts     cnt_data,TREG
        in      TREG,TCNT1H
        sts     cnt_data+1,TREG
        sbiw    NUMBL,0
        breq    mex1                    ; Infinite series
        sbiw    NUMBL,1                 ; Is series complete?
        brne    mex1
        sbr     STATUS,(1<<DATA_READY)
	cbr     STATUS,(1<<MEASUREMENT)
        in      TREG,GIMSK              ; Disable further interrupt
        cbr     TREG,(1<<INT1)
        out     GIMSK,TREG
;        cbi     PORTB,STROB
        out     TCCR2,YH		; Timer2: disconnect from OC2 and stop
        ldi     TREG,(1<<OCF2)		; Clear T2 flag
        out     TIFR,TREG
        out     SREG,SREG_COPY
        reti

mex1:   sbi     PORTD,MR                ; Next microexposition after pause
        cbi     PORTD,MR
        ldi     TREG,(1<<TOV0)|(1<<TOV1)
        out     TIFR,TREG
        clr     CNT3                    ; Counter0 additional byte reset
        out     TCNT0,CNT3              ; Counter 0 reset
        out     TCNT1H,CNT3             ; Counter 1 reset
        out     TCNT1L,CNT3
        sbr     STATUS,(1<<DATA_READY)
        out     SREG,SREG_COPY
        reti

;***********************************************************************
;*                  Most significant functional subroutine
;***********************************************************************


incremental_test:                       ; Decremental test initialization
        sbr     STATUS,(1<<TEST)
measurement_begin:                      ; Microexposition series begin
	sbrc    STATUS,MEASUREMENT
        rjmp    busy
        cbr     STATUS,(1<<BLOCK_READY)
        cbr     LINE_CSR,(1<<INDUCE_PASS)
        lds     NUMBL,number            ; Real counting will begin when strob = 1
        lds     NUMBH,number+1
        clr     POINTER
        sbi     PORTD,MR
        cbi     PORTD,MR
        clr     CNT3                    ; Counter0 additional byte reset
        out     TCNT0,CNT3              ; Counter 0 reset
        out     TCNT1H,CNT3             ; Counter 1 reset
        out     TCNT1L,CNT3
        ldi     TEMP,(1<<TOV0)|(1<<TOV1)
        out     TIFR,TEMP

        ldi     TEMP,(1<<INT1)          ; INT1 (STROB finish ) interrupt enable
        out     GIFR,TEMP
        in      TEMP,GIMSK
        sbr     TEMP,(1<<INT1)
        out     GIMSK,TEMP

        ldi     TEMP,data               ; Buffer preparing
        sts     active_buff,TEMP
        lds     TEMP,adress             ; Calculate begin number
        ori     TEMP,0xE0
        sts     pakage,TEMP

        sbr     STATUS,(1<<MEASUREMENT)
	sbrc	STATUS,EXTERNAL
        rjmp    yes                     ; Slave mode
        lds     EXPL,exposition         ; Master mode
        lds     EXPH,exposition+1
        ldi     TEMP,fstrob_pause
        sub     EXPL,TEMP
        sbc     EXPH,YH
        lsl     EXPL
        rol     EXPH
        sec
        ror     EXPL                    ; 7 low bits + 0x80
        out     TCNT2,YH
	cli
        in      SREG_COPY,SREG
	rcall	t2_pause		; start strob series
        rjmp    yes

measurement_stop:                       ; Microexposition series break
        clr     NUMBH
        ldi     NUMBL,1
        cli
        rcall   microexposition
        rjmp    yes

;***********************************************************************
;*                      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, Check destination
        cbr     LINE_CSR,(1<<DATA_SENDING)|(1<<RECEIVING)|(1<<INDUCTOR)
        andi    RECEIVE,MAXADRESS
        lds     BYTE_CNT,adress
        cp      RECEIVE,BYTE_CNT
        breq    my                      ; The module address
        sbrs    STATUS,INDUCED
        rjmp    receiv_return
        lds     BYTE_CNT,induct
        cp      RECEIVE,BYTE_CNT
        brne	receiv_return
        sbr     LINE_CSR,(1<<INDUCTOR)  ; Packet from inductor
my:     sbr     LINE_CSR,(1<<RECEIVING) ; Our packet begin
        ldi     XL,low(rbuffer)         ; Buffer initialization
        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 of the packet
        brne    rec_end
        cpi     RECEIVE,0x20            ; Packet length computation
        brcs    datum                   ; Data packet received
        brlt    noarg
        inc     BYTE_CNT
        sbrc    RECEIVE,MODIFICATOR
        inc     BYTE_CNT
noarg:  inc     BYTE_CNT
        inc     BYTE_CNT
        sts     rnumber,BYTE_CNT
        sbrc    LINE_CSR,INDUCTOR       ; This is no induce data pack
        cbr     LINE_CSR,(1<<RECEIVING)|(1<<INDUCTOR)
rec_end:st      X+,RECEIVE
        dec     BYTE_CNT
        brne    receiv_return
        sbrs    LINE_CSR,INDUCTOR
        sbr     LINE_CSR,(1<<RECV_READY); This packet for the module itself
        sbrc    LINE_CSR,INDUCTOR
        sbr     LINE_CSR,(1<<INDUCE_PASS); This packet is inductor only
rec_zero:
        cbi     ADCSR,ADEN              ; Line timer stop
        cbr     LINE_CSR,(1<<INDUCTOR)|(1<<RECEIVING)
        sbi     ADCSR,ADEN
        sbi     ADCSR,ADSC              ; Line timer start
receiv_return:
        clr     LINE_TIMER              ; Load of the line timer
        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:                     ; UART transmitter handler
        in      SREG_COPY,SREG
        cbi     UCSRB,TXB8              ; Header bit clear
        dec     BYTE_CNT
        brpl    transm_continue
        cbi     UCSRB,TXCIE             ; Transmission termination
        cbi     PORTD,DE                ; Disconnect transmitter from line
        clr     LINE_TIMER              ; Reload of the line timer
        sbi     ADCSR,ADSC              ; Line timer start
        out     SREG,SREG_COPY
        reti
transm_continue:
        ld      TRANSMIT,X+
        out     UDR,TRANSMIT
        out     SREG,SREG_COPY
        reti

line_monitor:                           ; Line monitor handler
        in      SREG_COPY,SREG
	sbr 	LINE_CSR,(1<<LINE_BUSY)
        clr     LINE_TIMER
        sbi     ADCSR,ADSC              ; Line timer start
        in      TREG,GIMSK              ; line_mon_off
        cbr     TREG,(1<<INT0)
        out     GIMSK,TREG
        out     SREG,SREG_COPY
        reti

adc_linetimer:
        in	SREG_COPY,SREG
        inc     LINE_TIMER
        cp      LINE_TIMER,SWITCH
        brcs    linetimer_run
        sbrc    LINE_CSR,TRANS_START
        rjmp    switch_timeout
        cp      LINE_TIMER,TOP
        brcs    linetimer_run
        rjmp    window_timeout
switch_timeout:                         ; Switch timeout handler
        cbr     LINE_CSR,(1<<TRANS_START)
        sbrc    LINE_CSR,DATA_SENDING
        rjmp    data_trans
        sbi     UCSRB,TXB8              ; Signal transmission start
        clr     BYTE_CNT
data_trans:                             ; Data transmission start
        sbi     PORTD,DE                ; Connect to line
        out     UDR,TRANSMIT
        sbi     UCSRB,TXCIE
        out     SREG,SREG_COPY          ; Line timer temporaly stopped
        reti

linetimer_run:
        sbi     ADCSR,ADSC
        out     SREG,SREG_COPY
        reti

window_timeout:                         ; Window timeout handler
        sbrc    LINE_CSR,RECEIVING
        rjmp    gap                     ; Receiving packet break
        sbrc    LINE_CSR,DATA_SENDING
        rjmp    sloss                   ; Return signal loss
line_free:
        cbr     LINE_CSR,(1<<LINE_BUSY) ; Line free
        ldi     TREG,(1<<INT0)
        out     GIFR,TREG
        in      TREG,GIMSK               ; Line monitor enabled
        sbr     TREG,(1<<INT0)
        out     GIMSK,TREG
        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

;***********************************************************************
;               RS485 exchange subroutines
;***********************************************************************

transmit_repeat:
        cbr     LINE_CSR,(1<<FAILURE)
        ld      TEMP_CNT,X
        dec     TEMP_CNT                ; MAXRETRY - number of the all retries
        breq    noattempt
        st      X,TEMP_CNT
        rjmp    transmit_init
noattempt:
        ret

transmit_init:                          ; Transmission initialization
        ldi     XL,low(tbuffer-1)
        ld      BYTE_CNT,X+
        ld      TRANSMIT,X+
        sbr     LINE_CSR,(1<<DATA_SENDING)
signal: sbr     LINE_CSR,(1<<TRANS_START)
        sbrc    LINE_CSR,LINE_BUSY
        ret
        sbi     UCSRB,TXB8              ; Active transmission
        mov     LINE_TIMER,SWITCH
        sbrc    STATUS,INDUCED
        clr     LINE_TIMER
        cli
        rjmp    adc_linetimer

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
        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

;***********************************************************************
;               Initialization subroutine
;***********************************************************************

sram_initialization:
        ldi     YL,0x60                 ; Clear all SRAM
fl1:    st      Y+,ZH
        tst     YL
        brne    fl1
        clr     YH

        ldi     ZL,low(line*2)		; Load line parameters
        clr     ZH
        ldi     TEMP_CNT,NLINE          ; Number of bytes
        ldi     YL,low(adress)
fl0:    lpm     TEMP,Z+
        st      Y+,TEMP
        dec     TEMP_CNT
        brne    fl0

        ldi     ZL,low(defaults*2)	; Load default settings
        ldi     TEMP_CNT,2*(enddefaults-defaults)	; Number of bytes
        ldi     YL,low(parameters)
fl2:    lpm     TEMP,Z+
        st      Y+,TEMP
        dec     TEMP_CNT
        brne    fl2
        lds     STATUS,mod_status       ; Load STATUS register
        ret

exchange_initialization:
        lds     TEMP,baud                ; UART initialization
        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
        lds     TOP,twindow
        lds     SWITCH,tswitch

        ldi     TEMP,(1<<ISC01)         ; Interrupts INT0 at falling edge - line monitor
        out     MCUCR,TEMP
        ldi     TEMP,(1<<INT0)          ; Line monitor enable
        out     GIFR,TEMP
        out     GIMSK,TEMP
                                        ; ADC converter - Line timer
        ldi     TEMP,(1<<REFS1)|(1<<REFS0)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(1<<MUX0)    ;GND
	out	ADMUX,TEMP
        ldi     TEMP,(1<<ADEN)|(1<<ADIE)|(1<<ADPS1)|(1<<ADPS0)             ;XTAL/16
        out     ADCSR,TEMP
        clr     XH
	ret

work_initialization:
        ldi     TEMP,(1<<CS02)|(1<<CS01); Timer0 - counts external clock  at falling edge
        out     TCCR0,TEMP
        out     TCNT0,YH
        ldi     TEMP,(1<<CS12)|(1<<CS11); Timer0 - counts external clock  at falling edge
        out     TCCR1B,TEMP
        out     TCNT1H,YH
        out     TCNT1L,YH
                                        ; Timer2 - CTC mode
        out     TCNT2,YH
;        ldi     TEMP,fstrob_pause
;        out     OCR2,TEMP
        out     TCCR2,YH
        ser     TEMP
        out     TIFR,TEMP               ; Clear all flags

        ldi     TEMP,(1<<OCIE2)|(1<<TOIE0)
        out     TIMSK,TEMP              ; Timers interrupt enable

        in      TEMP,MCUCR              ; Interrupts INT1 (strob) at falling edge
        sbr     TEMP,(1<<ISC11)
        out     MCUCR,TEMP
        ldi     TEMP,(1<<INT1)          ; Clear INT1
        out     GIFR,TEMP
                                        ; SPI at mode 0, Double speed, master, No Int,
	ldi	TEMP,(1<<SPI2X)
	out	SPSR,TEMP
        ldi     TEMP,(1<<MSTR)
        out     SPCR,TEMP

        ldi     TEMP,data
        sts     active_buff,TEMP
        ret

;***********************************************************************
;               Functional and data processing subroutine
;***********************************************************************

convert:                            	; New count handle
;        ldi     YL,cnt_data+4
;;;        lds     TEMP,cnt_data
;        mov     TEMP,DATA2
;        ld      TEMP,Y+
        bst     DATAS,T0
;;;        lds     DATA0,cnt_data+1
        mov     TEMP,DATA0
;        ld      DATA0,Y+
        bld     DATA0,6
        lsl     DATA0
;        ld      DATA1,Y+
;        ld      DATA2,Y+

        ldi     TEMP_CNT,4
cn0:    lsr     DATA2
        ror     DATA1
        ror     DATA0
        dec     TEMP_CNT
        brne    cn0

        lds     ZL,active_buff          ; New count A to buffer saving
        add     ZL,POINTER

        sbrc    STATUS,TEST
        movw    DATA0,NUMBL
        st      Z+,DATA0		; write current count A to SRAM
        inc     POINTER
        sbrc    STATUS,SHORTED
        rjmp    cn_b
        st      Z+,DATA1
        inc     POINTER

cn_b:   bst     DATAS,T1
;        lds     DATA0,cnt_data+1
        mov     DATA0,TEMP
        bld     DATA0,3
        swap    DATA0
        lds     DATA1,cnt_data
        lds     DATA2,cnt_data+1

        ldi     TEMP_CNT,4
cn1:    lsr     DATA2
        ror     DATA1
        ror     DATA0
        dec     TEMP_CNT
        brne    cn1

        sbrc    STATUS,TEST
        movw    DATA0,NUMBL
        st      Z+,DATA0                ; New count B to buffer saving
        inc     POINTER			; write current count B to SRAM
        sbrc    STATUS,SHORTED
        rjmp    cn_ctrl
        st      Z+,DATA1
        inc     POINTER

cn_ctrl:lds     TEMP,block_size         ; Is data block full?
        cp      POINTER,TEMP
        breq    blockready
        sbrc    STATUS,MEASUREMENT	;
	rjmp	cn_out
blockready:                             ; Data block is ready
        ldi     ZL,pakage               ; Block cyclic number modification
        ld      TEMP,Z
        subi    TEMP,0xE0
        andi    TEMP,0x7F
        st      Z+,TEMP                 ; New cyclic number
;        ldi     ZL,newblock
        ldd     TEMP,Z+2                ; load current active buffer
        st      Z+,TEMP                 ; addres of complete data block
        st      Z+,POINTER              ; Actual_size
        ldi     TEMP_CNT,(data^(data+data_size/2))
        eor     TEMP,TEMP_CNT
        st      Z, TEMP                 ; Write new active buffer
        clr     POINTER
;???        sbrs    STATUS,ACTIVE
;???      sbrc    STATUS,INDUCED
        sbr     STATUS,(1<<BLOCK_READY) ; For transmit
        sbrs    STATUS,MEASUREMENT	;
        cbr     STATUS,(1<<TEST)        ; Clear at end of incremental test
cn_out: cbr     STATUS,(1<<DATA_READY)
	ret


comm_level_setB:
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
	rcall	level_setB
        rjmp    yes

comm_level_setA:                        ; Discrimination threshold setting
        sbrc    STATUS,MEASUREMENT
        rjmp    busy
	rcall	level_setA
        rjmp    yes

level_setA:
        cbi     PORTB,CSA		; Select A, Start load new value
        lds     AL,levelA
	rcall	spi_levelbyte
        sbi     PORTB,CSA               ; update AD8400  channel A
;        cbi     PORTB,STROB
	ret
level_setB:
        cbi     PORTB,CSB		; Select B, Start load new value
        lds     AL,levelB
        rcall   spi_levelbyte
        sbi     PORTB,CSB               ; update AD8400  channel B
;        cbi     PORTB,STROB
	ret

spi_levelbyte:                          ; Upload 1 byte for AD8400, byte for transmit in AL
        sbi     PORTB,SCK			; A1
        cbi     PORTB,SCK
        sbi     PORTB,SCK			; A0
        cbi     PORTB,SCK
        sbi     SPCR,SPE
        out     SPDR,AL
        sbis    SPSR,SPIF                       ; Wait for transmission complete
        rjmp    PC-1
        cbi     SPCR,SPE                        ; Disable SPI
	ret

comm_exposition_set:                    ; Exposure setting
	sbrc    STATUS,MEASUREMENT	; last devices
        rjmp    busy
        rjmp    yes


constants:                              ; Constants request service
        ldi     ZL,low(apparatus*2)
        rjmp    PC+2
identification:                         ; Identification service
        ldi     ZL,low(identno*2)
        ldi     TEMP_CNT,5
        ldi     YL,low(tnumber)
        st      Y+,TEMP_CNT
        dec     TEMP_CNT
        st      Y+,TEMP_CNT
id0:    lpm     TEMP,Z+                 ; Copy from FLASH to the
        st      Y+,TEMP                 ; transmitter buffer
        dec     TEMP_CNT
        brne    id0
        st      Y+,YH
        rjmp    crc_gen

senddata:                              ; Packet with data block is formed
        lds     TEMP_CNT,actual_size
        inc     TEMP_CNT
        inc     TEMP_CNT
        ldi     YL,low(tnumber)
        st      Y+,TEMP_CNT             ; Packet length (actual_size+2)
        lds     TEMP,pakage  		; for transmitter
        st      Y+,TEMP                 ; Address byte
        dec     TEMP_CNT
        dec     TEMP_CNT
        st      Y+,TEMP_CNT             ; Data length (actual_size)
        lds     ZL,newblock
        rcall   rr_copy
        cbr     STATUS,(1<<BLOCK_READY)
        cbr     LINE_CSR,(1<<INDUCE_PASS)
        st      Y+,YH                   ; 0 instead CRC
        rjmp    crc_gen

require:                                ; Data block request service
        sbrs    STATUS,BLOCK_READY
        rjmp    nodat
        lds     ZL,newblock
        lds     TEMP_CNT,actual_size
        inc     TEMP_CNT
        ldi     YL,low(tnumber)
        st      Y+,TEMP_CNT             ; Packet length (actual_size+1)
        dec     TEMP_CNT
        st      Y+,TEMP_CNT             ; Data length (actual_size)
        rcall   rr_copy                 ; Data copy
        cbr     STATUS,(1<<BLOCK_READY)  ; Data will be empty after read
        cbr     LINE_CSR,(1<<INDUCE_PASS)
        st      Y+,YH                   ; 0 instead CRC
        rjmp    crc_gen

nodat:  ldi     TRANSMIT,NOD            ; Data not ready
        rjmp    signal

rr_copy:                                ; Copy block SRAM to SRAM
        ld      TEMP,Z+
        st      Y+,TEMP
        dec     TEMP_CNT
        brne    rr_copy
        ret

;***********************************************************************
;               SRAM organization
;***********************************************************************
.dseg
.org    0x60                    ; General parameters, 16 byte access via commands
parameters:
mod_status:                    	; Copy of STATUS register for external access
        .byte   1
levelA: .byte   1               ; Discrimination threshold cannel A
levelB: .byte   1               ; Discrimination threshold cannel B

.org    0x64
exposition:                     ; Microexposure duration, two bytes
        .byte   2
number: .byte   2               ; Microexposition series length, two bytes
                  		; 0 - infinite series
block_size:			; Data block size (up to 16 bytes)
        .byte   1
induct: .byte  	1               ; Inducing module address for counter

.org    0x6F
ee_crc: .byte   1               ; CRC of EEPROM parameter block

.org    0x70
adress: .byte   1               ; The module address
baud:   .byte   1               ; Exchange rate
twindow:.byte   1               ; Line timer bottom value for WINDOW generation
tswitch:.byte   1               ; Transmittance switch delay
rnumber:.byte   1               ; Receiver buffer
rbuffer:.byte   20
tnumber:.byte   1               ; Full length
tbuffer:.byte   20              ; Transmitter buffer

.org    0xA0                    ; Buffer for counts
data:   .byte   data_size       ; A0-DF

pakage: .byte   1               ; Cyclic packet number
newblock:                       ; Addres for complete data block (for transmit)
        .byte   1
actual_size:			; Size of complete data block
        .byte   1
active_buff:			; Addres of working buffer (for current series)
        .byte   1		; Pointer to first data byte in SRAM
cnt_data:                       ; current count from counter
	.byte   6
.exit
