;=================================================
;  *Copyright(C) 2023-2024 Advanced Micro Devices, Inc. All rights Reserved.
;=================================================

; Camera sensor I2C group control API
;
; [void] SensorGroupHold(void)
; [void] SensorGroupRelease(void)
;=================================================
.function SensorGroupHold
.endfunction

.function SensorGroupRelease
.endfunction
;=================================================
; Camera sensor exposure control API
;
; [uint32 setGain]  SensorConvertAGain(uint32 aGain, uint32 *aGainReal, uint32 *aGainSetting)
;=================================================
.function SensorConvertAGain
;R0 is the aGain (1000 base)
;retuen: R0 is for realAnalog Gain
; R1 is for reg setting
CALC_AGAIN_MAX:
    SUB R10, R0, $0x3C8C         ; R10 = R0 - 15.5 * 1000
    JLEZ R10, @CALC_AGAIN_MIN    ; if (aGain - 15.5 * 1000) <= 0 jump
    ;else
    MOVDW R0, $0x3C8C            ; else R0 = max again
    SHL R0, R0, $4               ; R0 = R0 * 16
    DIV R0, R0, $1000            ; R0 = R0 / 1000
    JEZ $0, @END

CALC_AGAIN_MIN:
    SUB R10, R0, $0x3E8           ; R10 = R0 - 1.0 * 1000
    JGZ R10, @CALC_AGAIN_x2       ; if (aGain - 1.0 * 1000) > 0 jump
    ;else
    MOVDW R0, $0x3E8              ; else R0 = min again
    SHL R0, R0, $4                ; R0 = R0 * 16
    DIV R0, R0, $1000             ; R0 = R0 / 1000
    JEZ $0, @END

CALC_AGAIN_x2:
    SUB R10, R0, $0x7D0            ; R10 = R0 - 2.0 * 1000
    JGZ R10, @CALC_AGAIN_x4        ; if (aGain - 2.0 * 1000) > 0 jump
    ;else calculate
    SHL R0, R0, $4                 ; R0 = R0 * 16
    DIV R0, R0, $1000              ; R0 = R0 / 1000
    AND R0, R0, $0xFF              ; R0 = R0 >> 6 & 0xFF -> Q4.4
    JEZ $0, @END

CALC_AGAIN_x4:
    SUB R10, R0, $0xFA0           ; R10 = R0 - 4.0 * 1000
    JGZ R10, @CALC_AGAIN_x8        ; if (aGain - 4.0 * 1000) > 0 jump
    ;else calculate
    SHL R0, R0, $4                 ; R0 = R0 * 16
    DIV R0, R0, $1000              ; R0 = R0 / 1000
    AND R0, R0, $0xFE              ; R0 = R0 >> 6 & 0xFE -> Q4.3
    JEZ $0, @END

CALC_AGAIN_x8:
    SUB R10, R0, $0x1F40           ; R10 = R0 - 8.0 * 1000
    JGZ R10, @CALC_AGAIN_x15p5     ; if (aGain - 8000) > 0 jump
    ;else calculate
    SHL R0, R0, $4                 ; R0 = R0 * 16
    DIV R0, R0, $1000              ; R0 = R0 / 1000
    AND R0, R0, $0xFC              ; R0 = R0 >> 6 & 0x0FC0 -> Q4.2
    JEZ $0, @END

CALC_AGAIN_x15p5:
    SHL R0, R0, $4                 ; R0 = R0 * 16
    DIV R0, R0, $1000              ; R0 = R0 / 1000
    AND R0, R0, $0xF8              ; R0 = R0 >> 6 & 0xF8 -> Q4.1

END:
    MOVDW R1, R0                   ; R1 = R0 : again setting
    MUL R0, R0, $1000              ; R0 = R0 * 1000
    SHR R0, R0, $4                 ; R0 = R0 * 16
.endfunction

