2010년 4월 24일 토요일

유니버셜 디자인

< 유니버셜 디자인 >

 

1. 개념

  • Design for all people
  • 유니버셜 디자인은 "평생 디자인"이라고도 부르는 디자인계의 최신 주제(2010.4.)
  • 장애인, 노인, 어린이 등 약자가 사용할 수 있는 환경과 상품 창조를 만드는 디자인을 말하고, 신체적인 약함뿐 아니라 상황이나 나이에 따라 일어날 수 있는 특정 부분의 불리한 점을 보완하는 것이 "유니버셜 디자인"이다.
  • '더 편하게, 더 안전하게, 더 풍요롭게'를 외치는 소비자 중심의 생활 디자인이 지금 세계 디자이너가 추구하는 디자인의 중심이다.

 

2. 배경

  • 20세기 들어서 장애인, 고령자 등이 늘면서, 그들이 일상 생활을 자유롭게 보낼 수 있는 베리어 프리(barrier free) 개념이 등장했다.
  • 1980년 미국의 건축가이자 공업 디자이너인 론 메이스는 베리어 프리 개념을 뛰어넘는 남녀노소 누구나 사는데 불편함이 없는 디자인을 해야한다고 주장했고, 이 때 유니버셜 디자인이라는 개념이 생겨났다.
  • 유니버셜 디자인은 장애의 개념을 좀더 넓힌 디자인으로 정상인뿐 아니라 일시적 장애를 포함한 모든 장애를 어린이와 노인이 사용할 수 있는 환경과 상품창조를 추구하고, 이론적으로 생각하는 신체적 능력의 부족함만이 아니라, 상황이나 나이에 따라 모든 사람이 가지고 있는 특정부분의 취약성 모두를 장애의 개념으로 본다.

 

3. 원리

  • 기능적 자원성이 높은 디자인(Supportive Design)
    • 기능상 필요한 도움을 제공해야 하며 사용자에게 불필요한 어떤 부담도 야기시켜서는 안된다. 조명의 경우 밝기가 적절치 않으면 시각의 정확성이 떨어지며
  • 수용가능한 디자인(Adaptable Design)
    • 상품이나 환경이 상황에 따라 조절가능함으로써 다양한 요구를 충족시킬 수 있는 유통성을 지녀야 한다. 특히 오랜 시간 다양한 형태로 작업하는 사무환경에서는 인간공학적인 방법으로 이러한 특성의 디자인이 연구되어야 한다.
    • 변화 가능한 형태의 작업대나 높이조절이 가능한 책상과 스탠드, 다양한 서체와 글자의 크기조절이 가능한 컴퓨터 프로그램들이 이러한 사례이다.
    • 이러한 상품은 시각장애자와 노인들에게도 매우 유용하다.
  • 접근 가능한 디자인(Accessible Design)
    • 접근 가능성이란 장애물이 제거된 상태이다.
    • 보도블럭을 휠체어 사용자와 자전거를 타는 사람, 환자들이 편리하게 다닐 수 있도록 고려하고 아울러 시각장애자들에게도 도움이 되도록 색채와 패턴, 적절한 배치와 질감있는 재료를 사용해 시각장애로 인한 사고를 가능한 줄이는 것 등이 이러한 것들이다.
  • 안전한 디자인(Safely-oriental Design)
    • 대조적인 색채와 패턴으로 레벨차를 표시하거나 모서리를 둥글게 처리한 것 등 안전한 디자인은 보다 개성적이며 예반적이다. 또한 안전성은 심리적인 건강함, 소속감, 자기가치등을 포함한다.
    • 장애자가 정상정적인 활동을 유지할 수 있도록 고려된 공간은 개인에게 도립심을 부여함으로써 심리적인 건강을 유지시켜 준다.

 

 

< 7가지 원칙 >

  • 공평한 사용(Equitable)
    • 누구라도 차별감이나 불안감, 열등감을 느끼지 않고 공평하게 사용 가능한가?
  • 사용상의 융통성(Flexiblility in Use)
    • 서두르거나, 다양한 생활환경 조건에서도 정확하고 자유롭게 사용 가능한가?
  • 간단하고 직관적인 사용(Simple and Intutive)
    • 직감적으로 사용방법을 간단히 알 수 있도록 간결하고, 사용 시 피드백이 있는가?
  • 쉽게 인지할 수 있는 정보(Perceptive Information)
    • 정보구조가 간단하고, 복수의 전달수단을 통해 정보입수가 가능한가?
  • 오류에 대한 포용력(Tolerance for Error)
    • 사고를 방지하고, 잘못된 명령에도 원래 상태로 쉽게 복귀가 가능한가?
  • 적은 물리적 노력(Low Physical Effort)
    • 무의미한 반복동작이나, 무리한 힘을 들이지 않고 자연스런 자세로 사용이 가능한가?
  • 접근과 사용을 위한 충분한 공간(Size and Space for Approach and Use)
    • 이동이나 수납이 용이하고, 다양한 신체조건의 사용자와 도우미가 함께 사용이 가능한가?

 

 이와 같은 유니버셜 디자인은 제품이나 환경시설 외에 모든 산업을 대상으로 할 만큼 대단히 광범위하며, 근래 고령화의 급진전에 따른 고령친화산업(실버산업)의 부각은 기업에 있어서 새로운 비즈니스 창출 및 참여라는 기회를 제공하고 있습니다. 본격적인 고령사회의 도래와 와 국제화, 정보통신기술의 고도화 등에 동반하여 사회, 경제구조의 변혁, 가치관의 다양화 등이 한층 진전될 것으로 예측되는 향후 사회에 있어서 유니버셜 디자인은 더불어 사는 사회를 형성해가기 위해 필연적인 대안이라고 할 수 있습니다.

 

 

출처 : Our Blog, UDRC 유니버셜 디자인 연구센터

2010년 4월 20일 화요일

Qt4를 이용한 C++ GUI 프로그래밍-Chapter 01

(1) Hello Qt

  • 예제

1 #include <QApplication>
2 #include <QLabel>

