;Copyright (C) 2022-2024 Advanced Micro Devices, Inc. All rights reserved.
;=================================================
; Camera sensor I2C group control API
;
; [void] SensorGroupHold(void)
; [void] SensorGroupRelease(void)
;=================================================
.function SensorGroupHold
;HM1092 does not support
.endfunction

.function SensorGroupRelease
;HM1092 does not support, this is for update command
WI2C $0x0104, $0x01, $1
WI2C $0x0104, $0x00, $1
.endfunction

;=================================================
; Camera sensor exposure control API
;
; [uint32 setGain]  SensorConvertAGain(uint32 aGain, uint32 *aGainReal, uint32 *aGainSetting)
;=================================================
.function SensorConvertAGain
;R0 is the aGain
;gain_reg = 256 * aGain / 1000;

SUB R9, R0, $1000
JGEZ R9 @aGain1x
JLZ R9 @Less1

aGain1x:
SUB R9, R0, $2000
JGEZ R9 @aGain2x
    MOVB R10, $0
    MOVB R11, $1
JLZ R9 @CalcLow

aGain2x:
SUB R9, R0, $4000
JGEZ R9 @aGain4x
    MOVB R10, $1
    MOVB R11, $2
JLZ R9 @CalcLow

aGain4x:
SUB R9, R0, $8000
JGEZ R9 @aGain8x
    MOVB R10, $2
    MOVB R11, $4
JLZ R9 @CalcLow

aGain8x:
SUB R9, R0, $16000
JGEZ R9 @aGain16x
    MOVB R10, $3
    MOVB R11, $8
JLZ R9 @CalcLow

aGain16x:
    MOVB R10, $4
    MOVB R11, $16
;Calculate low 4 bits
;1000*2^high*(1+low/16)=R0
;1000*2^R10*(1+low/16)=R0
;1000*R11*(1+low/16)=R0
;1+ 1ow/16 = R0/R11/1000
;R11*1000 +low/16*1000*R11 = R0
;low = (R0-R11*1000)*16/R11/1000
CalcLow:
MUL R12, R11, $1000
SUB R12, R0, R12
MUL R12, R12, $16
DIV R12, R12, R11
DIV R13, R12, $1000
;R10:high, R13:low
SHL R14, R10, $4            ;R14 = R10 << 4
OR  R14, R14, R13           ;R14 = R10 << 4 | R13
                            
MOVB R1, R14

;calculate real gain
;2^high*(1+low/16)*1000= real_gain_*1000_R0
;R11*(1+R13/16)*1000=R0
;R11*(16 + R13)*1000= R0*16
ADD R15, R13, $16
MUL R15, R15, R11
MUL R15, R15, $1000
DIV R15, R15, $16
MOVW R0, R15
JNZ $1 @End                 ; Jump to End

Less1:                      ; Not likely to happen. If does, write 1x
MOVB R1, $0
MOVW R0, $1000

End:
.endfunction

;=================================================
; Camera sensor exposure control API
;
; [uint32 setGain]  SensorSetAGain(uint32 aGainSetting)
;=================================================
.function SensorSetAGain
;R0 is the aGainSetting

WI2C $0x0205, R0, $1

.endfunction

;=================================================
; Camera sensor exposure control API
;
;=================================================
.function SensorGetAGain
;R0 is the realGain
;Gain = (1000 * regGain) / 256;
RI2C R8, $0x0205, $1   ;
AND R9, R8, $0x0f
SHR R10, R8, $4

SUB R11, R10, $1
JGZ R11 @aGain2x
    MOVDW R12, $1
JLZ R11 @Calculate

aGain2x:
SUB R11, R10, $2
JGZ R11 @aGain4x
    MOVDW R12, $2
JLZ R11 @Calculate

aGain4x:
SUB R11, R10, $4
JGZ R11 @aGain8x
    MOVDW R12, $4
JLZ R11 @Calculate

aGain8x:
SUB R11, R10, $8
JGZ R11 @aGain16x
    MOVDW R12, $8
JLZ R11 @Calculate

aGain16x:
    MOVDW R12, $16

Calculate:
MUL R9, R9, $1000
DIV R9, R9, $16
ADD R9, R9, $1000
MUL R9, R9, R12

MOVDW R0, R9

.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

JNZ R31 @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

SHR R9, R1, $8             ;R1 = frame_length_line
AND R9, R9, $0xff          ;R9 = frame_length_line0 = (frame_length_line >> 8) & 0xff
AND R10, R1, $0xff         ;R10 = frame_length_line1 = frame_length_line & 0xff
SHR R11, R0, $8            ;R0  = line_count
AND R11, R11, $0xff        ;R11 = line_count1 = (line_count >> 8) & 0xff
AND R12, R0, $0xff         ;R12 = line_count2 = line_count & 0xff

JLZ R30 @LINE_COUNT_FIRST  ;durationSetting is smaller than current_frame_length_lines
;SHL R10, R10, $8
;OR  R9,  R9,  R10          ; R9 = (R10 << 8) | R9
WI2C $0x0340, R9, $1        ; The I2C of HM1092 doesn't support burst mode.
                            ; So the value is write and read in 1 byte length.
WI2C $0x0341, R10, $1

;SHL R12, R12, $8           ; R12 = R12 << 8
;OR  R11, R12, R11          ; R11 = R12 | R11
WI2C $0x0202, R11, $1
WI2C $0x0203, R12, $1
JGZ $1 @END                ;Jump to end

LINE_COUNT_FIRST:
;SHL R12, R12, $8           ; R12 = R12 << 8
;OR  R11, R12, R11          ; R11 = R12 | R11
WI2C $0x0202, R11, $1
WI2C $0x0203, R12, $1
;SHL R10, R10, $8
;OR  R9,  R9,  R10          ; R9 = (R10 << 8) | R9
WI2C $0x0340, R9, $1
WI2C $0x0341, R10, $1

END:
;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

RI2C R8, $0x0202, $1   ;
RI2C R9, $0x0203, $1   ;
SHL R10, R8, $8        ;
OR R11, R10, R9       ;
MUL R0, R11, R1        ;

.endfunction

;===================================================
; Camera sensor Digital Gain control API
; Empty for now
;===================================================
.function SensorSetDGain
;DGAIN = reg 0x020E[1:0] +reg0x20f[7:0]/4/64
;1000 + reg0x20f[7:0]/4/64*1000 = R0 (uint:*1000)
;reg0x20f[7:0] = （R0 - 1000）*4*64/1000
SUB R6, R0, $1000
MUL R6, R6, $256
DIV R6, R6, $1000
WI2C $0x020E, $1, $1
WI2C $0x020F, R6, $1
.endfunction

;===================================================
; Camera sensor Digital Gain control API
; Empty for now
;===================================================
.function SensorGetDGain
.endfunction