;=================================================
; Camera sensor exposure control API
;
; [uint32 setGain]  SensorSetAGain(uint32 aGainSetting)
;=================================================
;R0 is the aGainSetting
.function SensorSetAGain
AND R10,R0,$0xff			;R11 = R0 & 0xff
WI2C $0xfd, $0x01, $1 ;Switch to page 1
WI2C $0x24, R10, $1
WI2C $0x01, $0x01, $1 ;Trigger update
.endfunction

;=================================================
; Camera sensor exposure control API
;[uint32 getAGain] SensorGetAGain(uint32 realGain)
;=================================================
.function SensorGetAGain
;R0 is the realGain
;Gain = (1000 * regGain) / 16;
WI2C $0xfd, $0x01, $1 ;Switch to page 1
RI2C R8, $0x24, $1   ;
MUL R10, R8, $1000    ;
DIV R0, R10, $16      ;
.endfunction
;=================================================
; Camera sensor exposure control API
;
; [uint32 setGain]  SensorSetDGain(uint32 dGain)
;=================================================

.function SensorSetDGain

.endfunction

;=================================================
; Camera sensor exposure control API
;
; [uint32 getGain]  SensorGetDGain(uint32 dGainSetting)
;=================================================

.function SensorGetDGain

.endfunction

;=================================================
; Camera sensor exposure control API
;
; [uint32 setItime] SensorSetItime(uint32 iTimeSetting,
;                                  uint32 durationSetting)
;=================================================
.function SensorSetItime
;R0 is the iTimeSetting,exposure line
;R1 is the durationSetting,vts,frame_length_line
;R6: first_frame_length_lines
;R31: save the current_frame_length_lines
;calculate******************
SHR R9, R1, $8             ;R1 = frame_length_line
AND R9, R9, $0xff          ;R9 = frame_length_line_high = (frame_length_line >> 8) & 0xff
AND R10, R1, $0xff         ;R10 = frame_length_line_l = frame_length_line & 0xff
SHL R10, R10, $8
OR  R9,  R9,  R10          ;R9 = (R10 << 8) | R9. final, R9 is frame_length_line/vts setting

SHR R15, R0, $8            ;R0  = line_count
AND R15, R15, $0xff        ;R15 = line_count_h = (line_count >> 8) & 0xff
AND R16, R0, $0xff         ;R16 = line_count_l = line_count & 0xff
SHL R16, R16, $8           ; R16 = R16 << 8
OR  R15, R15, R16          ; R15 = R16 | R15. final, R15 is exposure line reg setting
;calculate******************

JNZ R31 @FL_UPDATED			;if current_frame_length_lines !=0, jump to FL_UPDATED
MOVDW R31, R6               ;R31 = R6;

FL_UPDATED:
SUB R30, R1, R31			;R30 = R1 - R31 = durationSetting(frame_length_line) - current_frame_length_lines
MOVDW R31, R1				;R31 = R1

WI2C $0xfd, $0x01, $1
JLZ R30 @LINE_COUNT_FIRST  ;if frame_length_line_set < current_frame_length_lines, jump to LINE_COUNT_FIRST
	;need add vblanking here WI2C $0x380e, R9, $2
	WI2C $0x03, R15, $2
	JGZ R6 @END            ; if R6 >0 , jump to end

LINE_COUNT_FIRST:
	WI2C $0x03, R15, $2
	;need add vblanking here, WI2C $0x380e, R9, $2

END:
WI2C $0x01, $0x01, $1 ;Trigger update
;Note, the setted new Gain and new Itime must be return in R0 and R1
;Here, we just return the input value.
MOVDW R0, R0
.endfunction

;=================================================
; Camera sensor exposure control API
;
;=================================================
.function SensorGetItime
;R0 is the newItime
;R1: t_line
WI2C $0xfd, $0x01, $1
RI2C R9, $0x03, $1   ;line_count_h
RI2C R10, $0x04, $1  ;line_count_l
SHL R12, R9, $8      ;
OR R11, R10, R12     ;
MUL R0, R11, R1      ;

.endfunction

