내 첫 cocoa application: yuv player

저번 주에 개인적으로 de-interlacing 관련된 발표를 준비하느라 논문에 있는 de-interlacing 기법들을 구현해서 실험을 했었는데, 맥에서 돌아가는 yuv player 를 못찾는 바람에 결과는 윈도우로 옮겨서 확인해야하는 불편이 있었다.
랩에 이미 충분히 쓸만한 yuvplayer 가 있기는 하지만 윈도우 전용이고, 내가 예전 신입생 과제를 하면서 만들었던 플레이어 역시 윈도우용;; 뭐 하튼 플레이어를 구현하는데 필요한 기반 테크닉은 다 갖추고 있었기 때문에 MFC + OpenGL 로 구현해봤던 것을 똑같이 Cocoa+OpenGL 로 구현해봤다.

메뉴를 이용해서 size 와 color format, frame rate 등을 준비할 수 있도록 만들었는데, size 와 frame rate 를 사용자가 직접 입력하는 것은 귀찮은 관계로 나중에 -_-;;
뭐 하튼 Zoom 하고 Drag And Drop 과 관련된 코드만 추가하고 나면 내가 구현하고 싶었던 모든 기능이 다 들어가는 거 같다. (Zoom 이야 glPixelZoom 을 사용하면 한방에 오케이니 흐흣)
XCode + Interface Builder 를 이용한 첫 결과물인데, 굉장히 오래전에 이미 나와있던 프로그래밍 인터페이스인데도 불구하고 굉장히 편리하게 프로그래밍이 가능해서 감탄을 해버렸다. 물론 MS 진영도 Visual Studio 2005 로 오면서 편리한 기능들이 꽤 많이 추가되긴 했지만, GUI Application 을 만들기 위한 IDE 로는 XCode + 인터페이스 빌더 쪽이 한 수 위인 듯…
MFC 나 Cocoa 나 진입 장벽이 꽤 높지만… 기본적인 테크닉을 익히고 나면 굉장히 강력하게 사용이 가능한 것 같다. 그리고 C 에 능숙하다면 다른 언어를 접하는 데도 그리 큰 어려움을 느끼지 않는 것 같다. 학부 시절 C++, Java 등에 눈길을 뺐기지 않고 주력 언어로 C 를 선택했던 게 탁월한 선택이었던 듯…
p.s) 코드를 좀 정리하고 sourceforge 등에 자리를 틀어볼까 싶네요. 🙂

처음 짜본 wavelet transform…

화상처리기초 수업 과제 때문에 처음으로 wavelet transform 을 구현해보았습니다. 아래 이미지는 wavelet 으로 변환된 512×512 사이즈의 lena


histogram 을 보면, 값들이 낮은 값들로 집중되어 있는걸 확인할 수 있습니다. 역시 이미지 압축을 위해 사용할만 하네요. 😉

matrix multiply with mmx #2


대강 생각을 해보니 정말 mmx 를 이용해서 빠르게 연산을 하려면 위와 같이 하는게 가장 빠르겠군요. 다만 레지스터를 많이 쓰고 완전히 asm 코딩을 해야한다는 게 조금 귀찮겠군요. 😉
위의 다이아그램에 있는 과정을 통해 4×4 matrix * 4×4 matrix 의 한 row 씩을 계산해낼 수 있습니다. 대강 계산했을 때 3배 이상의 속도 향상이 있을거라고 예상되던데 과연~

코드로 옮기니 위와 같군요. 중간에 실수로 바이트오더를 헷갈려서 연산 결과가 뒤집혔었습니다. 정상적인 결과는 250 260 270 280 이 나와야 하는데 280 270 260 250 이 나와버리더군요. 아아 이거 다시 하고 싶은 작업이 아니네요;
흐흣 그래도 오랫만에 어셈블리 관련된 것들을 생각하고 있는데, 이것도 가끔 하니까 재밌네요. 근데 길어지면 할만하지 않다는거 -_-!
p.s) 전체 연산 코드를 보고 싶으시면 http://mytears.org/resources/mysrc/c/mmx.c 를 보시길 😉

matrix multiply with mmx #1

몇 일 전에 썼던 글에서 테스트를 해본 내용을 바탕으로 4×4 matrix multiply 연산을 mmx 를 이용해서 구현해봤습니다.

위와 같은 c version 의 코드를 작성한 후 아래와 같은 asm version 으로 컨버팅을 해봤는데, 100000 번 반복해서 연산을 하도록 해본 결과 mmx 버젼이 c 버젼보다 3배 정도 빠르게 연산을 하는 것을 확인할 수 있었습니다. (-O0 옵션과 함께 컴파일 했을 경우)
하지만 -O3 옵션과 함께 컴파일하게 되면 asm 버젼은 무한룹에 빠진 듯한 모습을 보여줬고, c 버젼의 수행속도가 -O0 로 컴파일한 asm 버젼보다 빠른 현상이 발생했습니다. 이유는 알 수 없음 -_-;

