이전 포스팅에서는 OV5640에 대해 간단히 알아보고 블록 다이어그램에서 전원 부분을 조금 살펴봤다. 이 부분은 DVDD에 1.5를 공급해줘야 하고, LDO에 의해 발생하는 발열을 주의해야 한다는 내용, PWDN 핀과 RESETB 핀의 타이밍 정도만 알아두면 될 것 같다. 자 이제 모든 IC의 심장과도 같은 Clock에 대해 알아보도록 하자. 후
(근데 이걸 왜 하냐면.. 구글링만 해도 많은 사람들이 작성해놓은 드라이버들이 많다. 사실 그거 그냥 가져다 사용하면 동작은 하겠지. 근데 다 단종모델이고 나는 최신(?) 모델을 사용할 계획인데 아직 데이터 시트를 받지 못했다. 뭐 큰 차이는 없을 테니까 카메라, 이미지 센서 개념도 이해할 겸 해서 리딩 하는 거다.)
3. OV5640 Clcok
OV5640은 XVCLK에 main clock을 공급하고 PLL을 통해 분기되는 듯하다. 근데 이 부분에 대한 블록 다이어그램은 없다. 그리고 블록 다이어 그램에 PCLK 화살표 방향으로 봐서는 분명 출력인 거 같은데 레지스터 내용을 보면 입출력이 되는 것 같다? 뭐지..?
이 부분은 카메라의 화질과 속도 등에 영향을 미치는 부분이기 때문에 굉장히 중요하다. 하나씩 꼼꼼히 집고 넘어가도록 노!력! 해보기로 하면서 OV5640의 XVCLK와 PCLK에 대해 알아보자!
3.1 Clock 설정
이전 포스팅에서는 clock의 하드웨어 스펙만 살펴봤다. 그럼 clock이 PLL을 통해 어떻게 활용되는지 확인해보자. PLL이 뭔지 이해하는 건.. 각자 알아서 하길 바란다. 나도 잘 모른다ㅎㅎ 왜냐고? 복잡하고 어려우니까ㅜㅜ
나도 공부해야 하니 링크는 걸어두도록 하겠다.
http://www.rfdh.com/bas_rf/begin/pll.php3
시스템에서 PLL 사용 여부는 아래 레지스터에서 설정한다.
Address | register name | default |
0x3103 | SCCB SYSTEM CTRL 1 | 0x00 |
bit[7] | bit[6] | bit[5] | bit[4] | bit[3] | bit[2] | bit[1] | bit[0] |
bit[1] : Select system input clock -> 0 : From pad clock -> 1 : From PLL |
데이터 시트를 보면 곳곳에 "Debug mode Changing this value is not allowed"라는 문구가 나온다. 이 레지스터는 bit [0]와 bit [7:2]에 이와 같이 적혀있다. 흠.. 구글링을 통해 찾은 여러 예제 코드에는 PLL을 사용하던 하지 않던 bit [0]에 1을 써주고 있다. 이건 왜지? 물어볼 곳이 없다.. 그냥 그렇게 해야지 뭐(좀 더 검색해보니까 어떤 코드는 1을 써주고 어떤 코드는 쓰지 않는다. 흠..??)
아무튼 PLL을 쓰려면 bit [1]은 꼭 1로 써줘야 한다. 여기에 1을 안 쓰면 XVCLK로 들어오는 clock을 PLL을 거치지 않고 바로 사용한다.
3.2 PLL 설정
PLL 관련 레지스터는 0x3034 ~ 0x3037, 0x3039 이렇게 총 5개다. 표로 간단히 정리해보겠다.
Address | register name | default |
0x3034 | SC PLL CONTRL 0 | 0x1A |
0x3035 | SC PLL CONTRL 1 | 0x11 |
0x3036 | SC PLL CONTRL 2 | 0x69 |
0x3037 | SC PLL CONTRL 3 | 0x03 |
0x3039 | SC PLL CONTRL 5 | 0x00 |
3.2.1 SC PLL CONTRL0(0x3034)
Address | register name | default |
0x3034 | SC PLL CONTRL 0 | 0x1A |
기본값은 0x1A로 설정되어 있다.
bit[7] | bit[6] | bit[5] | bit[4] | bit[3] | bit[2] | bit[1] | bit[0] |
bit[6:4] : PLL charge pump control bit[3:0] : MIPI bit mode -> 0x08 : 8-bit mode -> 0x0A : 10-bit mode |
bit [6:4]는 PLL에 charge pump라는 것을 컨트롤해주는 역할을 한다. 이 부분에 대해서는 앞에서도 말했지만 따로 언급하지 않겠다.
3.2.2 SC PLL CONTRL1(0x3035)
Address | register name | default |
0x3035 | SC PLL CONTRL1 | 0x11 |
bit[7] | bit[6] | bit[5] | bit[4] | bit[3] | bit[2] | bit[1] | bit[0] |
bit[7:4] : System clock divider Slow down all clocks bit[3:0] : Scale divider for MIPI MIPI PCLK/SERCLK can be slowed down |
기본값은 0x11이다. 상와 4bit는 system clock의 divider값이고 하위 4bit는 MIPI의 dvider 값으로 보인다. ST, ESP에서 제공하는 드라이버 코드를 모두 확인해본 결과 하위 bit는 0x01로 고정이고, 상위 bit만 변경하는 것으로 보인다. divider의 범위는 상위, 하위 모두 0x00~0x0f 까지다.
0x01 | ((sys_divider & 0x0f) << 4); 이렇게 하면 될 듯하다.
1.2.3 SC PLL CONTRL2(0x3036)
Address | register name | default |
0x3036 | SC PLL CONTRL2 | 0x69 |
bit[7] | bit[6] | bit[5] | bit[4] | bit[3] | bit[2] | bit[1] | bit[0] |
PLL multiplier (4~252) Can be any integer for 4~127 and only even integer for 128~252 |
PLL의 주파수 multiplier 값을 설정한다. 4~127은 모든 값을 사용가능하고, 128부터 252까지는 even integer, 즉 짝수만 사용가능하다.
3.2.4 SC PLL CONTRL3(0x3037)
Address | register name | default |
0x3037 | SC PLL CONTRL3 | 0x03 |
bit[7] | bit[6] | bit[5] | bit[4] | bit[3] | bit[2] | bit[1] | bit[0] |
bit[4] : PLL root divider -> 0x00 : Bypass -> 0x10 : Divided by2 bit[3:0] : PLL pre-divider -> 1, 2, 3, 4, 6, 8 |
PLL의 divider 값을 설정한다.
3.2.4 SC PLL CONTRL5(0x3039)
Address | register name | default |
0x3039 | SC PLL CONTRL5 | 0x00 |
bit[7] | bit[6] | bit[5] | bit[4] | bit[3] | bit[2] | bit[1] | bit[0] |
bit[7] : PLL bypass |
PLL bypass 설정.
PLL을 설정하는 5가지 레지스터를 정리해봤다. PLL은 외부에서 공급된 clock을 IC 전체에 공급하고 제어하는 역할을 하기 때문에 매우 중요하고 반드시 이해하고 넘어가야 한다. 여기서 이해라는 것은 동작 원리가 아니라 계산 방법이다. (ST cube처럼 블록 다이어그램으로 표시되어 있으면 얼마나 좋을까.. 하하) 클럭 계산 방법은 데이터 시트에도 없고, 구글에 떠돌아다니는 Application Note에도 없다. git에 공개된 코드를 찾아봐도 공식은 없다. 레지스터 설정값은 보이지만, 이것만 가지고 뭘 알아낼 수 는 없다 ㅜㅜ 그러던 중.. ESP에서 제공하는 드라이버 소스코드를 찾아보니 나왔다. 정상적으로 동작하는 코드니 믿고 학습해보자!
3.2 clock 계산
클럭 계산이 왜 중요하냐면 화질, 프레임에 따라 클럭을 변경해줘야 하기 때문이다. 즉, 변경하는 방법을 알아야 한다는 것이다. 물론 칩마다 조금 다르겠지만 개념은 할 것이고, 한번 해보면 다른 칩을 사용할 때 조금 더 쉽게 접근할 수 있을 것이다.
화질, 프레임에 따라 clock를 조정해줘야하는데 여기서 말하는 clock 란 이전 포스팅에서 언급한 PCLK(Parallel port output pixel Clock)이다. 여기까지 가는 과정이 좀 복잡하다. (휴 사람들이 포스팅해놓은 것만 보다가 직접 쓰려니까 어렵다. 하 그동안 아무런 대가 없이 남의 지식을 써먹은 것을 반성하자.)
PCLK 공식은 아래와 같다.
PCLK = PLL clk / pclk root divider / PCLK manual
이 공식중 데이터 시트에서 찾을 수 있는 것은 pclk root divider, PCLK manual 이 두 가지다. 이건 우선 넘어가고, 그럼 PLL clk를 알아야겠지? PLL clk 공식은 아래와 같다
PLL clk = VCO / System clock divider * 2 / n
여기서 우리가 알 수 있는 값은 System clock divider와 n의 값이다. 그럼 VCO는? 계산해야겠지? VCO 공식은 아래와 같다.
VCO = MCLK / PLL multiplier / PLL root divider
여기서 MCLK는 XVCLK를 통해 들어오는 main clock이다. 데이터 시트대로 24MHz를 사용한다라는 가정하에 계산한다. PLL의 pre-divider를 2로 설정해 계산하면,
MCLK = XVCLK / PLL pre-divider = 24MHz / 2 = 12MHz
그럼 다시 VCO로 돌아가서 계산해보자. 여기서 PLL multiplier는 10, PLL root divider는 0일 경우와 1경우가 있는데 0 인경우 Bypass이므로 1로 계산, 1이면 Divided by 2이기 때문에 2로 계산한다. 여기서는 0으로 설정해 계산 (위 내용 중 3.2.4 SC PLL CONTRL3(0x3037) 참고)
VCO = MCLK * PLL multiplier / PLL root divider = 12Mhz * 10 / 1 = 120MHz
PLL clk를 계산하기 위해 VCO를 구했으니 이제 PLL clk를 계산해보자. 3.2.4 SC PLL CONTRL5(0x3039) 레지스터의 bit[7]이 1이면 PLL 을 bypass 시키기 때문에 MCLK가 PLL clk가 된다. PLL을 사용하고자 한다면 이부분을 반드시 0으로 설정해야한다. System clock divider 는 1로 설정해 계산한다. (위 내용 중 3.2.2 SC PLL CONTRL1(0x3035) 참고)
아래 식중 2 / n 은 공식에 나와있는 식인대 MIPI bit mode 가 10이면 n=5가되고, 8이면 n=8이 된다.
PLL clk = VCO / System clock divider * 2 / n = 120MHz / 1 * 2 / 5 = 48MHz
마지막으로 PCLK를 계산해보자. PLL clk는 위에서 구했고, pclk root divider는 SYSTEM ROOT DIVIDER 레지스터에서 설정 한다.
Address | register name | default |
0x3108 | SYSTEM ROOT DIVIDER | 0x16 |
bit[7] | bit[6] | bit[5] | bit[4] | bit[3] | bit[2] | bit[1] | bit[0] |
bit[7:6] : Debug mode bit[5:4] : PCLK root divider -> 00 : PCLK = pll_clki -> 01 : PCLK = pll_clki/2 -> 10 : PCLK = pll_clki/4 -> 11 : PCLK = pll_clki/8 bit[3:2] : sclk2x root divider -> 00 : SCLK2x = pll_clki -> 01 : SCLK2x = pll_clki/2 -> 10 : SCLK2x = pll_clki/4 -> 11 : SCLK2x = pll_clki/8 bit[1:0] : SCLK root divider -> 00 : SCLK = pll_clki -> 01 : SCLK = pll_clki/2 -> 10 : SCLK = pll_clki/4 -> 11 : SCLK = pll_clki/8 |
bit[5:4]에서 PCLK에 나누는 값을 설정 할 수 있다. 본 포스팅에서는 01로 설정하도록 하겠다. 또 한가지 변수인 PCLK manual은 VFIFO CTRL0C 레지스터에서 설정 할 수 있다.
Address | register name | default |
0x460C | VFIFO CTRL0C | 0x20 |
bit[7] | bit[6] | bit[5] | bit[4] | bit[3] | bit[2] | bit[1] | bit[0] |
bit[7:4] : JPEG dummy data pad speed bit[2] : Footer disable JPEG footer disable -> 0 : In jpg_mode 2 footer will be added in the last six bytes of each frame -> 1 : Disable footer bit[1] : PCLK manual enable -> 0 : DVP PCLK divider control by auto mode -> 1 : DVP PCLK divider control by 0x3824[4:0] |
PCLK manual을 활성화 시킬경우 0x3824 번지에 있는 값을 DVP PCLK divider의 값으로 쓴다는 내용이다. 본 포스팅에서는 활성화로 설정하고, 0x3824번지의 [4:0]의 값을 2로 설정하도록 하겠다.
PCLK = PLL clk / pclk root divider / PCLK manual = 48MHz / 2 / 2 = 12MHz
흠..ESP의 예제를 보고 따라해봤다. 나중에 실제 카메라 제어를 통해 식이 맞는지 확인해봐야겠다.
다음 포스팅 부터는 ESP32 예제의 ov5640 드라이버 소스코드를 보면서 레지스터와 함께 분석해 나가도록 하겠다.
이번 포스팅은 여기까지. 고생했다.
- 끝 -
'Hardware&Firmware > Sensor(센서)' 카테고리의 다른 글
이미지 센서, OV5640 데이터 시트 리딩 -1 (0) | 2021.10.25 |
---|---|
자이로 센서, MPU6050 -1 (2) | 2021.08.16 |