;=============================================================================
;                    For HDR High Analog Gain
;
;    [uint32 setGain]  SensorSetHdrHighAGain(uint32 aGainSetting)
;=============================================================================
.function SensorSetHdrHighAGain
CALL @SensorSetAGain
.endfunction

;=============================================================================
;                    For HDR Low Analog Gain
;
;    [uint32 setGain]  SensorSetHdrLowAGain(uint32 aGainSetting)
;=============================================================================
.function SensorSetHdrLowAGain
AND R10,R0,$0xff			;R11 = R0 & 0xff
WI2C $0xfd, $0x01, $1 ;Switch to page 1
WI2C $0x3b, R10, $1
WI2C $0x01, $0x01, $1 ;Trigger update
.endfunction

;=============================================================================
;                    For HDR High Digital Gain
;
;    [uint32 setGain]  SensorSetHdrHighDGain(uint32 dGain)
;=============================================================================
.function SensorSetHdrHighDGain
.endfunction

;=============================================================================
;                    For HDR Low Digital Gain
;
;    [uint32 setGain]  SensorSetHdrLowDGain(uint32 dGain)
;=============================================================================
.function SensorSetHdrLowDGain
.endfunction

;=============================================================================
;                    For HDR High exposure control API
;
;    [uint32 setItime] SensorSetHdrHighItime(uint32 iTimeSetting)
;=============================================================================
.function SensorSetHdrHighItime
SHR R15, R0, $8            ;R0  = line_count
AND R15, R15, $0xff        ;R15 = line_count_h = (line_count >> 8) & 0xff
AND R16, R0, $0xff         ;R16 = line_count_l = line_count & 0xff
SHL R16, R16, $8           ; R16 = R16 << 8
OR  R15, R15, R16          ; R15 = R16 | R15. final, R15 is exposure line reg setting

WI2C $0xfd, $0x01, $1
WI2C $0x03, R15, $2
WI2C $0x01, $0x01, $1 ;Trigger update
.endfunction

;=================================================
; Camera sensor exposure control API
;
; [uint32 setItime] SensorSetHdrLowItime(uint32 iTimeSetting)
;=================================================
.function SensorSetHdrLowItime
SHR R15, R0, $8            ;R0  = line_count
AND R15, R15, $0xff        ;R15 = line_count_h = (line_count >> 8) & 0xff
AND R16, R0, $0xff         ;R16 = line_count_l = line_count & 0xff
SHL R16, R16, $8           ; R16 = R16 << 8
OR  R15, R15, R16          ; R15 = R16 | R15. final, R15 is exposure line reg setting

WI2C $0xfd, $0x01, $1
WI2C $0x4e, R15, $2
WI2C $0x01, $0x01, $1 ;Trigger update
.endfunction

.function SensorStreamOn
WI2C $0xfd, $0x01, $1
WI2C $0x33, $0x03, $1
WI2C $0x01, $0x02, $1
WI2C $0xfd, $0x00, $1
WI2C $0x20, $0x1f, $1
WI2C $0xfd, $0x01, $1
.endfunction

.function SensorStreamOff
WI2C $0xfd, $0x00, $1
WI2C $0x20, $0x5b, $1
WI2C $0xfd, $0x01, $1
WI2C $0x33, $0x02, $1
WI2C $0x01, $0x02, $1
.endfunction

;=================================================
; Camera sensor exposure control API
;
; SensorSetDuration(uint32 durationSetting)
;=================================================
.function SensorSetDuration
.endfunction

;================================================= 
; Camera sensor exposure control API ; 
; SensorGetDuration(uint32 pdurationSetting) 
;================================================= 
.function SensorGetDuration
;R0 is the durationSetting vts
WI2C $0xfd, $0x01, $1
RI2C R9, $0x35, $1   ;vts_h
RI2C R10, $0x36, $1  ;vts_l
SHL R11, R9, $8        ;R11 = R9(vts_h) << 8
OR R0, R11, R10       ;R0 = R11 | R10
.endfunction