8×8 matrix 는 뭔가 좀 더 생각해야할 것 같으니 나중에 정말 필요한 일 있을 때 구현을 해봐야겠습니다. -_-;
inline asm 작업을 하면서 eax 레지스터 값을 백업하지 않고 저렇게 사용해도 되는지는 잘 모르겠지만 –;; 하여튼 저 코드에 한해서는 별 문제 없으니 패스~ 꺄홋!!

mmx

요새 matrix 연산을 이용한 프로그램 조각 몇 가지를 짜보고 있는데, mmx 같은 SIMD instruction 을 사용하면 matrix 연산의 속도를 확 올릴 수 있지 않을까 싶은 생각이 들길래 inline asm 을 이용해서 간단한 mmx 코드를 만들어보았습니다.

위와 같은 코드를 작성하고, gcc mmx.c 를 통해 컴파일해서 돌려보니 간단히 성공 -_-v
c 코드를 사용할 경우 s1[0] load, s2[0] load, multiply, save to d[0] 와 같은 인스트럭션을 네 번 반복해서 실행하는 반면 mmx 를 사용할 경우 movq 를 통해 연속된 WORD 네 개를 mmx register 로 복사하고, pmullw 를 이용 4 개의 값을 한 인스트럭션에 연산을 하는 것을 통해 속도를 확 끌어올릴 수 있는거죠. 😉
다만 헷갈리는게 인텔의 메뉴얼에 나와있는 인자 순서와, AT&T 방식이 달라서 좀 헷갈리는군요.

  • Intel: movq mm0, [s1]
  • AT&T: movq (s1), %mm0

Intel 메뉴얼에서 설명하는 바에 의하면 첫번째 operland 가 destination 이 되고, 두번째 operland 가 destination 이 되는 반면 AT&T 방식에서는 거꾸로 첫번째 operland 가 src, 두번째 operland 가 dst 가 됩니다.
또한 주소값을 넘겨줄 때 intel 방식은 [] 로 감싸주면 되지만, AT&T 에서는 () 로 감싸줘야하고, 레지스터 이름 앞에 %를 붙여줘야 하는 규칙도 있어서 뭔가 대빵 귀찮네요. -_-;
참고로 gcc 에서 -masm=intel 옵션을 사용하면 intel 방식으로 어셈블리 명령어를 작성하는 것도 가능합니다.
p.s) movq 는 4개의 WORD 를 mmx register 로 복사하는 명령인데 –;; mm0 ~ mm7 식으로 64bit register name 을 써줘야 하는데 xmm0~xmm7 같은 sse 용 register 이름을 쓰는 바람에 잘못된 인스트럭션 사용이라고 계속 에러가나서 한참 헤맸네요;

avr gadget

몇 일전에 만들었던 avr 로 만든 장난감의 회로도와 소스코드를 공개합니다. 🙂
회로도:
http://mytears.org/resources/avr/gadget/avr-gadget-circuit.png
소스코드:
http://mytears.org/resources/avr/gadget/avr-gadget.c
결과물:
http://mytears.org/tmp/dir/?path=./avr&N
회로에서 Vcc 라고 되어있는 부분에 2.7V ~ 5.5V 사이로 연결을 해주면 되며, 회로에는 나와있지 않지만 10번 핀은 Ground 에 연결해줘야만 합니다. 또한 Vcc 에 3V 를 연결하게 될 경우 L.E.D 에 저항은 연결할 필요가 없습니다. (330옴은 5V 기준)
프로그램을 간단하게 설명하자면 8bit timer 를 사용했고, timer 에 overflow 가 발생할 때 (0xFF 에서 0x00 으로 넘어가게 되면) 생기는 ovf 인터럽트를 이용하고 있습니다.
처음엔 at90s2313 을 사용했었는데 불행히도 가지고 있는 at90s2313 중 하나는 다리가 부러져서 사망해버렸고, 나머지 하나는 뻘짓하다가 태워먹어버린고로 현재 소스코드는 attiny2313 용으로 작성되어 있습니다. (두 칩은 핀 배열등 대부분이 비슷하지만 ovf 인터럽트와 timer 관련 레지스터 이름이 살짝 다릅니다.)
인터럽트 테스트 코드:
http://mytears.org/resources/avr/interrupt-test/int-test.c
p.s) 결국 하나 남은 attiny2313 마저 장렬하게 전사… 프로젝트 검사를 아직 안받은고로 추가 주문 해야했다.
오늘의 교훈: 겁 없이 7805 를 믿고 15v 아답타에 연결하지 말자 -_-;;

AVR-ISP

오랫만에 AVR 을 가지고 노니까 재밌길래 범용으로 쓸 수 있을만한 AVR-ISP 를 만들었습니다. 40pin ZIF 소켓을 사용해서 쉽게 칩을 꼈다뺐다할 수 있도록 만들었고, pin header 를 이용해서 Vcc, GND, RESET, SCK, MISO, MOSI, XTAL1, XTAL2 등을 칩에 맞게 연결할 수 있도록 만들어놓았습니다.


