Trying to get the DSi cameras working
Trying to get the DSi cameras working
I want to hardware-test the camera functionality before implementing it in melonDS (well, I did, but so far my implementation is a trainwreck).
but, that's the thing, I can't get cameras to work on hardware, no matter what I do. I tried following the init procedure on GBAtek, I tried copying that found in some open-source MT9V113 driver, I even tried going from a disassembly of the DSi camera app code and some logs from melonDS, but none of it did the trick.
basically, the camera seems to initialize itself in some fucked-up status where it will never send any data, and if I put it in standby mode, I can never turn it back on again -- 'standard' camera wakeup code just hangs forever.
furthermore, some registers seem to entirely ignore writes at that point. setting bit9 in 001A (to enable data transfers) does not work, and I can't seem to change that register at all. also, MIPI registers are in some weird contradictory state (3402 reports MIPI is in standby, even though 3400 doesn't enable standby).
I even went and looked for code using the DSi cameras. found this, but they seem to have run into the same issue as me.
at this point, I threw everything I could at this wall, with zero effect whatsoever. so, has anybody ever managed to get the DSi cameras working? GBAtek kinda implies nocash did get them working, so I'd be curious.
but, that's the thing, I can't get cameras to work on hardware, no matter what I do. I tried following the init procedure on GBAtek, I tried copying that found in some open-source MT9V113 driver, I even tried going from a disassembly of the DSi camera app code and some logs from melonDS, but none of it did the trick.
basically, the camera seems to initialize itself in some fucked-up status where it will never send any data, and if I put it in standby mode, I can never turn it back on again -- 'standard' camera wakeup code just hangs forever.
furthermore, some registers seem to entirely ignore writes at that point. setting bit9 in 001A (to enable data transfers) does not work, and I can't seem to change that register at all. also, MIPI registers are in some weird contradictory state (3402 reports MIPI is in standby, even though 3400 doesn't enable standby).
I even went and looked for code using the DSi cameras. found this, but they seem to have run into the same issue as me.
at this point, I threw everything I could at this wall, with zero effect whatsoever. so, has anybody ever managed to get the DSi cameras working? GBAtek kinda implies nocash did get them working, so I'd be curious.
Re: Trying to get the DSi cameras working
Below is messy, but tested and working on hardware...
Code: Select all
;------------------
dsi_cam_init: ;init camera (and display the camera bitmap)...
push lr
bl cls
;- - -
REGBASE_CAM equ 4004200h
REG_CAM_MCNT equ 000h
REG_CAM_CNT equ 002h
REG_CAM_DAT equ 004h
REG_CAM_SOFS equ 010h
REG_CAM_EOFS equ 014h
;- - -
@@yuv_mode equ 0;1 ;YUV mode (with SLOW manual YUV-to-RGB conversion)
bl ini_engine_b_32k_bitmap
mov r4,4000000h ;\
mov r0,84h ; map VramC to 6200000h
strb r0,[r4,242h] ;/
mov r0,0 ;\
mov r1,0100h ;rot/scal ;
ldr r4,=4001000h ;
strh r1,[r4,20h] ;
strh r0,[r4,22h] ; rot/scale
strh r0,[r4,24h] ;
strh r1,[r4,26h] ;
strh r0,[r4,28h] ;
strh r0,[r4,2ah] ;
strh r0,[r4,2ch] ;
strh r0,[r4,2eh] ;/
ldr r1,=06200000h
mov r0,0
mov r2,256*256 ;/2
@@lll:
orr r0,8000h
strh r0,[r1],2
add r0,1
subs r2,1
bne @@lll
bl arm9_show_cam_irq
bl arm9_cam_int_clk_on ;-cam interface clk on (blah/anyways)
bl arm9_cam_mcnt_zero ;-cam mcnt
bl arm9_cam_ext_clk_on ;-cam clk on (required for I2C here)
bl arm9_cam_mcnt_22h ;-cam mcnt
;bl arm9_cam_ext_clk_off ;-cam clk off (blah)
ldr r1,=REGBASE_CAM
ldrh r0,[r1,REG_CAM_CNT]
bic r0,8000h // strh r0,[r1,REG_CAM_CNT] ;AND NOT 8000h ;CAM_CNT, disable (allow changing params)
orr r0,0020h // strh r0,[r1,REG_CAM_CNT] ;OR 0020h
bic r0,20h ;?
bic r0,0300h ;PICMODE?
orr r0,0200h // strh r0,[r1,REG_CAM_CNT] ;AND NOT 0300h, OR 0200h (0..3 no effect)
orr r0,0400h // strh r0,[r1,REG_CAM_CNT] ;OR 0400h ;whatever (works without) (no effect)
orr r0,0800h // strh r0,[r1,REG_CAM_CNT] ;OR 0800h ;IRQ enable
;bl arm9_cam_ext_clk_on ;-cam clk on (blah)
ldr r10,=aptina_code_list_init ;\
mov r11,7ah ;device1 ; init BOTH cameras
mov r12,78h ;device2 ;
bl send_aptina_code_list ;/
;bl arm9_cam_ext_clk_off ;\cam clk off-then-on (blah)
;bl arm9_cam_ext_clk_on ;/
bl arm9_show_cam_irq
;Now do more camera I2C stuff (LED on, and init ONE of the cameras, till E0 04 98)
ldr r10,=aptina_code_list_activate ;\
mov r11,7ah ;device1 ; activate ONE camera
mov r12,r11 ;same ; (7Ah=SelfPortrait, 78h=Landscape)
bl send_aptina_code_list ;/
bl arm9_show_cam_irq
ldr r1,=REGBASE_CAM
ldr r0,=01ff0080h
ldr r0,=008001ffh ;<-- full scanlines (rapid vertical roll)
ldr r0,=006001ffh ;<-- full scanlines (slow vertical roll)
ldr r0,=00c00080h ;<-- half scanlines (left half repeated 2x, plus black lines)
ldr r0,=00c00100h ;<-- full scanlines (normal picture)
ldr r0,=00c001ffh ;<-- full scanlines (normal picture)
str r0,[r1,REG_CAM_EOFS]
ldr r1,=REGBASE_CAM
ldrh r0,[r1,REG_CAM_CNT]
orr r0,2000h // strh r0,[r1,REG_CAM_CNT] ;OR 2000h ;whatever (works without)
.if @@yuv_mode
bic r0,2000h ;<-- cause valid picture (but with white-green-snow instead of correct RGB colors)
.endif
orr r0,4000h ;trimming enable
bic r0,4000h
bic r0,000fh
orr r0,0003h // strh r0,[r1,REG_CAM_CNT] ;AND NOT 000Fh, OR 0003h ;DMA.BLK
;3=normal
;1=draw2lines, insert2blacklines?
;7=skip each 2nd line (or draw4lines, skip4lines?)
orr r0,0020h // strh r0,[r1,REG_CAM_CNT] ;OR 0020h ;was already so though (or is it W?)
bic r0,20h ;?
orr r0,8000h // strh r0,[r1,REG_CAM_CNT] ;OR 8000h ;<--- kick (now AE23h)
;Read r0 = ([REGBASE_CAM+REG_CAM_CNT] AND 000Fh)+0001h
bl arm9_show_cam_irq
ldr r1,=REGBASE_CAM
ldrh r0,[r1,REG_CAM_CNT]
bl wrhex16bit
bl wrspc
ldrh r0,[r1,REG_CAM_CNT]
bl wrhex16bit
.if 0
bl wrspc
ldr r0,[r1,REG_CAM_DAT]
bl wrhex32bit
bl wrspc
ldr r0,[r1,REG_CAM_DAT]
bl wrhex32bit
.endif
bl wrcrlf
bl wrspc
ldr r0,[r1,REG_CAM_SOFS] ;trim start
bl wrhex32bit
bl wrspc
ldr r0,[r1,REG_CAM_EOFS] ;trim end
bl wrhex32bit
bl wrcrlf
ldr r1,=4004100h
ldr r0,[r1,38h] ;NDMA1CNT
bl wrhex32bit
bl wrcrlf
;XXX ---> Now do NDMA1
bl flushkey
@@keylop:
.if 0;1 ;try manual read...
ldr r4,=REGBASE_CAM
.if 01
ldrh r0,[r4,REG_CAM_CNT]
orr r0,20h
strh r0,[r4,REG_CAM_CNT]
ldr r2,[r4,REG_CAM_MCNT]
mov r0,r2
bl wrhex32bit
bl wrspc
@@wx:
ldr r0,[r4,REG_CAM_MCNT]
cmp r0,r2
beq @@wx
bl wrhex32bit
bl wrspc
bl wrhex32bit
bl wrcrlf
.endif
mov r1,6200000h ;dst
mov r3,192/4
@@xfer_ylop:
@@wait_blk_lop: ;\
ldrh r0,[r4,REG_CAM_CNT] ; wait
tst r0,10h ;
beq @@wait_blk_lop ;/
mov r2,200h ;\
@@xfer_blk_lop: ;
ldr r0,[r4,REG_CAM_DAT] ; read
str r0,[r1],4 ;
subs r2,1 ;
bne @@xfer_blk_lop ;/
.if 0
ldrh r0,[r4,REG_CAM_CNT] ;PICMODE?
bic r0,300h
;orr r0,100h+200h
;bic r0,400h ;?
strh r0,[r4,REG_CAM_CNT]
ldrh r0,[r4,REG_CAM_CNT]
; orr r0,20h ;<-- forces delay, plus UPPER block again
;bic r0,8000h
;strh r0,[r4,REG_CAM_CNT]
;mov r2,10000h ;<-- gets one 2nd block after this HUGE delay!
;@@wwyy:
;subs r2,1
;bne @@wwyy
.endif
subs r3,1
bne @@xfer_ylop
ldr r2,[r4,REG_CAM_MCNT]
mov r0,r2
bl wrhex32bit
bl wrspc
bl wrhex32bit
bl wrcrlf
@@w:
ldr r0,[r4,REG_CAM_MCNT]
cmp r0,r2
;beq @@w
bl wrhex32bit
bl wrspc
bl wrhex32bit
bl wrcrlf
.else
ldr r1,=4004100h
;ldr r0,=80050000h // str r0,[r1,0h] ;NDMACNT ;DSi7
ldr r0,=80060000h // str r0,[r1,0h] ;NDMACNT ;DSi9
mov r0, 0 // str r0,[r1,38h] ;NDMA1CNT
ldr r0,=REGBASE_CAM+REG_CAM_DAT // str r0,[r1,20h] ;NDMA1SAD <-- CAMERA
ldr r0,=06200000h // str r0,[r1,24h] ;NDMA1DAD <-- VRAM
.if @@yuv_mode ;or
ldr r0,=02800000h // str r0,[r1,24h] ;NDMA1DAD <-- RAM
.endif
mov r0, 00006000h // str r0,[r1,28h] ;NDMA1TCNT
mov r0, 00000200h // str r0,[r1,2Ch] ;NDMA1WCNT ;DMA.BLK
mov r0, 00000002h // str r0,[r1,30h] ;NDMA1BCNT
mov r0, 00000000h // str r0,[r1,34h] ;NDMA1FDATA
ldr r0,=8B044000h // str r0,[r1,38h] ;NDMA1CNT ;bit16-19:DMA.BLK
@@wait_dma:
ldr r1,=4004100h
ldr r0,[r1,38h] ;NDMA1CNT
tst r0,80000000h
bne @@wait_dma
.if @@yuv_mode
push r0-r12
mov r4,2800000h
mov r5,6200000h
mov r6,256*192
@@copy_to_vram_lop:
ldr r0,[r4],4
mov r0,r0,lsr 0 ;Y1
mov r1,r0,lsr 16 ;Y2
mov r2,r0,lsr 8 ;Cb
mov r3,r0,lsr 24 ;Cr
and r0,0ffh ;Y1
and r1,0ffh ;Y2
and r2,0ffh ;Cb
and r3,0ffh ;Cr
sub r2,80h ;Cb
sub r3,80h ;Cr
ldr r8,=1772*100h/1000 ;(for B)
ldr r9,=1402*100h/1000 ;(for R)
mov r10,0344*100h/1000 ;(for G-B)
mov r11,0714*100h/1000 ;(for G-R)
mul r8,r8,r3 ;(for B)
mul r9,r9,r2 ;(for R)
mul r10,r10,r3 ;(for G-B)
mul r11,r11,r2 ;(for G-R)
bl @@emit
mov r0,r1 ;Y2
bl @@emit
; R = 1.000 x Y + 1.402 x (V - 128)
; G = 1.000 x Y - 0.344 x (U - 128) - 0.714 x (V - 128)
; B = 1.000 x Y + 1.772 x (U - 128)
mov r0,r0,lsr 3
subs r6,1+1
bne @@copy_to_vram_lop
b @@skip
@@emit:
add r2,r0,r9,asr 8 ;B
add r3,r0,r8,asr 8 ;R
sub r7,r0,r10,asr 8 ;G-B
sub r7,r7,r11,asr 8 ;G-R
cmp r2,0 // movlt r2,0
cmp r3,0 // movlt r3,0
cmp r7,0 // movlt r7,0
cmp r2,100h // movge r2,0ffh
cmp r3,100h // movge r3,0ffh
cmp r7,100h // movge r7,0ffh
mov r2,r2,lsr 3
mov r3,r3,lsr 3
mov r7,r7,lsr 3
mov r0,8000h ;Alpha
orr r0,r0,r2,lsl 10 ;B
orr r0,r0,r7,lsl 5 ;G
orr r0,r0,r3,lsl 0 ;R
strh r0,[r5],2
bx lr
@@skip:
pop r0-r12
.endif ;(@@yuv_mode)
.if 1
mov r0,10
ldr r4,=scryloc
strb r0,[r4]
ldr r1,=02800000h
ldr r0,[r1]
bl wrhex32bit
bl wrcrlf
ldr r1,=02800200h
ldr r0,[r1]
bl wrhex32bit
bl wrcrlf
ldr r1,=02800400h
ldr r0,[r1]
bl wrhex32bit
bl wrcrlf
ldr r1,=02800600h
ldr r0,[r1]
bl wrhex32bit
bl wrcrlf
bl wrcrlf
.endif
.endif
bl getkey
beq @@keylop
ldr r1,=REGBASE_CAM
ldrh r0,[r1,REG_CAM_CNT]
bl wrhex16bit
bl wrspc
ldrh r0,[r1,REG_CAM_CNT]
bl wrhex16bit
.if 0
bl wrspc
ldr r0,[r1,REG_CAM_DAT]
bl wrhex32bit
bl wrspc
ldr r0,[r1,REG_CAM_DAT]
bl wrhex32bit
.endif
bl wrcrlf
ldr r1,=4004100h
ldr r0,[r1,38h] ;NDMA1CNT
bl wrhex32bit
bl wrcrlf
bl arm9_show_cam_irq
bl waitkey
pop pc
;---
arm9_cam_mcnt_zero:
ldr r1,=REGBASE_CAM ;CAM_MCNT, Camera Module Control
mov r0,0000h ;CLR all
strh r0,[r1,REG_CAM_MCNT]
mov r0,1eh
b arm9_camera_delay
;---
arm9_cam_mcnt_22h:
ldr r1,=REGBASE_CAM ;CAM_MCNT, Camera Module Control
mov r0,0022h ;SET bit1,bit5
strh r0,[r1,REG_CAM_MCNT]
mov r0,2000h ;HUGE DELAY here
b arm9_camera_delay
;---
arm9_cam_int_clk_on:
ldr r1,=4004004h
ldrh r0,[r1]
orr r0,0004h ;SET bit2 (usually enabled anyways)
strh r0,[r1]
mov r0,1eh
b arm9_camera_delay
;---
arm9_cam_ext_clk_on:
ldr r1,=4004004h
ldrh r0,[r1]
orr r0,0100h ;SET bit8 (needed for camera access)
strh r0,[r1]
mov r0,1eh
b arm9_camera_delay
;---
arm9_cam_ext_clk_off:
ldr r1,=4004004h
ldrh r0,[r1]
bic r0,0100h ;CLR bit8
strh r0,[r1]
mov r0,1eh
b arm9_camera_delay
;---
arm9_camera_delay:
;XXX should adjust to ARM9-CPU-SPEED
;mov r0,r0,lsl 1 ;???
;mov r0,r0,lsl 1 ;???
@@lop:
subs r0,1
bne @@lop
bx lr
;---
arm9_show_cam_irq:
push lr
mov r1,4000000h
ldr r0,[r1,214h] ;IF
and r0,1 shl 25 ;CAM
bl wrhex32bit
bl wrcrlf
pop pc
;------------------
send_aptina_code_list: ;in: r10=src, r11=device1, r12=device2
push r0-r12,lr
bl switch_to_other_cpu ;-be ARM7
@@list_lop: ;-list lop...
push r11
ldrh r4,[r10],2 ;CMD (token) ;\
ldrh r5,[r10],2 ;IDX (index) ;
ldrh r6,[r10],2 ;DTA (data) ; obtain list entry
tst r4,AptDiff ;
moveq r7,r6 ;DTA2=DTA ;
ldrneh r7,[r10],2 ;DTA2 (data2) ;/
mov r11,r11 ;device1 ;\device lop...
@@device_lop: ;/
@@wait_lop: ;\
bl @@read_old_data ;
bl @@check_wait_condition ; data core
bne @@wait_lop ;
bl @@manipulate_data ;
bl @@write_new_data ;/
.if 0
cmp r11,7ah
bne @@no_read
and r0,r4,0ffh ;CMD.lsbs
cmp r0,AptRd
bne @@no_read
mov r0,r8
bl wrhex16bit
bl wrcrlf
bl waitkey
@@no_read:
.endif
cmp r11,r12 ;device2 ;\
movne r11,r12 ;device2 ; lop next device
movne r6,r7 ;DTA=DTA2 ; (unless already device2)
bne @@device_lop ;/
pop r11
ldrsh r0,[r10] ;CMD (token) ;\
cmp r0,-1 ; lop next list entry
bne @@list_lop ;/
bl switch_to_other_cpu ;-back to ARM9 side
pop r0-r12,pc
;--- --- ---
@@manipulate_data:
and r0,r4,0ffh ;CMD.lsbs
cmp r0,AptSet ;\SET (or)
orreq r8,r6 ;/
cmp r0,AptClr ;\CLR (and not)
biceq r8,r6 ;/
bx lr
;---
@@check_wait_condition:
and r0,r4,0ffh ;CMD.lsbs
cmp r0,AptWaitSet ;\
beq @@wait_set ;/
cmp r0,AptWaitClr ;\
beq @@wait_clr ;/
cmp r0,AptWaitOther ;\
beq @@wait_other ;/
@@do_not_wait:
cmp r0,r0 ;EQ=no wait
bx lr
@@do_wait:
cmp sp,0 ;NE=wait
bx lr
@@wait_set:
tst r8,r6
bne @@do_not_wait ;ready (set)
b @@do_wait
@@wait_clr:
tst r8,r6
beq @@do_not_wait ;ready (cleared)
b @@do_wait
@@wait_other:
cmp r8,r6
bne @@do_not_wait ;ready (other)
b @@do_wait
;---
@@read_old_data:
mov r8,r6 ;DTA ;\
and r0,r4,0ffh ;CMD.lsbs ; exit if raw-write (and return DTA from list)
cmp r0,AptWr ;
bxeq lr ;/
push lr
bl @@send_mcu_idx ;-send MCU index (if any)
mov r1,082h // orr r0,r11,0 // bl i2c_send_data ;device + START ;\
mov r1,080h // mov r0,r9,lsr 8 // bl i2c_send_data ;index.msb (IDX/0990h) ;
mov r1,081h // mov r0,r9 // bl i2c_send_data ;index.lsb + STOP ;/
mov r1,082h // orr r0,r11,1 // bl i2c_send_data ;device+rd + START ;\
mov r1,0b0h // bl i2c_get_data // mov r8,r0,lsl 8 ;index.msb (DTA) ;
mov r1,0a1h // bl i2c_get_data // orr r8,r0 ;index.lsb + STOP ;/
pop pc
;---
@@write_new_data:
and r0,r4,0ffh ;CMD.lsbs ;\
cmp r0,AptWr ;
cmpne r0,AptSet ; exit if not write (or set/clr)
cmpne r0,AptClr ;
bxne lr ;/
push lr
bl @@send_mcu_idx ;-send MCU index (if any)
mov r1,082h // orr r0,r11,0 // bl i2c_send_data ;device + START ;\
mov r1,080h // mov r0,r9,lsr 8 // bl i2c_send_data ;index.msb (IDX/0990h) ;
mov r1,080h // mov r0,r9 // bl i2c_send_data ;index.lsb ;
mov r1,080h // mov r0,r8,lsr 8 // bl i2c_send_data ;data.msb (DTA) ;
mov r1,081h // mov r0,r8 // bl i2c_send_data ;data.lsb + STOP ;/
pop pc
;---
@@send_mcu_idx:
mov r9,r5 ;IDX ;\
tst r4,AptMcu ;CMD ; exit if non-mcu (and return r9=IDX)
bxeq lr ;/
push lr
mov r1,082h // orr r0,r11,0 // bl i2c_send_data ;device + START ;\
mov r1,080h // mov r0,09h // bl i2c_send_data ;index.msb (098Ch) ;
mov r1,080h // mov r0,8ch // bl i2c_send_data ;index.lsb ;
mov r1,080h // mov r0,r5,lsr 8 // bl i2c_send_data ;data.msb (IDX) ;
mov r1,081h // mov r0,r5 // bl i2c_send_data ;data.lsb + STOP ;/
mov r9,0990h ;-return r9=0990h (instead of IDX)
pop pc
;------------------
.pool
;------------------
AptWr equ 00h ;MOV
AptSet equ 01h ;OR
AptClr equ 02h ;AND NOT
AptWaitSet equ 03h ;test, wait until NZ
AptWaitClr equ 04h ;test, wait until Z
AptWaitOther equ 05h ;compare, wait until NE
AptRd equ 06h ;read...
;---
AptMcu equ 1000h
AptDiff equ 2000h
AptOnly7Ah equ 4000h
AptOnly78h equ 8000h
;---
AptWrDiff equ AptWr+AptDiff
AptRdMcu equ AptMcu+AptRd
AptWrMcu equ AptMcu+AptWr
AptSetMcu equ AptMcu+AptSet
AptClrMcu equ AptMcu+AptClr
AptWrMcuDiff equ AptMcu+AptWr+AptDiff
AptWrMcuOnly7Ah equ AptMcu+AptWr+AptOnly7Ah
AptWaitMcuOther equ AptMcu+AptWaitOther
;------------------
InitAptDetails equ 0
;------------------
;SysFlaw init from 200D144h:
; [4004004h]=[4004004h] OR 0004h ;SCFG_CLK, Camera Interface Clock = ON
; [4004200h]=0000h ;CAM_MCNT, Camera Module Control
; test [4004004h].bit0 and delay(1Eh, step4) ;SCFG_CLK, ARM9 CPU Clock
; [4004004h]=[4004004h] OR 0100h ;SCFG_CLK, Camera External Clock = ON
; test [4004004h].bit0 and delay(1Eh, step4) ;SCFG_CLK, ARM9 CPU Clock
; [4004200h]=0022h ;CAM_MCNT, Camera Module Control
; test [4004004h].bit0 and delay(2008h, step4) ;SCFG_CLK, ARM9 CPU Clock
; [4004004h]=[4004004h] AND NOT 0100h ;SCFG_CLK, Camera External Clock = OFF
;Further code from 200D1F4h:
; [4004202h]=[4004202h] AND NOT 8000h ;CAM_CNT, disable (allow changing params)
;Further code from 200D270h:
; [4004202h]=[4004202h] OR 0020h
;Further code from 200D2C8h:
; [4004202h]=([4004202h] AND NOT 0300h) OR 0200h
;Further code from 200D2F4h:
; [4004202h]=[4004202h] OR 0400h
;Further code from 200D294h:
; [4004202h]=[4004202h] OR 0800h
;Further code from 200C9BCh:
; [4004004h]=[4004004h] OR 0100h ;SCFG_CLK, Camera External Clock = ON
; test [4004004h].bit0 and delay(14h, step4) ;SCFG_CLK, ARM9 CPU Clock
;---> Now do camera I2C init (up to setting BPTWL camera LED=off) <---
; aptina_code_list_init
;Further code from 200CBxxh:
; [4004004h]=[4004004h] AND NOT 0100h ;SCFG_CLK, Camera External Clock = OFF
;Further code from 200CBxxh:
; [4004004h]=[4004004h] OR 0100h ;SCFG_CLK, Camera External Clock = ON
; test [4004004h].bit0 and delay(14h, step4) ;SCFG_CLK, ARM9 CPU Clock
;---> Now do more camera I2C stuff (LED on, and init ONE of the cameras, till E0 04 98)
; aptina_code_list_activate
;Further code from 200D218h:
; [4004202h]=[4004202h] OR 2000h
;Further code from 200D3xxh:
; [4004202h]=([4004202h] AND NOT 000Fh) OR 0003h
;Further code from 200D270h:
; [4004202h]=[4004202h] OR 0020h ;was already so though
;Further code from 200D1D0h:
; [4004202h]=[4004202h] OR 8000h ;<--- kick (now AE23h)
;Further code from 200D36Ch:
; Read r0 = ([4004202h] AND 000Fh)+0001h
; Mul 200h
;---> Now do NDMA1:
; [4004120h]=04004204h ;NDMA1SAD <-- CAMERA
; [4004124h]=020D67E0h ;NDMA1DAD <-- RAM
; [4004128h]=00006000h ;NDMA1TCNT
; [400412Ch]=00000200h ;NDMA1WCNT
; [4004130h]=00000002h ;NDMA1BCNT
; [4004134h]=00000000h ;NDMA1FDATA
; [4004138h]=8B044000h ;NDMA1CNT
;Then,
; Read r0 = ([4004202h] AND 000Fh)+0001h
; and then hang... until NDMA finishes or so
;------------------
aptina_code_list_init: ;(as from system flaw)
dw AptRd ,00000h,0 ;CHIP_VERSION_REG
dw AptWr ,0001Ah,00003h ;RESET_AND_MISC_CONTROL (issue reset)
dw AptWr ,0001Ah,00000h ;RESET_AND_MISC_CONTROL (release reset)
dw AptWr ,00018h,04028h ;STANDBY_CONTROL (wakeup)
dw AptWr ,0001Eh,00201h ;PAD_SLEW
dw AptWr ,00016h,042DFh ;CLOCKS_CONTROL
dw AptWaitClr,00018h,04000h ;STANDBY_CONTROL (wait for bit14=0=WakeupDone)
dw AptWaitSet,0301Ah,00004h ;UNDOC! RESERVED? ALIAS of 3022h? (bit2=1=WakeupDone)
dw AptWrMcu ,002F0h,00000h ;UNDOC! RAM?
dw AptWrMcu ,002F2h,00210h ;UNDOC! RAM?
dw AptWrMcu ,002F4h,0001Ah ;UNDOC! RAM?
dw AptWrMcu ,02145h,002F4h ;UNDOC! SEQ?
dw AptWrMcu ,0A134h, 001h ;UNDOC! SEQ?
dw AptSetMcu ,0A115h, 002h ;SEQ_CAP_MODE (set bit1=video)
dw AptWrMcu ,02755h,00002h ;MODE_OUTPUT_FORMAT_A (bit5=0=YUV)
dw AptWrMcu ,02757h,00002h ;MODE_OUTPUT_FORMAT_B
dw AptWr ,00014h,02145h ;PLL_CONTROL
dw AptWr ,00010h,00111h ;PLL_DIVIDERS
dw AptWr ,00012h,00000h ;PLL_P_DIVIDERS
dw AptWr ,00014h,0244Bh ;PLL_CONTROL
dw AptWr ,00014h,0304Bh ;PLL_CONTROL
dw AptWaitSet,00014h,08000h ;PLL_CONTROL (wait for bit15=1=PllLockOkay)
dw AptClr ,00014h,00001h ;PLL_CONTROL (change bit0=0=PllBypassOff)
;---
.if InitAptDetails ;WORKs if skipped
dw AptWrMcu ,0222Dh,00058h ;AE_R9_STEP ;-AE R9 step
dw AptWrMcu ,0A408h, 015h ;FD_SEARCH_F1_50
dw AptWrMcu ,0A409h, 018h ;FD_SEARCH_F2_50
dw AptWrMcu ,0A40Ah, 019h ;FD_SEARCH_F1_60
dw AptWrMcu ,0A40Bh, 01Ch ;FD_SEARCH_F2_60
dw AptWrMcu ,02411h,00058h ;FD_R9_STEP_F60_A
dw AptWrMcu ,02413h,0006Ah ;FD_R9_STEP_F50_A
dw AptWrMcu ,02415h,00058h ;FD_R9_STEP_F60_B
dw AptWrMcu ,02417h,0006Ah ;FD_R9_STEP_F50_B
dw AptWrMcu ,0A402h, 01Dh ;FD_WINDOW_POSH (Horizontal Pos)
dw AptWrMcu ,0A403h, 004h ;FD_WINDOW_HEIGHT
dw AptWrMcu ,0A404h, 010h ;FD_MODE
dw AptWrMcu ,0A40Dh, 002h ;FD_STAT_MIN
dw AptWrMcu ,0A40Eh, 003h ;FD_STAT_MAX
dw AptWrMcu ,0A410h, 00Ah ;FD_MIN_AMPLITUDE
dw AptWrMcu ,0A40Ch, 000h ;UNDOC! RESERVED_FD_0C
.endif
dw AptWrMcu ,02703h,00100h ;256 ;MODE_OUTPUT_WIDTH_A ;\Size A
dw AptWrMcu ,02705h,000C0h ;192 ;MODE_OUTPUT_HEIGHT_A ;/ 256x192
dw AptWrMcu ,02707h,00280h ;640 ;MODE_OUTPUT_WIDTH_B ;\Size B
dw AptWrMcu ,02709h,001E0h ;480 ;MODE_OUTPUT_HEIGHT_B ;/ 640x480
;---
dw AptWrMcu ,02715h,00001h ;MODE_SENSOR_ROW_SPEED_A ;\
dw AptWrMcu ,02719h,0001Ah ;MODE_SENSOR_FINE_CORRECTION_A ;
dw AptWrMcu ,0271Bh,0006Bh ;MODE_SENSOR_FINE_IT_MIN_A ; Sensor A
dw AptWrMcu ,0271Dh,0006Bh ;MODE_SENSOR_FINE_IT_MAX_MARGIN_A ;
dw AptWrMcu ,0271Fh,002C0h ;MODE_SENSOR_FRAME_LENGTH_A ;
dw AptWrMcu ,02721h,0034Bh ;MODE_SENSOR_LINE_LENGTH_PCK_A ;/
;---
dw AptWrMcu ,0A20Bh, 000h ;AE_MIN_INDEX ;\AE min/max
dw AptWrMcu ,0A20Ch, 006h ;AE_MAX_INDEX ;/
;skipping above two AE_MIN/MAX_INDEX makes conversion MUCH slower
;(and picture becomes MUCH brighter, with BETTER low-light quality)
;---
dw AptWrMcu ,0272Bh,00001h ;MODE_SENSOR_ROW_SPEED_B ;\
dw AptWrMcu ,0272Fh,0001Ah ;MODE_SENSOR_FINE_CORRECTION_B ;
dw AptWrMcu ,02731h,0006Bh ;MODE_SENSOR_FINE_IT_MIN_B ; Sensor B
dw AptWrMcu ,02733h,0006Bh ;MODE_SENSOR_FINE_IT_MAX_MARGIN_B ;
dw AptWrMcu ,02735h,002C0h ;MODE_SENSOR_FRAME_LENGTH_B ;
dw AptWrMcu ,02737h,0034Bh ;MODE_SENSOR_LINE_LENGTH_PCK_B ;/
;---
.if InitAptDetails ;WORKs if skipped
dw AptWrMcu ,02739h,00000h ;MODE_CROP_X0_A ;\
dw AptWrMcu ,0273Bh,0027Fh ;MODE_CROP_X1_A ; Crop A
dw AptWrMcu ,0273Dh,00000h ;MODE_CROP_Y0_A ;
dw AptWrMcu ,0273Fh,001DFh ;MODE_CROP_Y1_A ;/
dw AptWrMcu ,02747h,00000h ;MODE_CROP_X0_B ;\
dw AptWrMcu ,02749h,0027Fh ;MODE_CROP_X1_B ; Crop B
dw AptWrMcu ,0274Bh,00000h ;MODE_CROP_Y0_B ;
dw AptWrMcu ,0274Dh,001DFh ;MODE_CROP_Y1_B ;/
dw AptWrMcu ,0A40Dh, 002h ;FD_STAT_MIN (blah, already done above)
dw AptWrMcu ,0A410h, 00Ah ;FD_MIN_AMPLITUDE (blah, already done above)
dw AptWrMcu ,0A40Ch, 000h ;UNDOC! RESERVED_FD_0C (blah, already done above)
;---
dw AptWr ,03658h,001F0h ;P_RD_P0Q0 ;\ ;\
dw AptWr ,0365Ah,059CCh ;P_RD_P0Q1 ; ;
dw AptWr ,0365Ch,05232h ;P_RD_P0Q2 ; P0 ;
dw AptWr ,0365Eh,0006Dh ;P_RD_P0Q3 ; ; P0..P4
dw AptWr ,03660h,08952h ;P_RD_P0Q4 ;/ ; Coefficients
dw AptWr ,03680h,03F8Ah ;P_RD_P1Q0 ;\ ; for Red
dw AptWr ,03682h,0D10Ch ;P_RD_P1Q1 ; ;
dw AptWr ,03684h,05C90h ;P_RD_P1Q2 ; P1 ;
dw AptWr ,03686h,0D0B0h ;P_RD_P1Q3 ; ;
dw AptWr ,03688h,0A614h ;P_RD_P1Q4 ;/ ;
dw AptWr ,036A8h,043B2h ;P_RD_P2Q0 ;\ ;
dw AptWr ,036AAh,04291h ;P_RD_P2Q1 ; ;
dw AptWr ,036ACh,034B6h ;P_RD_P2Q2 ; P2 ;
dw AptWr ,036AEh,0F955h ;P_RD_P2Q3 ; ;
dw AptWr ,036B0h,0F379h ;P_RD_P2Q4 ;/ ;
dw AptWr ,036D0h,023B2h ;P_RD_P3Q0 ;\ ;
dw AptWr ,036D2h,07630h ;P_RD_P3Q1 ; ;
dw AptWr ,036D4h,0BA14h ;P_RD_P3Q2 ; P3 ;
dw AptWr ,036D6h,0C814h ;P_RD_P3Q3 ; ;
dw AptWr ,036D8h,00FB9h ;P_RD_P3Q4 ;/ ;
dw AptWr ,036F8h,00E15h ;P_RD_P4Q0 ;\ ;
dw AptWr ,036FAh,0D055h ;P_RD_P4Q1 ; ;
dw AptWr ,036FCh,0CFBAh ;P_RD_P4Q2 ; P4 ;
dw AptWr ,036FEh,0109Ah ;P_RD_P4Q3 ; ;
dw AptWr ,03700h,07FBDh ;P_RD_P4Q4 ;/ ;/
dw AptWr ,0364Eh,002F0h ;P_GR_P0Q0 ;\ ;\
dw AptWr ,03650h,03D8Ah ;P_GR_P0Q1 ; ;
dw AptWr ,03652h,02512h ;P_GR_P0Q2 ; P0 ;
dw AptWr ,03654h,06049h ;P_GR_P0Q3 ; ; P0..P4
dw AptWr ,03656h,03B2Fh ;P_GR_P0Q4 ;/ ; Coefficients
dw AptWr ,03676h,08F06h ;P_GR_P1Q0 ;\ ; for Green1
dw AptWr ,03678h,0FCECh ;P_GR_P1Q1 ; ;
dw AptWr ,0367Ah,03710h ;P_GR_P1Q2 ; P1 ;
dw AptWr ,0367Ch,0B62Dh ;P_GR_P1Q3 ; ;
dw AptWr ,0367Eh,0C834h ;P_GR_P1Q4 ;/ ;
dw AptWr ,0369Eh,01072h ;P_GR_P2Q0 ;\ ;
dw AptWr ,036A0h,018F0h ;P_GR_P2Q1 ; ;
dw AptWr ,036A2h,03156h ;P_GR_P2Q2 ; P2 ;
dw AptWr ,036A4h,0CCF4h ;P_GR_P2Q3 ; ;
dw AptWr ,036A6h,0E8F9h ;P_GR_P2Q4 ;/ ;
dw AptWr ,036C6h,023F2h ;P_GR_P3Q0 ;\ ;
dw AptWr ,036C8h,0E40Fh ;P_GR_P3Q1 ; ;
dw AptWr ,036CAh,0A814h ;P_GR_P3Q2 ; P3 ;
dw AptWr ,036CCh,00E52h ;P_GR_P3Q3 ; ;
dw AptWr ,036CEh,05078h ;P_GR_P3Q4 ;/ ;
dw AptWr ,036EEh,01A75h ;P_GR_P4Q0 ;\ ;
dw AptWr ,036F0h,0B254h ;P_GR_P4Q1 ; ;
dw AptWr ,036F2h,0C23Ah ;P_GR_P4Q2 ; P4 ;
dw AptWr ,036F4h,07CD8h ;P_GR_P4Q3 ; ;
dw AptWr ,036F6h,05C1Dh ;P_GR_P4Q4 ;/ ;/
dw AptWr ,03662h,00230h ;P_BL_P0Q0 ;\ ;\
dw AptWr ,03664h,08D67h ;P_BL_P0Q1 ; ;
dw AptWr ,03666h,01F32h ;P_BL_P0Q2 ; P0 ;
dw AptWr ,03668h,0ACECh ;P_BL_P0Q3 ; ; P0..P4
dw AptWr ,0366Ah,003AEh ;P_BL_P0Q4 ;/ ; Coefficients
dw AptWr ,0368Ah,09ECCh ;P_BL_P1Q0 ;\ ; for Blue
dw AptWr ,0368Ch,09B2Dh ;P_BL_P1Q1 ; ;
dw AptWr ,0368Eh,00631h ;P_BL_P1Q2 ; P1 ;
dw AptWr ,03690h,0224Fh ;P_BL_P1Q3 ; ;
dw AptWr ,03692h,0BA54h ;P_BL_P1Q4 ;/ ;
dw AptWr ,036B2h,00392h ;P_BL_P2Q0 ;\ ;
dw AptWr ,036B4h,03E50h ;P_BL_P2Q1 ; ;
dw AptWr ,036B6h,027B6h ;P_BL_P2Q2 ; P2 ;
dw AptWr ,036B8h,0FC54h ;P_BL_P2Q3 ; ;
dw AptWr ,036BAh,0D9F9h ;P_BL_P2Q4 ;/ ;
dw AptWr ,036DAh,04112h ;P_BL_P3Q0 ;\ ;
dw AptWr ,036DCh,029F1h ;P_BL_P3Q1 ; ;
dw AptWr ,036DEh,096D4h ;P_BL_P3Q2 ; P3 ;
dw AptWr ,036E0h,0F934h ;P_BL_P3Q3 ; ;
dw AptWr ,036E2h,02B18h ;P_BL_P3Q4 ;/ ;
dw AptWr ,03702h,02615h ;P_BL_P4Q0 ;\ ;
dw AptWr ,03704h,0E9D4h ;P_BL_P4Q1 ; ;
dw AptWr ,03706h,0B4DAh ;P_BL_P4Q2 ; P4 ;
dw AptWr ,03708h,03899h ;P_BL_P4Q3 ; ;
dw AptWr ,0370Ah,052BDh ;P_BL_P4Q4 ;/ ;/
dw AptWr ,0366Ch,001B0h ;P_GB_P0Q0 ;\ ;\
dw AptWr ,0366Eh,069EAh ;P_GB_P0Q1 ; ;
dw AptWr ,03670h,02432h ;P_GB_P0Q2 ; P0 ;
dw AptWr ,03672h,030EEh ;P_GB_P0Q3 ; ; P0..P4
dw AptWr ,03674h,0056Fh ;P_GB_P0Q4 ;/ ; Coefficients
dw AptWr ,03694h,0B52Ah ;P_GB_P1Q0 ;\ ; for Green2
dw AptWr ,03696h,0C12Dh ;P_GB_P1Q1 ; ;
dw AptWr ,03698h,04650h ;P_GB_P1Q2 ; P1 ;
dw AptWr ,0369Ah,0640Fh ;P_GB_P1Q3 ; ;
dw AptWr ,0369Ch,0BAB4h ;P_GB_P1Q4 ;/ ;
dw AptWr ,036BCh,00CF2h ;P_GB_P2Q0 ;\ ;
dw AptWr ,036BEh,00351h ;P_GB_P2Q1 ; ;
dw AptWr ,036C0h,036F6h ;P_GB_P2Q2 ; P2 ;
dw AptWr ,036C2h,0A3F5h ;P_GB_P2Q3 ; ;
dw AptWr ,036C4h,0F2B9h ;P_GB_P2Q4 ;/ ;
dw AptWr ,036E4h,02B12h ;P_GB_P3Q0 ;\ ;
dw AptWr ,036E6h,0102Fh ;P_GB_P3Q1 ; ;
dw AptWr ,036E8h,0E0F4h ;P_GB_P3Q2 ; P3 ;
dw AptWr ,036EAh,088F5h ;P_GB_P3Q3 ; ;
dw AptWr ,036ECh,056B8h ;P_GB_P3Q4 ;/ ;
dw AptWr ,0370Ch,01EF5h ;P_GB_P4Q0 ;\ ;
dw AptWr ,0370Eh,09075h ;P_GB_P4Q1 ; ;
dw AptWr ,03710h,0CC9Ah ;P_GB_P4Q2 ; P4 ;
dw AptWr ,03712h,04D59h ;P_GB_P4Q3 ; ;
dw AptWr ,03714h,06BBDh ;P_GB_P4Q4 ;/ ;/
dw AptWr ,03644h,00144h ;POLY_ORIGIN_C (Center Column)
dw AptWr ,03642h,000F4h ;POLY_ORIGIN_R (Center Row)
.endif
;---
dw AptSet ,03210h,00008h ;COLOR_PIPELINE_CONTROL (set bit3=1, Enable PGA pixel shading correction)
;---
.if 01 ;<-- hangs if skipped? !!
dw AptWrMcu ,0A208h, 000h ;UNDOC! RESERVED_AE_08
dw AptWrMcu ,0A24Ch, 020h ;AE_TARGETBUFFERSPEED
dw AptWrMcu ,0A24Fh, 070h ;AE_BASETARGET
.endif
.if InitAptDetails ;WORKs if skipped
dw AptWrMcu ,0A109h, 020h ;SEQ_AE_FASTBUFF
dw AptWrMcu ,0A10Ah, 001h ;SEQ_AE_FASTSTEP
dw AptWrMcu ,0A20Bh, 000h ;AE_MIN_INDEX (blah, already set above)
dw AptWrMcu ,0A20Dh, 030h ;AE_MIN_VIRTGAIN
dw AptWrMcu ,0A20Eh, 080h ;AE_MAX_VIRTGAIN
dw AptWrMcu ,0A24Ah, 028h ;AE_TARGETMIN
dw AptWrMcu ,0A24Bh, 0C0h ;AE_TARGETMAX
dw AptWrMcu ,0A75Dh, 000h ;MODE_Y_RGB_OFFSET_A ;\Offset A/B
dw AptWrMcu ,0A75Eh, 000h ;MODE_Y_RGB_OFFSET_B ;/
dw AptWrMcu ,0A11Dh, 001h ;SEQ_PREVIEW_1_AE
dw AptWrMcu ,0A129h, 001h ;SEQ_PREVIEW_3_AE
dw AptWrMcu ,0A207h, 00Ch ;AE_GATE
dw AptWrMcu ,0A35Dh, 07Bh ;AWB_STEADY_BGAIN_OUT_MIN
dw AptWrMcu ,0A35Eh, 085h ;AWB_STEADY_BGAIN_OUT_MAX
dw AptWrMcu ,0A35Fh, 07Eh ;AWB_STEADY_BGAIN_IN_MIN
dw AptWrMcu ,0A360h, 082h ;AWB_STEADY_BGAIN_IN_MAX
dw AptWrMcu ,02361h,00040h ;UNDOC! RESERVED_AWB_61
dw AptWrMcu ,0A10Bh, 008h ;SEQ_AWB_CONTBUFF
dw AptWrMcu ,0A10Ch, 002h ;SEQ_AWB_CONTSTEP
dw AptWrMcu ,0A302h, 000h ;AWB_WINDOW_POS
dw AptWrMcu ,0A303h, 0FFh ;AWB_WINDOW_SIZE
dw AptWr ,0323Eh,0C22Ch ;UNDOC! RESERVED_SOC1_323E
dw AptWr ,03244h,00335h ;UNDOC! RESERVED_SOC1_3244
dw AptWr ,03240h,06214h ;UNDOC! RESERVED_SOC1_3240
dw AptWr ,031E0h,00001h ;UNDOC! RESERVED_CORE_31E0 .. PIX_DEF_ID ?
dw AptWr ,0322Ah,00004h ;UNDOC! RESERVED_SOC1_322A
dw AptWr ,035B0h,0049Dh ;UNDOC! RESERVED_SOC2_35B0
dw AptWrMcu ,0AB04h, 020h ;HG_MAX_DLEVEL
dw AptWrMcu ,0AB06h, 003h ;HG_PERCENT
dw AptWrMcu ,0AB37h, 003h ;HG_GAMMA_MORPH_CTRL
dw AptWrMcu ,02B28h,01388h ;HG_LL_BRIGHTNESSSTART
dw AptWrMcu ,02B2Ah,04E20h ;HG_LL_BRIGHTNESSSTOP
dw AptWrMcu ,02B38h,00100h ;HG_GAMMASTARTMORPH
dw AptWrMcu ,02B3Ah,020CCh ;HG_GAMMASTOPMORPH
dw AptWrMcu ,0AB21h, 008h ;UNDOC! RESERVED_HG_21
dw AptWrMcu ,0AB22h, 002h ;HG_LL_APCORR1
dw AptWrMcu ,0AB23h, 000h ;UNDOC! RESERVED_HG_23
dw AptWrMcu ,0AB25h, 014h ;HG_LL_INTERPTHRESH2
dw AptWrMcu ,0AB26h, 000h ;HG_LL_APCORR2
dw AptWrMcu ,0AB27h, 004h ;HG_LL_APTHRESH2
dw AptWrMcu ,0AB1Fh, 0C7h ;HG_LLMODE
dw AptWrMcu ,0AB31h, 01Eh ;HG_NR_STOP_G (huh, only "G", not "R+G+B"?)
.endif
;--- below is done separately for each camera (not done together at once)
dw AptWrMcuDiff ,02717h,00024h,00025h ;MODE_SENSOR_READ_MODE_A ;diff 7Ah/78h (diff=hflip)
dw AptWrMcuDiff ,0272Dh,00024h,00025h ;MODE_SENSOR_READ_MODE_B ; (diff=hflip)
dw AptWrMcuDiff ,0A202h, 022h, 000h ;AE_WINDOW_POS
dw AptWrMcuDiff ,0A203h, 0BBh, 0FFh ;AE_WINDOW_SIZE
.if InitAptDetails ;WORKs if skipped
dw AptWr ,03032h,00100h ;DIGITAL_GAIN_GREENR
dw AptWr ,03034h,00100h ;DIGITAL_GAIN_RED
dw AptWr ,03036h,00100h ;DIGITAL_GAIN_BLUE
dw AptWr ,03038h,00100h ;DIGITAL_GAIN_GREENB
.endif
;---
dw AptSet ,00016h,00020h ;CLOCKS_CONTROL (set bit5=1, reserved, UNDOC!)
;---
.if InitAptDetails ;WORKs if skipped
dw AptWrMcu ,0A24Fh, 070h ;AE_BASETARGET (blah, already set above)
dw AptWrMcu ,0A11Dh, 001h ;SEQ_PREVIEW_1_AE (blah, already set above)
dw AptWrMcu ,0A129h, 001h ;SEQ_PREVIEW_3_AE (blah, already set above)
dw AptWrMcu ,0AB3Ch, 000h ;HG_GAMMA_TABLE_A_0 ;\
dw AptWrMcuDiff ,0AB3Dh, 00Ch, 00Bh ;HG_GAMMA_TABLE_A_1 ;
dw AptWrMcuDiff ,0AB3Eh, 022h, 020h ;HG_GAMMA_TABLE_A_2 ;
dw AptWrMcuDiff ,0AB3Fh, 03Eh, 03Bh ;HG_GAMMA_TABLE_A_3 ;
dw AptWrMcuDiff ,0AB40h, 05Dh, 05Bh ;HG_GAMMA_TABLE_A_4 ;
dw AptWrMcuDiff ,0AB41h, 073h, 072h ;HG_GAMMA_TABLE_A_5 ;
dw AptWrMcuDiff ,0AB42h, 085h, 085h ;HG_GAMMA_TABLE_A_6 ;
dw AptWrMcuDiff ,0AB43h, 094h, 096h ;HG_GAMMA_TABLE_A_7 ;
dw AptWrMcuDiff ,0AB44h, 0A2h, 0A4h ;HG_GAMMA_TABLE_A_8 ;
dw AptWrMcuDiff ,0AB45h, 0AEh, 0B1h ;HG_GAMMA_TABLE_A_9 ;
dw AptWrMcuDiff ,0AB46h, 0B9h, 0BCh ;HG_GAMMA_TABLE_A_10 ;
dw AptWrMcuDiff ,0AB47h, 0C3h, 0C6h ;HG_GAMMA_TABLE_A_11 ;
dw AptWrMcuDiff ,0AB48h, 0CDh, 0D0h ;HG_GAMMA_TABLE_A_12 ;
dw AptWrMcuDiff ,0AB49h, 0D7h, 0D9h ;HG_GAMMA_TABLE_A_13 ;
dw AptWrMcuDiff ,0AB4Ah, 0DFh, 0E2h ;HG_GAMMA_TABLE_A_14 ;
dw AptWrMcuDiff ,0AB4Bh, 0E8h, 0EAh ;HG_GAMMA_TABLE_A_15 ;
dw AptWrMcuDiff ,0AB4Ch, 0F0h, 0F1h ;HG_GAMMA_TABLE_A_16 ;
dw AptWrMcu ,0AB4Dh, 0F8h ;HG_GAMMA_TABLE_A_17 ;
dw AptWrMcu ,0AB4Eh, 0FFh ;HG_GAMMA_TABLE_A_18 ;/
dw AptWrMcu ,0AB4Fh, 000h ;HG_GAMMA_TABLE_B_0 ;\
dw AptWrMcuDiff ,0AB50h, 00Ch, 00Bh ;HG_GAMMA_TABLE_B_1 ;
dw AptWrMcuDiff ,0AB51h, 026h, 023h ;HG_GAMMA_TABLE_B_2 ;
dw AptWrMcuDiff ,0AB52h, 050h, 04Dh ;HG_GAMMA_TABLE_B_3 ;
dw AptWrMcuDiff ,0AB53h, 072h, 071h ;HG_GAMMA_TABLE_B_4 ;
dw AptWrMcuDiff ,0AB54h, 088h, 088h ;HG_GAMMA_TABLE_B_5 ;
dw AptWrMcuDiff ,0AB55h, 098h, 09Ah ;HG_GAMMA_TABLE_B_6 ;
dw AptWrMcuDiff ,0AB56h, 0A6h, 0A9h ;HG_GAMMA_TABLE_B_7 ;
dw AptWrMcuDiff ,0AB57h, 0B2h, 0B5h ;HG_GAMMA_TABLE_B_8 ;
dw AptWrMcuDiff ,0AB58h, 0BCh, 0C0h ;HG_GAMMA_TABLE_B_9 ;
dw AptWrMcuDiff ,0AB59h, 0C6h, 0C9h ;HG_GAMMA_TABLE_B_10 ;
dw AptWrMcuDiff ,0AB5Ah, 0CFh, 0D2h ;HG_GAMMA_TABLE_B_11 ;
dw AptWrMcuDiff ,0AB5Bh, 0D7h, 0DAh ;HG_GAMMA_TABLE_B_12 ;
dw AptWrMcuDiff ,0AB5Ch, 0DFh, 0E1h ;HG_GAMMA_TABLE_B_13 ;
dw AptWrMcuDiff ,0AB5Dh, 0E6h, 0E8h ;HG_GAMMA_TABLE_B_14 ;
dw AptWrMcuDiff ,0AB5Eh, 0EDh, 0EEh ;HG_GAMMA_TABLE_B_15 ;
dw AptWrMcuDiff ,0AB5Fh, 0F3h, 0F4h ;HG_GAMMA_TABLE_B_16 ;
dw AptWrMcuDiff ,0AB60h, 0F9h, 0FAh ;HG_GAMMA_TABLE_B_17 ;
dw AptWrMcu ,0AB61h, 0FFh ;HG_GAMMA_TABLE_B_18 ;/
dw AptWrMcu ,02306h,0038Ah ;AWB_CCM_L_0 ;\ ;\
dw AptWrMcu ,02308h,0FDDDh ;AWB_CCM_L_1 ; K11,K12,K13 ;
dw AptWrMcu ,0230Ah,0003Ah ;AWB_CCM_L_2 ;/ ;
dw AptWrMcu ,0230Ch,0FF42h ;AWB_CCM_L_3 ;\ ; Left
dw AptWrMcu ,0230Eh,002D7h ;AWB_CCM_L_4 ; K21,K22,K23 ; CCM
dw AptWrMcu ,02310h,0FF67h ;AWB_CCM_L_5 ;/ ; Matrix
dw AptWrMcu ,02312h,0FF5Dh ;AWB_CCM_L_6 ;\ ;
dw AptWrMcu ,02314h,0FD98h ;AWB_CCM_L_7 ; K31,K32,K33 ;
dw AptWrMcu ,02316h,00437h ;AWB_CCM_L_8 ;/ ;
dw AptWrMcu ,02318h,00015h ;AWB_CCM_L_9 ;-Red/Green Gain ;
dw AptWrMcu ,0231Ah,0003Ch ;AWB_CCM_L_10 ;-Blue/Green Gain ;/
dw AptWrMcu ,0231Ch,0FF30h ;AWB_CCM_RL_0 ;\ ;\
dw AptWrMcu ,0231Eh,00092h ;AWB_CCM_RL_1 ; D11,D12,D13 ;
dw AptWrMcu ,02320h,0FFD1h ;AWB_CCM_RL_2 ;/ ;
dw AptWrMcu ,02322h,00041h ;AWB_CCM_RL_3 ;\ ; Delta
dw AptWrMcu ,02324h,0FFD4h ;AWB_CCM_RL_4 ; D21,D22,D23 ; CCM
dw AptWrMcu ,02326h,0FFB8h ;AWB_CCM_RL_5 ;/ ; Matrix
dw AptWrMcu ,02328h,00085h ;AWB_CCM_RL_6 ;\ ;
dw AptWrMcu ,0232Ah,00199h ;AWB_CCM_RL_7 ; D31,D32,D33 ;
dw AptWrMcu ,0232Ch,0FDE2h ;AWB_CCM_RL_8 ;/ ;
dw AptWrMcu ,0232Eh,00010h ;AWB_CCM_RL_9 ;-Red/Green Gain ;
dw AptWrMcu ,02330h,0FFE9h ;AWB_CCM_RL_10 ;-Blue/Green Gain ;/
dw AptWrMcu ,0AB20h, 068h ;HG_LL_SAT1
dw AptWrMcu ,0AB24h, 028h ;HG_LL_SAT2
dw AptWrMcu ,0A365h, 020h ;AWB_X0
dw AptWrMcu ,0A366h, 0F0h ;AWB_KR_L
dw AptWrMcu ,0A367h, 0A0h ;AWB_KG_L
dw AptWrMcu ,0A368h, 060h ;AWB_KB_L
dw AptWrMcu ,0A369h, 082h ;AWB_KR_R
dw AptWrMcu ,0A36Ah, 082h ;AWB_KG_R
dw AptWrMcu ,0A36Bh, 082h ;AWB_KB_R
dw AptWrMcu ,0A363h, 0D5h ;AWB_TG_MIN0
dw AptWrMcu ,0A364h, 0EDh ;AWB_TG_MAX0
dw AptWrMcu ,0A34Ah, 076h ;AWB_GAIN_MIN
dw AptWrMcu ,0A34Bh, 0D9h ;AWB_GAIN_MAX
dw AptWrMcu ,0A34Ch, 060h ;AWB_GAINMIN_B
dw AptWrMcu ,0A34Dh, 0C7h ;AWB_GAINMAX_B
.endif
dw AptWrMcu ,0A115h, 072h ;SEQ_CAP_MODE (was already somehow manipulated)
dw AptWrMcu ,0A11Fh, 001h ;SEQ_PREVIEW_1_AWB
;---
.if InitAptDetails ;WORKs if skipped
dw AptSet ,00016h,00000h ;CLOCKS_CONTROL (blah, nothing changed here)
.endif
;---
dw AptWrDiff ,0326Ch,00900h,01000h ;APERTURE_PARAMETERS (diff... XXX)
dw AptWrMcuDiff ,0AB22h, 001h, 002h ;HG_LL_APCORR1 (diff... XXX)
.if InitAptDetails ;WORKs if skipped
dw AptWrMcuOnly7Ah,0A202h, 022h ;AE_WINDOW_POS (device 7Ah only?) (and blah, already set so above!)
dw AptWrMcuOnly7Ah,0A203h, 0BBh ;AE_WINDOW_SIZE (device 7Ah only?) (and blah, already set so above!)
.endif
;---
dw AptWrMcu ,0A103h, 006h ;SEQ_CMD (06h=RefreshMode)
dw AptWaitMcuOther,0A103h, 006h ;SEQ_CMD (wait to become ZERO instead of 06h)
;---
dw AptWrMcu ,0A103h, 005h ;SEQ_CMD (05h=Refresh)
dw AptWaitMcuOther,0A103h, 005h ;SEQ_CMD (wait to become ZERO instead of 05h)
;---
.if InitAptDetails ;WORKs if skipped
dw AptSet ,00018h,00001h ;STANDBY_CONTROL (set bit0=1=Standby)
dw AptWaitSet ,00018h,04000h ;STANDBY_CONTROL (wait for bit14=1=StandbyDone)
dw AptWaitClr ,0301Ah,00004h ;UNDOC! RESERVED? ALIAS of 3022h? (bit2=0=StandbyDone)
.endif
;---
dw -1
.align 4
;------------------
aptina_code_list_activate: ;(as from system flaw)
;--- below ONLY for device 78h (=active camera?)
.if InitAptDetails ;WORKs if skipped
dw AptSet ,00016h,00000h ;CLOCKS_CONTROL (blah, nothing changed here)
dw AptRdMcu ,0A117h,0 ;SEQ_PREVIEW_0_AE ;\
dw AptRdMcu ,0A11Dh,0 ;SEQ_PREVIEW_1_AE ; backup old? uh, is that reading possible during standby?
dw AptRdMcu ,0A11Fh,0 ;SEQ_PREVIEW_1_AWB ;/
dw AptRd ,03012h,0 ;COARSE_INTEGRATION_TIME (Y Time)
dw AptRd ,03028h,0 ;ANALOGUE_GAIN_CODE_GLOBAL ;\
dw AptRd ,0302Ah,0 ;ANALOGUE_GAIN_CODE_GREENR ; Analogue Gain Codes
dw AptRd ,0302Ch,0 ;ANALOGUE_GAIN_CODE_RED ; with 3bit fraction
dw AptRd ,0302Eh,0 ;ANALOGUE_GAIN_CODE_BLUE ; (0..007Fh, def=000Bh)
dw AptRd ,03030h,0 ;ANALOGUE_GAIN_CODE_GREENB ;/
dw AptWrMcu ,0A117h, 000h ;SEQ_PREVIEW_0_AE ;\
dw AptWrMcu ,0A11Dh, 000h ;SEQ_PREVIEW_1_AE ; temporarily off?
dw AptWrMcu ,0A11Fh, 000h ;SEQ_PREVIEW_1_AWB ;/
.endif
;---
dw AptClr ,00018h,00001h ;STANDBY_CONTROL (bit0=0=wakeup)
dw AptWaitClr ,00018h,04000h ;STANDBY_CONTROL (wait for bit14=0=WakeupDone)
dw AptWaitSet ,0301Ah,00004h ;UNDOC! RESERVED? ALIAS of 3022h? (bit2=1=WakeupDone)
;---
.if InitAptDetails ;WORKs if skipped
dw AptWr ,031E0h,00001h ;UNDOC! RESERVED_CORE_31E0 .. PIX_DEF_ID ? (blah, already set so in init)
.endif
;---
dw AptWr ,03012h,00000h +10h +800h ;COARSE_INTEGRATION_TIME (Y Time) (raises brightness !!!)
;above COARSE=800h is required at night for good brightness when sitting in a room with a small bulb ?
;but at normal daylight (without much sunshine), COARSE 0,10h,800h, doesn't make much of a difference?
;see also AE_MIN/MAX_INDEX
;---
.if InitAptDetails ;WORKs if skipped
dw AptWr ,03028h,00000h ;ANALOGUE_GAIN_CODE_GLOBAL ;\
dw AptWr ,0302Ah,00000h ;ANALOGUE_GAIN_CODE_GREENR ; Analogue Gain Codes
dw AptWr ,0302Ch,00000h ;ANALOGUE_GAIN_CODE_RED ; with 3bit fraction
dw AptWr ,0302Eh,00000h ;ANALOGUE_GAIN_CODE_BLUE ; (0..007Fh, def=000Bh)
dw AptWr ,03030h,00000h ;ANALOGUE_GAIN_CODE_GREENB ;/
dw AptWrMcu ,0A117h, 000h ;SEQ_PREVIEW_0_AE ;\
dw AptWrMcu ,0A11Dh, 001h ;SEQ_PREVIEW_1_AE ; restore old?
dw AptWrMcu ,0A11Fh, 001h ;SEQ_PREVIEW_1_AWB ;/
dw AptWrMcu ,0A103h, 006h ;SEQ_CMD (06h=RefreshMode)
dw AptWaitMcuOther,0A103h, 006h ;SEQ_CMD (wait to become ZERO instead of 06h)
dw AptWrMcu ,0A103h, 005h ;SEQ_CMD (05h=Refresh)
dw AptWaitMcuOther,0A103h, 005h ;SEQ_CMD (wait to become ZERO instead of 05h)
.endif
dw AptSet ,0001Ah,00200h ;RESET_AND_MISC_CONTROL (bit9=1=ParallelEnable)
;---
dw -1
.align 4
;------------------
Re: Trying to get the DSi cameras working
thanks! I'll give it a try and let you know.
Re: Trying to get the DSi cameras working
well, my init procedure does include all the 'essential' operations your code is doing, and yet, it's still freezing.
I figure that might be because I'm only initializing one camera, somehow; maybe I'm supposed to init both simultaneously, like official apps do? that's all I can see, I'm entirely out of ideas there. lest of trying a straight copypaste of your init list...
EDIT- initializing both cameras simultaneously didn't help, either.
but there must be something screwy with I2C comm. I'm trying to read some registers from the cameras after init, and the results for some registers differ depending on previous reads, and registers for camera 0x78 tend to be ORed with 0x03FF, which is weird.
EDIT- okay, seems I fixed the I2C fuckiness (turns out you don't set the ACK bit when receiving the last byte during a read). that seems to have fixed the hang, let's see if I can actually get something done now.
EDIT- well, I managed to have one camera frame displayed onscreen. thank you for your code, that helped me figure out what the issue was (after much fumbling, heh). now I can focus on what I originally wanted to do: reversing the specifics of the camera transfer hardware.
basically, setting bit15 in CAM_CNT and setting up the NDMA transfer will allow one frame to be transferred, but that's about it. I noticed some more oddities, for example, the DSi camera app won't set CAM_CNT.bit15 until it has received some IRQ. I want to see what the conditions are, because obviously, the frame transfer is working well on its own, but the DRQ bit in CAM_CNT isn't getting set on its own...
EDIT- some quick precisions on this before I go to bed
* camera IRQ is thrown every time the camera has a new frame it can transfer ('camera vblank' I guess)
* DRQ bit gets set when the internal buffer is full, ie. when enabling the transfer in CAM_CNT but never actually transferring shit
* have yet to figure out how big the buffer is
* DMA is triggered when CAM_CNT.bit15 is set and when the buffer is full enough (sure enough, the 'DMA scanlines' setting in CAM_CNT)
wasn't sure how all of these interacted, so maybe now I can make an implementation that won't make the camera app shit itself... we'll see tomorrow.
I figure that might be because I'm only initializing one camera, somehow; maybe I'm supposed to init both simultaneously, like official apps do? that's all I can see, I'm entirely out of ideas there. lest of trying a straight copypaste of your init list...
EDIT- initializing both cameras simultaneously didn't help, either.
but there must be something screwy with I2C comm. I'm trying to read some registers from the cameras after init, and the results for some registers differ depending on previous reads, and registers for camera 0x78 tend to be ORed with 0x03FF, which is weird.
EDIT- okay, seems I fixed the I2C fuckiness (turns out you don't set the ACK bit when receiving the last byte during a read). that seems to have fixed the hang, let's see if I can actually get something done now.
EDIT- well, I managed to have one camera frame displayed onscreen. thank you for your code, that helped me figure out what the issue was (after much fumbling, heh). now I can focus on what I originally wanted to do: reversing the specifics of the camera transfer hardware.
basically, setting bit15 in CAM_CNT and setting up the NDMA transfer will allow one frame to be transferred, but that's about it. I noticed some more oddities, for example, the DSi camera app won't set CAM_CNT.bit15 until it has received some IRQ. I want to see what the conditions are, because obviously, the frame transfer is working well on its own, but the DRQ bit in CAM_CNT isn't getting set on its own...
EDIT- some quick precisions on this before I go to bed
* camera IRQ is thrown every time the camera has a new frame it can transfer ('camera vblank' I guess)
* DRQ bit gets set when the internal buffer is full, ie. when enabling the transfer in CAM_CNT but never actually transferring shit
* have yet to figure out how big the buffer is
* DMA is triggered when CAM_CNT.bit15 is set and when the buffer is full enough (sure enough, the 'DMA scanlines' setting in CAM_CNT)
wasn't sure how all of these interacted, so maybe now I can make an implementation that won't make the camera app shit itself... we'll see tomorrow.
Re: Trying to get the DSi cameras working
Yeah, some I2C device seem to be using ACK to indicate whether to "request to receive more data". Not sure if that is standarized, or if it depends on the device/manufacturer. And not sure what it is good for (slightly earlier transfer-stop notification than stop condition)? Anyways, glad that you got it working!
Are you planning to support USB cameras in the emulator? And if yes, for which OS, with which software interface? I had tried it in no$gba some years ago using DirectShow (which seemed to be the most standard backwards compatible way). The default behaviour of DirectShow is:
To process the camera image in software, one is supposed to add two filters (Sample Grabber to receive the bitmap, and Null Filter to prevent the ugly ActiveMovie Window being displayed):
The problem is that those two filter don't seem to be part of the window OS, and instead microsoft seems to want people to write those filters themselves using some kind of microsoft SDK (without having that SDK, it appears to impossible to use DirectShow, especially when coding in raw ASM, so I finally gave up on that part).
I guess anything newer than DirectShow is coming up with yet more nasty issues, and/or require to include 500MByte of driver binaries ; )
Are you planning to support USB cameras in the emulator? And if yes, for which OS, with which software interface? I had tried it in no$gba some years ago using DirectShow (which seemed to be the most standard backwards compatible way). The default behaviour of DirectShow is:
Code: Select all
Camera Source ---> optional filter(s) ---> ActiveMovie Window
Code: Select all
Camera Source ---> Sample Grabber Filter ---> Null Filter
I guess anything newer than DirectShow is coming up with yet more nasty issues, and/or require to include 500MByte of driver binaries ; )
Re: Trying to get the DSi cameras working
heh.
well, regarding melonDS, we use the Qt framework. it's not what I like the most, but it lets us port melonDS to other platforms without too much trouble (well, less trouble than the existing alternatives, and I've studied them long and hard).
from what I could see, Qt does support camera input, via the QCamera class. I'm not sure how good that is, though. we use SDL2 as a sorta-complement library for things like audio support and joystick input, because Qt isn't very good at these things. (that's the thing about Qt, it kinda tries to cover everything, but without being particularly good at it. also it's huge)
SDL2 itself doesn't seem to have any camera support however. I found a sample that uses v4l2 but that seems to be specific to Linux.
shrug.
we might also want alternate camera input modes, akin to what we have for microphone input. like feeding a still picture or a video file, but that's another can of worms.
well, regarding melonDS, we use the Qt framework. it's not what I like the most, but it lets us port melonDS to other platforms without too much trouble (well, less trouble than the existing alternatives, and I've studied them long and hard).
from what I could see, Qt does support camera input, via the QCamera class. I'm not sure how good that is, though. we use SDL2 as a sorta-complement library for things like audio support and joystick input, because Qt isn't very good at these things. (that's the thing about Qt, it kinda tries to cover everything, but without being particularly good at it. also it's huge)
SDL2 itself doesn't seem to have any camera support however. I found a sample that uses v4l2 but that seems to be specific to Linux.
shrug.
we might also want alternate camera input modes, akin to what we have for microphone input. like feeding a still picture or a video file, but that's another can of worms.
Re: Trying to get the DSi cameras working
so, my observations so far on the whole 'camera buffer' thing:
* when doing manual reading of the camera picture: setting the CAM_CNT DMA threshold to 0 lets me read two blocks instead of one
* this, even if I use manual DMA transfers instead of reading it word per word, which strikes me as weird, manual DMA would hardly be slower than the automated NDMA transfer, unless NDMA is able to use some magical faster bus?
* nope, not even NDMA is fast enough
* from what I gather, the DRQ bit is set when the amount of data in the buffer reaches the DMA threshold, and that is what triggers a DMA transfer
* nope. DRQ bit is set on overflow as well as underflow (if DMA threshold is lower than DMA block size), it's an error bit
* transfer stops presumably when the buffer overflows, atleast until you set bit5 in CAM_CNT
* no idea yet how big the buffer is
* haven't found a way to read the current buffer level, either
it's weird because if I measure the time between setting CAM_CNT.bit15 and the DRQ bit getting set, it's always some ugly number (like 2214203 cycles), and has no relation to the DMA threshold. so really, what's the DRQ bit about, is it more like some overflow bit?
measurements made by making the camera DMA read from timer registers instead of 0x04004204, show the following:
* when DMA threshold is 0: transfer starts 708572 cycles after it's enabled
* when DMA threshold is 3: 730944 cycles.
* it takes 2 cycles per word.
beh, the timing are just weird.
I also couldn't get DMA thresholds above 3 to work. probably has to do with the PAD_SLEW register on the camera side.
* when doing manual reading of the camera picture: setting the CAM_CNT DMA threshold to 0 lets me read two blocks instead of one
* this, even if I use manual DMA transfers instead of reading it word per word, which strikes me as weird, manual DMA would hardly be slower than the automated NDMA transfer, unless NDMA is able to use some magical faster bus?
* nope, not even NDMA is fast enough
* from what I gather, the DRQ bit is set when the amount of data in the buffer reaches the DMA threshold, and that is what triggers a DMA transfer
* nope. DRQ bit is set on overflow as well as underflow (if DMA threshold is lower than DMA block size), it's an error bit
* transfer stops presumably when the buffer overflows, atleast until you set bit5 in CAM_CNT
* no idea yet how big the buffer is
* haven't found a way to read the current buffer level, either
it's weird because if I measure the time between setting CAM_CNT.bit15 and the DRQ bit getting set, it's always some ugly number (like 2214203 cycles), and has no relation to the DMA threshold. so really, what's the DRQ bit about, is it more like some overflow bit?
measurements made by making the camera DMA read from timer registers instead of 0x04004204, show the following:
* when DMA threshold is 0: transfer starts 708572 cycles after it's enabled
* when DMA threshold is 3: 730944 cycles.
* it takes 2 cycles per word.
beh, the timing are just weird.
I also couldn't get DMA thresholds above 3 to work. probably has to do with the PAD_SLEW register on the camera side.
Re: Trying to get the DSi cameras working
This stung me the first time I wrote an I²C host. The endpoint wouldn't listen to a STOP if I'd acknowledged a byte, and would talk all over subsequent communication.
This is part of the standard, but kind of hidden:
NXP UM10204 §3.1.6 wrote:There are five conditions that lead to the generation of a NACK: [...] 5. A master-receiver must signal the end of the transfer to the slave transmitter.
Re: Trying to get the DSi cameras working
CAM_CNT.bit4 in gbatek is currently described as "Data request? or Data overrun? or so?".
If you are also thinking that it is just an error flag... okay, I'll change it to "Data overrun/underrun error".
I think there might be no buffer at all at camera side, ie. it does probably just output pixels on the fly.
If that's right, the PAD_SLEW register (in the camera) can hardly affect the receive buffer size (in the console).
The receive buffer size... well it's apparently selected via CAM_CNT.bit0-3. Setting that to 3 (default) will receive 3+1 scanlines, usually with 256 pixels. So the receive buffer would be 1024 pixels, or probably twice as much for receiving another block while DMAing the previous block.
The question would be what happens when using horizontal resolutions other than 256 pixels:
For 128-pixel scanlines... maybe you can receive up to 8 scanlines per block?
For 640-pixel scanlines... maybe you can receive only 1 or 2 scanlines per block?
If you want to do very uncommon things: The camera's MODE_OUTPUT_FORMAT could be theoretically programmed to Mono or RGB instead of YUV, that might also affect the number of pixels vs buffer size.
The conversion time does very much vary depending on brightness/exposure settings (and there's even an auto-exposure mode). I don't think that you could convert that into a meaningful formula for calculating timings.
Setting CAM_CNT.bit15 does probably just enable receive (without notifying the camera about it, so the timing till first data block would depend on when the camera is sending the next VSYNC signal).
If you are also thinking that it is just an error flag... okay, I'll change it to "Data overrun/underrun error".
I think there might be no buffer at all at camera side, ie. it does probably just output pixels on the fly.
If that's right, the PAD_SLEW register (in the camera) can hardly affect the receive buffer size (in the console).
The receive buffer size... well it's apparently selected via CAM_CNT.bit0-3. Setting that to 3 (default) will receive 3+1 scanlines, usually with 256 pixels. So the receive buffer would be 1024 pixels, or probably twice as much for receiving another block while DMAing the previous block.
The question would be what happens when using horizontal resolutions other than 256 pixels:
For 128-pixel scanlines... maybe you can receive up to 8 scanlines per block?
For 640-pixel scanlines... maybe you can receive only 1 or 2 scanlines per block?
If you want to do very uncommon things: The camera's MODE_OUTPUT_FORMAT could be theoretically programmed to Mono or RGB instead of YUV, that might also affect the number of pixels vs buffer size.
The conversion time does very much vary depending on brightness/exposure settings (and there's even an auto-exposure mode). I don't think that you could convert that into a meaningful formula for calculating timings.
Setting CAM_CNT.bit15 does probably just enable receive (without notifying the camera about it, so the timing till first data block would depend on when the camera is sending the next VSYNC signal).
Re: Trying to get the DSi cameras working
The 3DS is having very similar camera hardware.
But, looking at the 3DS CAM_CNT register, there is no "number scanlines" setting.
Instead, there's a CAM_STAT register indicating the FIFO size in range 0..500h (mul 8 bytes?)
So, the buffer size is apparently matched to a multiple of 320 pixels, not 256 pixels (on 3DS at least).
But, looking at the 3DS CAM_CNT register, there is no "number scanlines" setting.
Instead, there's a CAM_STAT register indicating the FIFO size in range 0..500h (mul 8 bytes?)
So, the buffer size is apparently matched to a multiple of 320 pixels, not 256 pixels (on 3DS at least).
Re: Trying to get the DSi cameras working
Good to know, thanks! The full text is...
There are five conditions that lead to the generation of a NACK:
1. No receiver is present on the bus with the transmitted address so there is no device to respond with an acknowledge.
2. The receiver is unable to receive or transmit because it is performing some real-time function and is not ready to start communication with the master.
3. During the transfer, the receiver gets data or commands that it does not understand.
4. During the transfer, the receiver cannot receive any more data bytes.
5. A master-receiver must signal the end of the transfer to the slave transmitter.
Re: Trying to get the DSi cameras working
I've been gazing at the I2C low level transfer diagrams...
Sending the I2C Stop condition is done by sending a "corrupted" databit (instead of sending the first databit of the next byte) on the SDA output pin.
However, in receive mode, SDA would be in input direction (for receiving the first databit of next byte). So the master simply cannot output the Stop condition in that state (unless when using the ACK bit to notify the slave that the transfer will be stopped now).
---
Apart from Start and Stop conditions, Nintendo's I2C_CNT register can also generate some sort of "Error/Flush/Pause/whatever" condition:
I don't really know what bit2 is doing... Everything seems to work without using that bit... Although Nintendo's code does set that bit in some cases (no idea when/why they are doing that exactly).
Sending the I2C Stop condition is done by sending a "corrupted" databit (instead of sending the first databit of the next byte) on the SDA output pin.
However, in receive mode, SDA would be in input direction (for receiving the first databit of next byte). So the master simply cannot output the Stop condition in that state (unless when using the ACK bit to notify the slave that the transfer will be stopped now).
---
Apart from Start and Stop conditions, Nintendo's I2C_CNT register can also generate some sort of "Error/Flush/Pause/whatever" condition:
Code: Select all
bit0 Stop (0=No, 1=Stop/last byte)
bit1 Start (0=No, 1=Start/first byte)
bit2 Error (0=No, 1=Pause/Flush? after Error, used with/after Stop)
Re: Trying to get the DSi cameras working
well, good to know. reminds me there are still flaws in melonDS's I2C code...
by the way, if you're interested in updating GBAtek's DS side of the documentation, just let me know. (alternately you can look around on the melonDS blog or board)
namely, I have some notes on the 3D engine (details on GX timings and fun low-level details on the rasterizer), some details on wifi operation (namely about the multiplayer features), and some other minor things (mostly things like register bits/values documented as 'reserved/prohibited')...
by the way, if you're interested in updating GBAtek's DS side of the documentation, just let me know. (alternately you can look around on the melonDS blog or board)
namely, I have some notes on the 3D engine (details on GX timings and fun low-level details on the rasterizer), some details on wifi operation (namely about the multiplayer features), and some other minor things (mostly things like register bits/values documented as 'reserved/prohibited')...
Re: Trying to get the DSi cameras working
Yes, let's start with...
http://forums.nesdev.com/viewtopic.php?f=23&t=21140 - NDS Cartridge ROM specs
http://forums.nesdev.com/viewtopic.php?f=23&t=21141 - NDS Wifi specs
I am a bit out of touch with 2D/3D video hardware, but I'll still figure out how to update, too (preferably with understanding the updated stuff myself).
Re: Trying to get the DSi cameras working
Regarding I²C:
Maybe my driver helps. This is for 3DS but the I²C regs are basically identically with few exceptions.
https://github.com/profi200/open_agb_fi ... ware/i2c.c
https://github.com/profi200/open_agb_fi ... ware/i2c.h
On the "kernel_experiments" branch you can also find a version with proper locks and waiting for events instead of blocking on the IRQ.
Maybe my driver helps. This is for 3DS but the I²C regs are basically identically with few exceptions.
https://github.com/profi200/open_agb_fi ... ware/i2c.c
https://github.com/profi200/open_agb_fi ... ware/i2c.h
On the "kernel_experiments" branch you can also find a version with proper locks and waiting for events instead of blocking on the IRQ.