3 int main(int argc, char *argv[])
4 {
5     QApplication app(argc, argv);
6     QLabel *label = new QLabel("Hello Qt!");
7     label->show();
8     return app.exec();
9 }

  • Qt의 모든 클래스는 자신의 이름과 똑같은 이름으로 된 헤더파일 내에 정의되어 있다.
  • 5번째 줄 : 응용 프로그램 차원의 자원을 관리하기 위해 QApplication 객체를 생성한다.
    • QApplication은 GUI 응용 프로그램 제어 흐름과 주요 설정 사항을 관리하는 클래스로서, 메인 이벤트 루프를 갖고 있으며, 응용 프로그램의 초기화와 종료화 그리고 시스템 차원의 설정사항과 응용 프로그램 차원의 설정사항을 다룬다.
    • Qt를 사용하는 GUI 응용 프로그램에는 하나의 QApplication 객체만이 존재할 수 있으며, 전역 포인터인 qApp 나 QCoreApplication::instance()를 통해 이 객체에 접근할 수 있다.(자세한 것은 Qt 어시스턴트 참조)
  • 명령행으로부터 입력되는 인자 중에서 Qt가 자체적으로 인식하는 것이 있기 때문에, QApplication을 생성할 때는 생성자에 argc와 argv를 넘겨줘야 한다.
  • 6번째 줄 : "Hello Qt"라는 문자열을 출력하는 QLabel 위젯을 생성하고 있다.
  • Qt와 유닉스에서 통용되는 위젯(Widget)이란 용어는 유저 인터페이스 상에 자리잡은 각각의 비주얼한 요소를 일컫는 말이다. '윈도우 가젯'이란 말에서 유래된 이 용어는, 윈도우에서 사용되는 용어인 '컨트롤'이나 '컨테이너'와 그 의미하는 바가 동일한데, 이를 테면 버튼, 메뉴, 스크롤 바, 프레임 등이 바로 위젯인 것이다. 하지만 Qt는 어떠한 위젯이라도 윈도우가 될 수 있다는 특징이 있다.
  • 7번째 줄 : 이 레이블이 화면에 보이게 만들고 있다. 모든 위젯은 항상 화면에 보이지 않는 상태로 생성되는데, 이러한 방침은 화면에 보이기 이전에 위젯에 필요한 모든 조치가 취해질 수 있게 하기 위한 것으로서, 이를 통해 불필요한 화면의  깜빡임을 막을 수 있게 된다.(화면 깜빡임의 다른 방법은 더블 버퍼링으로 5장에서 다룬다.)
  • 8번 줄 : 응용 프로그램의 제어를 Qt에게 넘겨주고 있다. 이렇게 되면 프로그램은 마우스 클릭이나 키보드 입력과 같은 사용자의 액션을 기다리는 일종의 대기모드인 이벤트 루프에 진입하게 된다. 사용자의 액션은 이벤트('메시지'라고도 함)를 발생시키게 되는데, 프로그램은 보통 이러한 이벤트에 대해 몇 가지 함수를 실행함으로써 반응하게 된다. 예를 들어, 사용자가 어떤 위젯을 클릭하면 '마우스 버튼의 누름'과 '마우스 버튼의 뗌'을 의미하는 이벤트가 생성된다.
  • main() 함수의 끝부분에서는 좀 더 간략함을 위해 QLabel 객체에 대한 delete 호출을 생략하고 있다. 프로그램이 종료되면 운영체제는 그 프로그램이 사용한 모든 메모리를 회수하기 때문에, 이 정도 크기의 작은 프로그램에서 발생하는 메모리 누수는 아무런 해가 되지 않는다.
  • 프로그램을 실행시키려면 먼저 컴퓨터에 Qt 4.3.2이상의 Qt 4가 설치되어 있어야 함.
  • 그리고 Qt의 bin 디렉토리가 PATH 환경변수에 설정되어 있어야 함.(부록 A 참조, 윈도우는 Qt 설치시 자동으로 등록됨.)
    • 1 # vi hello.cpp
      2 # qmake -project
      3 # qmake hello.pro
      4 # make
      5 # ./hello
    • 1 : chapter01의 hello 예제 파일 소스임.
    • 2 : 플랫폼에 독립적인 프로젝트 파일(hello.pro)이 생성됨.
    • 3 : 이전 단계에서 생성된 플랫폼 독립적인 프로젝트 파일로부터 특정 플랫폼을 위한 makefile이 생성됨.
    • 4 : 프로그램이 만들어 진다.
    • 5 : 만들어진 프로그램을 실행

 

  • ### 윈도우 비쥬얼 스튜디오 프로젝트 파일 만드는 법 ###
    • # qmake -tp vc hello.pro

 

 

(2) Signal / Slot

  • 시그널은 함수와 연결될 수 있어서, 시그널이 발생하면 그와 연결된 함수가 자동으로 실행되는데, 이처럼 시그널의 발생에 의해 자동으로 호출되는 함수를 슬롯이라고 한다.
  • SIGNAL()과 SLOT()은 시그널과 슬롯을 연결하는 데 사용하는 매크로이다.
  • ex) QObject::connect( button, SIGNAL(clicked()), &app, SLOT(quit()));

 

(3) Widget

  • QWidget은 어떤 응용프로그램의 메인 윈도우가 될 수 있다.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         

 

 

(4) Reference Document

 

 

end

2010년 4월 19일 월요일

Qt4를 이용한 C++ GUI 프로그래밍-시작하기

* Qt(큐트)

  • 소스 코드 한 벌만으로 다양한 운영체제 환경에서 실행 가능한 어플리케이션을 만들 수 있도록 해주는 크로스 플랫폼 응용프로그램 프레임워크
  • 노르웨이에 있는 트롤테크에서 처음 개발되었고, 2008년 노키아가 인수하여 현재 모바일 및 데스크톱 소프트웨어에 관한 노키아의 플랫폼 소프트웨어 전략의 핵심 역할을 하고 있음.(2008년?)
  • Write Once, Compile Anywhere : 소스 코드는 한 벌만 만들고 이를 원하는 운영체제 환경에서 컴파일하기만 하면 해당 환경에서 실행될 수 있는 이미지가 만들어진다.(윈도우, 리눅스, 맥 OS 지원, 임베디드 리눅스, 윈도우 CE 지원)
  • Qt로 만들어진 제품들 : 구글 어스, 얻도비 포토샵 앨범, 스카이프, 메스메티카,  KDE, KOffice
  • 오픈 소스로 배포되고 있음

 