이 칩 저 칩을 구울라면 점퍼 세팅을 다시 해줘야 하지만, 뭐 그래도 빵판에 꼽아놓고 구울 때에 비하면 훨씬 편해진 것 같습니다. 하지만 마이크로마우스 같은 계속적인 디버깅 / 개선을 해야하는 것을 만든다면 아예 보드에 ISP 와 연결할 수 있는 인터페이스를 갖춰놓는 것이 훨씬 효율적일 거 같네요. 칩을 뺐다꼈다하는것도 은근히 귀찮아요. -_-;
부품 리스트: 40 pin ZIF socket, 40pin pin header, box connector, 4Mhz crystal, 10uF capacitor, 100nF capacitor, 30pf capacitor * 2, diode bridge, LM7805, 330옴 array register, red L.E.D (전원 확인용), green L.E.D (다운로딩 상태 확인용)
p.s) 제가 처음 접했던 8051 계열의 경우도 AT89S51 등의 ISP 가 지원되는 칩이 있었네요.

AVR

실험(4) 과목 때문에 스트레스가 여간이 아닙니다. 중간고사 평균이 8점이었고, 중간 + 기말 + Report 점수를 합산한게 70점을 넘지 않으면 F 를 주시겠다는군요. 문제는 이 과목이 전공 필수이고, 전 요번학기가 마지막이어야만 한다는 거죠.
하여튼 그런 이유로 추가 점수를 받기 위해 오랫만에 AVR 을 만져야 했습니다. AVR 은 ATMEL 에서 만든 MCU 로 ISP 인터페이스를 갖추고 있어서 복잡한 롬라이터를 만들지 않고도 간단하게 프로그램을 구울 수 있습니다.
빵판에 구성한 AVR ISP
실험(4) 시간에 atmega128 과 관련 보드 / ISP 가 지급이 되었지만, 뗌질을 하다가 칩을 태워먹은건지 아님 어딘가 뗌질이 잘못된건지 하여튼 작동하지를 않더군요. 어쩔 수 없이 예전에 사두었던 AT90S2313 을 이용하기로 마음을 먹고 위의 사진처럼 빵판에 회로를 구성했습니다. 보기엔 좀 그렇지만 하여튼 작동은 잘 하는군요. 후훗
AVR 을 이용한 자판기 에뮬레이터
결국 두 시간동안 열혈 뗌질을 한 끝에 위와 같은 최종 결과물을 만들어냈습니다. I/O 가 모잘라서 500원 투입 버튼은 만들지 않았지만, 그걸 제외하면 구현해야 하는 스펙은 모조리 구현해놓았습니다.
모처럼 오랫만에 mcu 를 가지고 놀았더니 재밌네요. 필받은 김에 아래와 같은걸 추가로 뗌질해봤습니다.
이 회로는 뭘까요~?
예전에 홍익대학교 전자전기공학부 학회인 유레카에서 유행했던 겁니다 😉 축제 때 팔기도 했던걸로 알고 있는데… 뭐 하여튼 L.E.D 에 저항연결하기도 귀찮고, 전원을 따로 입력받기도 귀찮고 해서 3V 로 동작하게 만들어버렸습니다.
아래 사진은 밤에 불을 다 꺼놓고 노출을 1s 로 해놓은 뒤 위 회로를 살짝 흔들어준 모습입니다. 메시지를 길게 넣을 수도 있지만 그 노가다가 귀찮아서 -_-;
잔상으로 그려진 스마일 마크
위 회로를 업그레이드 해서 ^_^, -_-, T.T, 하트 등을 그릴 수 있도록 업데이트 했습니다. 결과물을 보시려면 아래 url 로 😉
http://mytears.org/tmp/dir/?path=./avr&N
p.s) 참고로 AVR 을 굽기 위해선 MISO / MOSI / SCK / RESET (ISP 에서 입력을 받습니다.), VCC, GND 그리고 XTAL1, XTAL2 (크리스탈) 정도만 연결해주면 됩니다. 예전에 VCC, GND 등은 패러랠 포트에서 들어오는 건 줄 알고 삽질한 기억이 나서;;;

새 백업 스크립트…

예전 스크립트에서는 그냥 특정 사용자에 한해서 백업을 하도록 하고 있었습니다. 하지만 백업의 중요성을 절실히 느끼게 되서, 요번엔 사용자의 계정 사용량을 체크해서 1기가 미만으로 사용을 하고 있다면 자동으로 백업을 하도록 만들었습니다.

또한 ls 와 head, tmpwatch 를 이용해서 백업본이 최신 2 개만이 유지되도록 만들어놓았습니다. 만약 타르볼로 묶는데 1시간 이상 걸리는 용량을 아카이빙 하면 문제가 될 수 있습니다. –;