* Qt 라이선스

  • 오픈 소스 에디션
    • GNU GPL 사용에 대한 요구사항이 포함됨
    • 소스를 보고, 수정하고, 배포하는 권리를 부여함.
  • 상용 에디션
    • 만든 응용 프로그램을 상용 라이선스 조건을 적용하고자 할 경우 사용
    • 자신만의 조건 하에 판매하고 배포할 수 있음.

 

* Qt 설치하기(부록 A)

  • Qt 다운로드 하기
  • 책 예제 다운 받기
  • Qt/윈도우 설치(MinGW C++ 설치 필수)
  • Qt/맥 설치(Xcode Tools 먼저 설치 필수)
  • Qt/X11 설치
    • # cd /tmp
    • # gunzip qt-x11-opensource-src-4.3.2.tar.gz
    • # tar xvf qt-x11-opensource-src-4.3.2.tar
    • # cd /tmp/qt-x11-opensource-src-4.3.2
    • # ./configure
    • # make
    • # make install or sudo make install
    • 환경 변수 설정(.profile)
      PATH=/usr/local/Trolltech/Qt-4.3.2/bin:$PATH
      export PATH

 

2010년 4월 14일 수요일

linux 2.6 device model

* 5 component for device model

  • the device model core -> defines a set of structures and functions
    • 'include/linux/device.h', 'drivers/base/*.c'
  • the generic bus drivers
    • bus / struct bus_type / bus_register(), bus_unregister()
  • the bus  controller drivers
    • device / struct device / device_register(), device_unregister()
  • the device drivers
    • driver / sturce device_driver / driver_register(), driver_unregister()
  • the class drivers
    • class / struct class / class_register(), class_unregister()

 

* Device Model Core

  • 'struct bus_type' : Represents busses(PCI, USB, I2C, etc.)
  • 'struct device' : Represents devices(Intel AC97 audio controller, Intel PRO/100 ethernet controller, a PS/2 mouse, etc.)
  • 'struct device_driver' : Represents kernel drivers that handle devices
  • 'struct class ' : Represents a class of devices(sound, input, graphics, etc.)
  • 'include/linux/device.h', 'drivers/base/*.c'

 

* device_register() : 한 device에 대해 맞는 driver들을 검색

* driver_register() : 한 driver에 대해 맞는 device들을 검색

 

* Generic Bus Drivers

  • kernel이 지원하는 모든 bus마다 generic bus driver가 있다. Generic bus driver는 sturct bus_type을 allocate하고 bus_register()를 써서 kernel의 bus type list에 register한다.
  • bus_type structure
    • name (string)
    • !klist_devices (klist)
    • !klist_driver (klist)
    • match (fp)
    • suspend (fp)
    • resume (fp)
  • klist_devices는 이 bus에 존재하는 device들의 list, Bus controller driver가 device_register()를 호출함에 의해 update 됨.
  • Bus controller driver는 system initialization 시 bus를 scan해서 어떤 device들이 있는지 check한 뒤 각 device마다 device_register()를 호출해서 klist_devices를 scan해서 맞는 driver (match() 이용)를 찾는다. 그런 뒤 device를 klist_devices에 update한다.
  • Bus controller driver는 또한 gadget이 hot plugged 되었을 때(어떤 device인지 확인한 뒤) device_register()를 호출해서 klist_drivers를 scan해서 각 device 마다 맞는 driver( match() 이용 )를 찾는다. 그런뒤 device를 klist_devices에 update 한다.
  • klist_driver는 이 bus에 존재하는 device들을 handle할 수 있는 driver들의 list, Device driver가 스스로 initialization 할 때, driver_register()를 호출하여 자신을 등록함으로써 갱신된다.
  • Device Driver가 kernel에 inserted 되면, 이 driver는 driver_register()를 호출하여 해당 bus에 대해 klist_devices를 scan하여 이 driver가 다룰 수 있는 device들을 찾는다. 그런 뒤 driver를 klist_drivers에 update 한다.
  • match()에 의해 device와 driver가 associated 되는 것을 binding이라고 한다.
  • ex) 'drivers/net/phy/mdio_bus.c'
  • struct bus_type mdio_bus_type = {
    . name = "mdio_bus",
    .match = mdio_bus_match,
    .suspend = mdio_bus_suspend,
    .resume = mdio_bus_resume,
    };

 

* '!' is internal to the device motel core and should not be touched by the bus controller driver directly.

 

* Bus Controller Drivers

  • Bus의 device driver다. 따라서, 여느 device drivers와 마찬가지로 자신을 driver_register()로 등록함. 그러나 추가적으로 자신이 다루는 bus 상에 있는 devices를 detect하여 device_register()를 이용해 등록한다. bus_type 구조체의 klist_devices list에.
  • 새로운 Linux device driver model에서 모든 device는 bus 상에 존재하므로, 결국 bus controller driver가 모든 device를 등록한다. struct device 형태로. bus_type 구조체의 klist_devices list에.
  • device
    • bus_id (string)
    • bus (bus_type)
    • parent (device)
    • !driver(device_driver)
  • 'drivers/net/gianfar_mii.c'

 

* Device Drivers

  • 모든 device driver는, driver_register()를 호출해 bus_type 구조체의 klist_driver list에 자기 자신을 등록한다. 그 다음에 device model core가 이 driver를 한 device와 binding을 시도함.
  • 한 device가 registered 되면 (이는 곧 이 device를 handle할 수 있는 drivers가 klist_drivers에 등록된다는 말이므로) 한 특정 driver에 의해 handled 될 수 있는데, 그 driver의 probe member가 하는 일이 바로 그 특정 device 하나를 위해 이 driver의 한 instance를 생성해내는 (그리고 그 device를 초기화하는) 일이다.
  • device_driver
    • bus (bus_type)
    • probe (fp)
    • remove (fp)
    • suspend (fp)
    • resume (fp)
  • bus는 이 driver가 등록될 klist_drivers를 가진 bus_type 구조체에 대한 pointer.
  • probe는, 이 driver가 지원하는 device가 detected (이는 곧 device를 지원하는 drivers를 klist_drivers에서 찾아내는 일을 한 것 즉, binded) 될 때마다 불리는 callback function. 이 함수는 driver 자신을 각 device 당 하나 씩 instantiate한 뒤 그 device를 initialize 한다.
  • remove는 이 driver를 그 device로부터 unbind하기 위해 불리는 callback function. Unbinding은 device가 physically removed 되거나 driver가 unloaded 되거나 system이 shutdown 될 때 일어난다.
  • 'drivers/net/phy/'

 

* Class Drivers

  • Class driver는 그것이 표현하는 device class들에 대해 struct class를 instantiate하여  class_register()를 통해 device model core에 등록한다.
  • Devices를 적당한 class에 추가하는 것은 각 해당 device driver의 책임이다.
  • class
    • name (string)
    • !devices (list)
  • devices는 이 class에 속한 device들의 list이다. 이 list는 device driver들에 의해 갱신된다. (그 device driver들이 자기 자신들을 각 device들에 대해 instantiate할 때).

 

* Conclusion

  • 결국 이런 data structure들이 있음으로 해서, device들이 어떻게 tree 구조를 이루고 있는지 알 수 있고, 어떤 종류의 device들이 system에 존재하는지도 알 수 있다.
  • 그 효과는 더 나은 power management, 그리고 system에 연결된 devices에 대한 더 나은 통찰.

 

출처 : 블로그

 

 

I2C

I2C(Inter-Integrated Circuit,아이 스퀘어 씨)

  • 필립스에서 개발한 직렬 컴퓨터 버스
  • 마더보드, 임베디드 시스템, 휴대전화 등에 저속의 주변 기기를 연결하기 위해 사용됨.
  • I2C는 풀업 저항이 연결된 직렬 데이터(SDA)와 직렬 클럭(SCL)이라는 두 개의 양방향 오픈 컬렉터 라인을 사용한다. 최대 전압은 +5V이며, 일반적으로 +3.3V 시스템이 사용되지만 다른 전압도 가능하다.
  • I2C 레퍼런스 디자인은 7bit의 주소 공간을 가지며, 이 중 16개는 예약되어 있으므로, 동일한 버스에 최대 112개의 노드를 연결할 수 있다. 가장 일반적으로 사용되는 I2C 버스의 모드는 표준 모드인 100kbit/s와 저속 모드인 10kbit/s가 사용된다. 최신 리비전의 I2C는 보다 빠르게 동작하며, fast mode인 400kbit/s와 고속 모드인 3.4Mbit/s를 지원한다. 최대 1008 노드까지 연결 가능한 10bit 주소 지정 등의 확장된 기능등을 지원한다.
  • 응용 영역
    • 사용자 설정값을 저장하기 위해 NVRAM에 접근하는 경우
    • 저속의 디지털-아날로그 변환 회로에 접근하는 경우
    • 저속의 아날로그-디지털 변환 회로에 접근하는 경우
    • 모니터의 명암, 대비, 색상 등을 변경하는 경우
    • 지능형 스피커의 볼륨값을 변경하는 경우
    • 휴대전화 같은 장치에 포함된 발광 다이오드를 제어하는 경우
    • 중앙 처리 장치 온도나 팬 속도와 같은 하드웨어 모니터링 정보나 진단 센서 정보를 읽는 경우
    • 실시간 클럭 값을 읽는 경우
    • 시스템 요소의 전원을 제어하는 경우
  • I2C의 장점은 특히 마이크로컨트롤러에서 단지 2개의 일반 목적 입출력 핀(GPIO)과 소프트웨어만을 이용하여 여러 장치들을 제어할 수 있다는 점이다
  • 주변장치들은 시스템이 동작 중일 때도 I2C 버스에 추가/제거될 수 있으며, 이것은 핫 스왑이 필요한 요소들을 이용하는 응용에 적합하다.
  • I2C는 엑세스 버스, VESA 디스플레이 데이터 채널 (DDC) 인터페이스, 시스템 과리 버스(SMBus), IPMI 프로토콜 중의 하나인 지능형 플랫폼 관리 버스(IPMB)의 기본 기술이다. 이러한 것들은 전압과 클럭 주파수 범위에서 차이가 있으며, 인터럽트 라인을 가질 수 있다.
  • I2C 버스의 설계상 장점 : 노이즈에 강하여 신뢰성이 높고, 매우 적은 전력을 사용하며, 다양한 온다환경에서도 잘 동작할 뿐만 아니라, 다양한 전압레벨을 지원한다.

 

* I2C에서 ACK의 역할

  • Write 시 정상 수신 신호
  • Read 시 송신 완료 신호
  • Write, Read 모두 ACK 신호는 Slave에서 발생시킴

 

* I2C의 정의

  • 1980년대 필립스에서 개발된 버스 표준안
  • 2개의 전송 라인을 이용한 양방향 통신 지원(SDA, SCL)
  • 현재 세계에서 가장 많이 쓰이는 임베디드 표준안
  • Multi-master capable bus with arbitration feature
  • Master-Slave communication supported
  • Each IC on the bus is identified by its own address code

 

* I2C의 장점

  • 단순한 하드웨어 구성
  • 단순한 프로토콜로 구성
  • 장치의 연결과 제거가 용이함
  • Simpler PCB
  • Fast enough for all "Human Interfaces" applications(Display, Switches, Keyboard)
  • Large number of I2C devices

 

* I2C Signals

 (1) Control Signal

  • SCL highdptj SDA transition으로 판정
  • Start / Stop bit
    • Start : SDA low 이동 후 SCL low 이동
    • Stop : SCL high 이동 후 SDA high 이동

 (2) Data Signal

  • SCL이 pulse 안에서 SDA 데이터의 이동으로 0/1 구분
  • SCL pulse 안에서...
    • SDA pulse 존재하면 : 1
    • SDA pulse 존재하지 않으면 : 0

 (3) ACK / NAK Signal

  • 9번째 data 신호로 판명
    • ACK : 0
    • NAK : 1

 

 

The image shows a simplified equivalent circuit diagram for an I2C connection between two devices (master or slave). It shows all factors which are relevant for I2C.

 

VCC I2C supply voltage, typically ranging from 1.2 V to 5.5 V
GND Common ground
SDA Serial data (I2C data line)
SCL Serial clock (I2C clock line)
Rp Pull-up resistance (a.k.a. I2C termination)
Rs Serial resistance
Cp Wire capacitance
Cc Cross channel capacitance

 

 

출처 : 위키 백과, 다음 블로그, 네이버 블로그, I2C bus(영문)

2010년 4월 13일 화요일

latency

latency : 지연 (또는 대기) 시간

 

1. 네트워크에서의 latency는 delay와 비슷한 말로서, 하나의 데이터 패킷을 한 지점에서 다른 지점으로 보내는데 소요되는 시간을 표현한 것이다. 그러나 일부에서는 (예를 들어 AT&T 등에서는), 패킷 하나를 보내고 그것이 송신자에게 되돌아올 때까지의 왕복에 걸리는 시간을 latency라고 부르기도 한다. latency는 한 지점에서 다른 지점 사이에 (지연시간이 전혀 없이) 데이터가 즉시 전송되어야만 하는 것으로 가정한다. 네트워크에서 latency를 일으키는 요인은 다음과 같다.

  • 전달 지연 : 이것은 단순히 하나의 패킷이 한 지점에서 다른 지점으로 광속으로 이동하는데 걸리는 시간이다.
  • 전송 지연 : (광케이블, 무선 또는 그 밖의 어떤 것이라도) 매체 그 차제에서 약간의 지연이 생긴다. 또 패킷의 크기에 따라서도 왕복하는데 지연이 생길 수 있는데, 그 이유는 패킷이 클수록 수신하고 반환하는데 시간이 더 걸리기 때문이다.
  • 라우터 및 기타 처리 지연 :  게이트웨이 노드들 시험하고, 또 어쩌면 패킷 내의 헤더를 변경 (예를 들어, TTL 필드 내에 있는  카운트의 값을 변경하는 등) 하는 데에도 시간이 걸린다.
  • 다른 컴퓨터 및 저장장치 지연 : 네트웍 내 행로 양단에서, 패킷은 스위치 브리지와 같은 중간 장비들에서 하드디스크와 같은 저장장치에 액세스하기 쉽다 (그러나백본 통계에서, 이러한 종류의 지연은 십중팔구 고려되지 않는다). 

 

2. 컴퓨터 시스템에서의 latency는 종종 응답시간을 늦추는 지연이나 대기를 의미하는데 사용된다. 컴퓨터 latency에 기여하는 명확한 요인들로는, 마이크로프로세서와 입출력장치들 간의 데이터 속도가 맞지 않거나, 데이터 버퍼링이 불충분한 것 등이 포함된다. 컴퓨터 내에서, latnecy는 prefeching이나 멀티 스레딩, 또는 다중 스레드의 실행에 걸친 병렬 처리의 사용 등

과 같은 기술에 의해 제거되거나 감추어질 수 있다.

 

3. 입체 시야와 머리 추적 장치 등이 제공되는 헬멧을 설명하는 3차원 모의실험에서, latency는 컴퓨터가 머리의 움직임을 감지하는 때부터 적절한 이미지가 나타나는데 까지 걸리는 시간을 말한다.

 

출처 : 텀즈

2010년 4월 10일 토요일

리눅스 사운드 프로그래밍

< 음악이 생겨라 (Let There Be Music) >

 

by Shuveb Hussain

한글 번역 전정호

이 글은 한글번역판을 요약한 것입니다.

 

*** 사운드 카드 프로그래밍 ***

 

 (1) 샘플링

  • 음을 녹음할 때 음질을 선택한다.
  • 음질을 결정하는 중요한 요소 중 하나가 샘플링 빈도(sampling rate)이다.
  • 음은 시간에 따라 진동수가 바뀌는 파장일 뿐이다.
  • 음을 녹음하려면 일정 간격으로 음의 진동수를 기록한다. 이 간격을 샘플링 빈도라고 한다.
  • 샘플링 빈도가 높을수록 음질이 좋아진다. 예를 들어, CD의 샘플링 빈도는 초당 44100번, 즉 44.1kHz이다.
  • PCM(Pulse Code Modulation, 펄스 코드 변조)이라고 하는 이 작업은 ADC(Analogue to Digital Converter, 아날로그-디지털 변환기)가 한다.

 

 

 (2) 비트와 채널

  • 음을 샘플링할 때, 샘플당 일정 수의 비트를 사용하고, 이런 채널을 여러 개 사용한다. 샘플링하는 자료의 비트 개수를 샘플링 정밀도(resolution)라고 한다.
  • 가장 흔한 형식은 8비트 양수 바이트 혹은 16비트이다.
  • 채널별로 자료를 분리한다. 예를 들어, CD 음악에는 왼쪽, 오른쪽(스테레오) 두 채널이 있다.
  • 8비트 정밀도로 CD음질을 녹음할 때 초당 필요한 크기를 계산해보면 :
  •        2        x       44100      =      88200 bytes
    (채널 개수) x (샘플링 빈도) = (초당 필요한 크기)

  • 이제 이론은 충분하니 실제 프로그램을 시작하자.

 

 

 (3) 사운드 카드를 프로그래밍 하기

  • 사운드 카드를 프로그래밍하는 방법이 몇가지 있다.
  •  초기 리눅스 드라이버가 만들어지던 때 두 그룹이 있었다.
    • Open Sound System(OSS)은 많은 장치 드라이버를 작성한 그룹으로 심지어 하드웨어 사양을 공개하지 않거나 비밀유지동의(non-disclusure agreement)를 하지않은 개발자에게 사양을 공개하지 않는 사운드 카드 제조사의 이진모듈도 포함하였다. 하드웨어 제조자가 개인에게 사양을 알려주려고하지 않았기 때문에 OSS는 4Front Technologies란 회사를 만들었다.
    • ALSA(Advanced Linux Sound Architecture)는 제조사가 사양을 공개한 사운드 카드 드라이버만 작성했다. ALSA는 2.6-test 커널에 포함되어 있다.
  • ALSA는 OSS 에뮬레이션 계층을 제공하기 때문에 OSS로 작성한 프로그램은 OSS와 ALSA 시스템에서 모두 동작한다. 간단하고 대다수의 시스템에 설치되어 있기 때문에 이 글은 OSS 프로그래밍을 다룰 것이다.

 

  • 유닉스/리눅스는 모든 장치 드라이버마다 (보통 /dev 디렉토리에) 파일 시스템 인터페이스가 있다. 이 장치파일을 open, read, write, lseek, close와 같은 파일관련 시스템 호출에 사용한다. 장치파일을 장치드라이버가 요청을 기다리는 파일시스템상의 훅(hook)이라고 보면 된다.예를 들어, /dev/hda1 파일은 primary master IDE 하드디스크의 첫번째 파티션에 대한 인터페이스이다. open 시스템호출을 사용하여 파일을 열면 일반파일과 같이 파일핸드(file handle)을 얻을 수 있다. 파일핸들을 읽으면 실제로 파티션의 첫번째 섹터에 있는 자료를 읽게 된다. 또, 앞으로 lseek하면 파일포인터(file pointer)를 앞으로 이동한다. 섹터를 건너뛰으려면 섹터 크기만큼 앞으로 lseek한다. 위험하므로 하드디스크 장치 파일을 수정하지는 마라. 파티션에 값을 쓰면 파티션이 망가질 수 있다. 하드웨어 장치는 보통 root만 직접 접근할 수 있다.

 (4) 코드

  • 이제 코드로 넘어가자. 이 코드는 root가 아니어도 문제없이 실행되야 한다. 파일장치를 접근하는데 문제가 있다면 root로 su하고 chmod하여 접근 권한을 푼다. 물론 리눅스에서 작동하는 사운드카드를 사용해야 한다. 직접 코드를 입력하지 않고 여기에서 다운받을 수 있다. demo.pcm 파일도 같이 다운받아야 한다.

 

/*
 * oss.c는 사운드카드에서 raw PCM 22KHz 샘플음을 낸다
 *
 * 중요 - 프로그램을 실행하기전에 현재 디렉토리에 demo.pcm 파일이 있는지 확인하라.
 */

#include < sys/types.h >
#include < sys/stat.h >
#include < sys/soundcard.h >
#include < sys/ioctl.h >
#include < unistd.h >
#include < fcntl.h >
#include < errno.h >
#include < stdlib.h >

#define SECONDS 5 //재생 시간 (초)

int main()
{
    int fd;
    int handle = -1;
    int channels = 1;         // 0=모노 1=스테레오
    int format = AFMT_U8;
    int rate = 22000;
    unsigned char* data;

   /* 사운드카드에 해당하는 파일에 쓰기위해(write) 파일을 연다(open). DSP = Digital Signal Processor */
    if ( (handle = open("/dev/dsp",O_WRONLY)) == -1 )
    {
  perror("open /dev/dsp");
  return -1;
    }

   /* 재생하려는 음이 스테레오라고 사운드카드에 알린다. 0=모노 1=스테레오 */
    if ( ioctl(handle, SNDCTL_DSP_STEREO,&channels) == -1 )
    {
  perror("ioctl stereo");
  return errno;
    }

    /* 자료 형식을 사운드카드에게 알린다 */
    if ( ioctl(handle, SNDCTL_DSP_SETFMT,&format) == -1 )
    {
  perror("ioctl format");
  return errno;
    }

    /* DSP 재생율(playback rate), 즉 raw PCM 음의 샘플링 빈도를 지정한다. */
    if (ioctl(handle, SNDCTL_DSP_SPEED,&rate) == -1 )
    {
  perror("ioctl sample rate");
  return errno;
    }

    // 빈도 * 5 초 * 두 채널
    data = malloc(rate*SECONDS*(channels+1));

    if((fd=open("demo.pcm",O_RDONLY))==-1)
    {
  perror("open file");
  exit(-1);
    }

    /* demo 파일에 저장된 정보를 읽어서 할당한 메모리에 저장한다 */
    read(fd,data,rate*SECONDS*(channels+1));
    close(fd);

    /* 읽은 내용을 사운드카드에 쓴다(write)! 그러면 재생이 된다. */
    write(handle, data, rate*SECONDS*(channels+1));

    if (ioctl(handle, SNDCTL_DSP_SYNC) == -1)
    {
  perror("ioctl sync");
  return errno;
     }

    free(data); //좋다. 마무리.
    close(handle);

    printf("===Done===\n");
    return 0;
}


 

(5) 코드 설명

  • 이 프로그램은 raw PCM, 22KHz, stereo 자료파일을 5초간 연주한다. 프로그램은 크게 3가지 작업을 한다.
    • sound 장치 열기(open)
    • 재생을 위한 파라미터 설정
    • 장치에 자료 쓰기(write)
  • open() / write() / close() 시스템 호출은 일반 파일과 동일하다.
  • ioctl()(Input/Output ConTroL) 시스템 호출을 사용하여 재생에 사용할 파라미터를 설정한다. ioctl() 시스템 호출은 입출력 장치와 통신하거나 파라미터를 설정할 때 사용한다. 또 시스템 호출의 개수를 줄이기 위한 편법으로 사용되기도 한다. 그래서 흔히 프로그래머의 다용도칼이라고 부른다. 함수의 원형
  • int ioctl( int fd, int command, ... );

    • fd : 장치의 파일 기술자(file descriptor)
    • command : 장치에 대한 요청/명령
    • ... : command에 따라 달라진다.
  • ioctl(handle, SNDCTL_DSP_SPEED, &rate)
    • DSP 재생을 설정한다. rate는 장치 드라이버로 전달되는 실제 재생율이다.
  • 예제 프로그램에는 3가지 ioctl()이 있다.
    • 재생에 사용할 채널 개수(channels)를 설정
    • PCM 형식(format)을 설정
    • 재생율(sampling rate)을 설정
  • 이것으로 장치에 필요한 정보는 충분하고, 다음은 장치파일에 PCM 자료를 직접 쓰면(write) 재생이 된다. 마지막 ioctl()은 장치를 비우고(flush), 그 다음 PCM 자료를 저장하기 위해 할당한 메모리를 해제한다. 이게 끝이다.

 

 

(6) 음악 저장 형식

  • 방금 전에 5초짜리 22KHz 음악을 재생하기 위해 raw PCM 자료 220KB가 필요했다.
    • 22,000 x  5  x   2    = 220,000 bytes
    • (샘플   x 초 x 채널 = 데이터 크기)
    • CD 음질로 1분을 재생하기 위해 필요한 크기는 :
      • 44,100 x 60 x 2 = 5292000 bytes, 약 5 MB!
  • 음악 CD는 raw PCM 형식으로 자료를 저장한다. 그러나 컴퓨터는 음악을 효율적으로 저장하고 (인터넷으로) 전송하기 위해 음악을 압축하여 크기를 줄이고 재생시 다시 압축을 푼다. 어떤 음악이던 관계없이 샘플링률은 고정되어 있다. 아무 소리가 없는 몇 초간을 샘플링 했다고 생각해 보자. 같은 시간의 시끄러운 락 음악과 동일한 크기가 필요하다.
  • raw 음악파일은 자료반복이 매우 적기 때문에 일반적인 압축방법으로는 잘 압축되지 않는다. 음악은 다른 기술을 사용하여 압축한다. 가장 일반적인 방법은 사림이 귀로 들을 수 없는 부분을 제거하거나 음악 특성에 따라 압축한다. 음악을 좋아하는 사람들에게 가장 대중적인 형식은 분명 MP3다. 현재 MP3에는 특허문제가 걸려 있기 때문에, 오픈소스 공동체에서는 Ogg Vorbis 형식을 반긴다. 두 형식 모두 크기가 비슷하게 줄어들며 음질의 손실을 최소화한다.

 

 

 (7) Ogg Vorbis 파일을 재생하는 방법

  • 사운드 카드가 어떻게 raw 음악 자료를 재생하는지 알았으니, Ogg Vorbis 파일을 재생하는 방법을 알아보자. Ogg Vorbis 파일을 재생하려면 먼저 복호화(decode), 즉 raw PCM 자료로 변환해야 한다.
  • libvorbisfile이 이 작업을 한다. 이 라이브러리는 매우 낮은 수준을 다루지만 더 세밀한 조절이 가능한 libvorbis 라이브러리보다 높은 수준에서 변환을 한다. 이제 문제가 간단해진다 : Ogg Vorbis 파일에서 읽은 자료를 라이브러리로 넘기고, 라이브러리가 변환된 raw PCM 자료를 사운드 카드로 직접 보낸다. 소스는 여기에
  • #include < sys/types.h >
    #include < sys/stat.h >
    #include < sys/soundcard.h >
    #include < sys/ioctl.h >
    #include < unistd.h >
    #include < fcntl.h >
    #include < errno.h >
    #include < stdlib.h >

    #include "vorbis/codec.h"
    #include "vorbisfile.h"

    int setup_dsp(int fd,int rate, int channels);

    char pcmout[4096]; // 변환한 PCM 자료를 저장할 4KB 버퍼
    int dev_fd;

    int main(int argc, char **argv)
    {
     OggVorbis_File vf;
     int eof=0;
     int current_section;
     FILE *infile,*outfile;

     if(argc<2)
     {
      printf("supply file arguement");
      exit(0);
     }

     if ( (dev_fd = open("/dev/dsp",O_WRONLY)) == -1 )
    {
      perror("open /dev/dsp");
      return -1;
     }

     infile=fopen(argv[1],"r");

     if(infile==NULL)
     {
      perror("fopen");
      exit(-1);
     }  

    if(ov_open(infile, &vf, NULL, 0) < 0)
    {
      fprintf(stderr,"Input does not appear to be an Ogg bitstream.");
      exit(1);
     }

     char **ptr=ov_comment(&vf,-1)->user_comments;
     vorbis_info *vi=ov_info(&vf,-1);

     while(*ptr)
     {
      fprintf(stderr,"%s",*ptr);
      ++ptr;
     }

     fprintf(stderr,"Bitstream is %d channel, %ldHz",vi->channels,vi->rate);
     fprintf(stderr,"Decoded length: %ld samples",(long)ov_pcm_total(&vf,-1));
     fprintf(stderr,"Encoded by: %s",ov_comment(&vf,-1)->vendor);

     if(setup_dsp(dev_fd,vi->rate,vi->channels-1))
     {
      printf("dsp setup error.aborting");
      exit(-1);
     }

     int count=0;

     while(!eof)
     {
          long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,&current_section);
          if (ret == 0)
          {
        /* EOF */
      eof=1;
          }
          else if (ret < 0)
          {
            /* 자료에 오류가 있다.  (프로그램에) 중요하다면 보고하지만,
      이 프로그램은 하지 않는다. */
           }
          else   {
      printf("Writing %d bytes for the %d time.",ret,++count);
      write(dev_fd,pcmout,ret);
          }
     }

     ov_clear(&vf);
     fclose(infile);
     
    if (ioctl(dev_fd, SNDCTL_DSP_SYNC) == -1)
    {
          perror("ioctl sync");
      return errno;
     }

     close(dev_fd);
     fprintf(stderr,"Done.");

     return(0);
    }


    int setup_dsp(int handle,int rate, int channels)
    {
        int format;

        if ( ioctl(handle, SNDCTL_DSP_STEREO,&channels) == -1 )
        {
      perror("ioctl stereo");
      return errno;
        }

         format=AFMT_U8;

         if ( ioctl(handle, SNDCTL_DSP_SETFMT,&format) == -1 )
        {
      perror("ioctl format");
      return errno;
        }
     
        if ( ioctl(handle, SNDCTL_DSP_SPEED,&rate) == -1 )
       {
      perror("ioctl sample rate");
      return errno;
        }

         return 0;
    }

 

  • 다음과 같이 컴파일 한다.
  • gcc oggplay.c -oggplay -lvorbisfile -I/path/to/vorbis/header/files -L/path/to/vorbis/lib/files

  • 라이브러리파일과 헤더파일이 /usr/lib 이나 /usr/include 같은 일반적인 위치에 있다면 -l 과 -L 명령행 옵션이 필요없다. 모든 대중적인 배포본에 vorbisfile 라이브러리가 포함되있다. 만약 시스템에 설치가 안되있다면 여기에서 다운받을 수 있다. 또, Ogg Vorbis 사이트는 여기다. 프로그램을 컴파일하려면 (개발용) 헤더파일이 필요하다.

  • setup_dsp 함수는 dsp 장치를 열고(open), 세가지 중요한 파라미터인 채널, 형식, 재생율을 지정한다. 음악 재생을 위해 가장 중요한 세가지 파라미터를 기억하라. main 함수는 오류검사외에, 쉘 아규먼트로 준 Ogg Vorbis 파일을 열고, 파일에 저장된 설명과 파일정보를 출력한다. ov_open() 라이브러리함수가 채우는 구조체에 저장된 샘플링 빈도와 채널 정보를 setup_dsp 함수에 넘긴다. 그후 프로그램은 Ogg Vorbis 파일 내용을 변환하여 버퍼에 넣는 반복문을 실행한다. 반복문은 버퍼에 저장한 raw PCM 자료를 앞에서 설정한 dsp 장치에 쓴다. 파일이 끝날때까지 반복한 후, 마지막으로 정리하고 종료한다. 간단하지 않는가? 쉽고 직관적으로 변환해준 libvorbisfile에게 감사하다.
  • Ogg Vorbis 파일을 변환하려면 libvorbisfile을 사용하면 된다. MP3 파일을 변환하여 재생하고 싶다면 여러 라이브러리를 선택할 수 있다. 많이 사용하는 라이브러리중에 영상과 음악을 모두 변환할 수 있는 smpeg 라이브러리가 있다. 또, libmad 라이브러리도 찾았다. 나는 smpeg의 음악 변환 기능만 사용하기로 했다. 관심이 있다면 smpeg의 MPEG 영상 변환 기능도 살펴보길 바란다. 라이브러리 사용법을 설명하는 샘플 프로그램 plaympeg도 포함되있다. 영상을 보여주기위해 smpeg은 매우 사용하기 쉽고 기능이 많은 그래픽 프로그래밍 라이브러리인 SDL을 사용한다. 이외에도 MP3를 변환하는 라이브러리는 많지만, 많은 리눅스 배포본에 smpeg이 포함되있기때문에 smpeg을 선택했다. 많이 사용하는 gtv MPEG 영상플레이어도 smpeg 패키지에 포함되있다.

 

 (8) MP3 파일 연주하는 프로그램 예제

  • smpeg 라이브러리가 변환한 MP3 자료를 직접 사운드 카드로 보낸다. 직접 PCM을 다룰 필요가 없다. 소스 다운로드
  • #include < stdio.h >
    #include < stdlib.h >
    #include < string.h >
    #include < signal.h >
    #include < unistd.h >
    #include < errno.h >
    #include < sys/types.h >
    #include < sys/stat.h >
    #include < sys/ioctl.h >
    #include < sys/time.h >

    #include "smpeg.h"

    void usage(char *argv0)
    {
        printf("Hi,%s This is the normal useage.",argv0);
    }

    int main(int argc, char *argv[])
    {

        int volume;
        SMPEG *mpeg;
        SMPEG_Info info;
       
        volume = 100; //Volume level

        /* 아규먼트가 없으면 사용법만 출력한다 */
        if (argc == 1)
        {
             usage(argv[0]);
             return(0);
        }

        mpeg = SMPEG_new(argv[1], &info;, 1);

        if ( SMPEG_error(mpeg) )
        {
                fprintf(stderr, "%s: %s", argv[1], SMPEG_error(mpeg));
                SMPEG_delete(mpeg);
        }

        SMPEG_enableaudio(mpeg, 1);
       SMPEG_setvolume(mpeg, volume);

        /* 음악에 대한 정보를 출력한다 */
        if ( info.has_audio )
        {
                printf("%s: MPEG audio stream", argv[1]);
         
                if ( info.has_audio )
                    printf("Audio %s", info.audio_string);

                 if ( info.total_size )
      printf("Size: %d", info.total_size);
             

                  if ( info.total_time )
      printf("Total time: %f", info.total_time);

                   /* 재생하고 재생이 끌날때까지 기다린다 */
      SMPEG_play(mpeg);  

      while(SMPEG_status(mpeg)==SMPEG_PLAYING);

            SMPEG_delete(mpeg); //구조체 반환
       }

       return(0);
    }

  • 여기에 있는 smpeg을 설치한후 프로그램을 컴파일한다. smpeg을 설치하기위해서 미리 SDL을 설치해야 한다. 컴파일할때 헤더파일과 라이브러리파일 경로를 컴파일러에게 알려줘야 한다. 쉽게 하려고 smpeg 패키지는 smpeg-config라는 간단한 도구를 제공한다. 다음과 같이 프로그램을 컴파일한다:
  • gcc playmp3.c `smpeg-config --cflags --libs` -I/usr/include/SDL

  • smpeg-config 명령어를 감싸는 따옴표문자를 주의하라. 보통 backqoute라고 부르며, US식 키보드에서 틸데(~) 문자와 같이 있다. 쉘에서 이 문자는 안에 있는 명령어의 출력을 그 자리에 대신한다. 그냥 smpeg-config 명령만 실행해보면 내가 무슨 말을 하는지 알 것이다. -I/usr/include/SDL 명령행 옵션을 -I < 실제 SDL 경로 >로 수정하라. SDL 함수를 사용하지 않아도, smpeg.h가 내부적으로 SDL 헤더파일을 사용하므로 SDL 헤더파일 경로를 지정해야 한다. RPM 사용자는 프로그램을 컴파일하기위해 smpeg과 smpeg-devel 패키지를 설치해야 한다.
  • SMPEG_new 라이브러리함수는 필요한 내부 객체를 할당하고, MP3 파일에 대한 정보를 SMPEG_info 구조체에 채운다. 프로그램은 이 정보를 출력하고, SMPEG_play를 호출하여 재생을 시작한다. 함수는 즉시 반환되기때문에 다른 작업을 하면서 MP3를 연주하는 프로그램에 유용하다. 이 프로그램에서는 따로 할 일이 없기때문에 재생이 끝날 때까지 기다린다. SMPEG_delete는 그동안 라이브러리가 할당한 모든 메모리를 반환하고, 마친다

 

 글이 여러분의 프로그래밍 작업에 조금이나마 도움이 되길 바란다. 의견을 듣고 싶다. 잘못된 점을 알려주거나 제안을 바란다. shuveb@shuvebhussain.org로 내게 연락할 수 있다.

 

참고로 테스트를 해봤는데 PCM RAW파일로만 가능한다. ^^ 형식이 그렇네. mp3나 다른 형식의 파일을 받아서 cool edit로 변환해 주었다. 쿠울~~~ 에디터 ㄱㄱ 그리고 역시나 속도 그런거 잘 맞춰줘야 한다는 ^^

 

출처 : http://www.whiterabbitpress.com/lg/issue97tag/shuveb.html

 

출처 : 한국어 출처, 원문(영어)